pax_global_header00006660000000000000000000000064134316014110014504gustar00rootroot0000000000000052 comment=83e199132496a90e7d075f0eb1502450394c2a8a runawk-runawk-1.6.1/000077500000000000000000000000001343160141100143255ustar00rootroot00000000000000runawk-runawk-1.6.1/Makefile000066400000000000000000000013561343160141100157720ustar00rootroot00000000000000################################################## SUBPRJ = runawk:test modules examples a_getopt doc SUBPRJ_DFLT ?= runawk modules WITH_ALT_GETOPT ?= yes .if ${WITH_ALT_GETOPT:tl} == "yes" SUBPRJ_DFLT += a_getopt .endif MKC_REQD = 0.26.0 ################################################## # "cleandir" also removes temporary files of regression tests cleandir: cleandir-test # Avoid running test-runawk, test-modules etc. test: all-test @: # Also implement test_all test_all: test_all-test # We use "target "manpages" for making a distribution tarball TARGETS += _manpages # _manpages is a new recursive target DIST_TARGETS = manpages manpages: _manpages rm ${MKC_CACHEDIR}/_mkc* .include "Makefile.inc" .include runawk-runawk-1.6.1/Makefile.inc000066400000000000000000000002611343160141100165340ustar00rootroot00000000000000VERSION = 1.6.1 BIRTHDATE = 2007-09-24 EGDIR ?= ${DATADIR}/doc/runawk/examples MODULESDIR ?= ${DATADIR}/runawk DOCDIR ?= ${DATADIR}/doc/runawk TARGETS += test_all runawk-runawk-1.6.1/README000066400000000000000000000105221343160141100152050ustar00rootroot00000000000000====================================================================== runawk: small wrapper for AWK interpreter that impements modules system and helps one to write the standalone AWK programs. author: Aleksey Cheusov project's home page: http://sourceforge.net/projects/runawk licence: MIT license ====================================================================== MOTIVATION See section MOTIVATION of runawk.1 or runawk.pod. ====================================================================== INSTALLATION See INSTALL file. ====================================================================== MODULES RunAWK provides lots of AWK modules ready for use. All of them are under modules/ subdirectory. They are installed by default. abort.awk, alt_assert.awk - power abort() and assert() alt_join.awk - join :-) braceexpand.awk - awk equivalent to shell's braceexpand functionality basename.awk, dirname.awk - equivalents to basename(1) and dirname(1) embed_str.awk - reads strings from AWK code exitnow.awk - has_prefix.awk, has_suffix.awk - trivial string functions match_br.awk - find pair closed brackets in a string max.awk, min.awk, isnum.awk, abs.awk - trivial math functions modinfo.awk - routines to get an information about modules that are in use multisub.awk - another replacement functions pow.awk - synonym for ^ init_getopt.awk, alt_getopt.awk, power_getopt.awk - POSIX/SUS compatible routines for handling options EASILY ;-) readfile.awk - read an entire file into variable runcmd.awk - safe wrapper over system() shquote.awk - escapes shell's special characters heapsort.awk, quicksort.awk, sort.awk - sorting functions str2regexp.awk - string to regexp routines tokenre.awk - alternative mechanism for separating input into tokens xclose.awk, xgetline.awk, xsystem.awk - functions to write robust programs tmpfile.awk - generates names of automatically deleted tempfiles fieldwidths.awk - portable equivalent of GNU awk's FIELDWIDTHS ;-) CR_in.awk - removes CR symbols from input lines. trim.awk - functions for trimming spaces from the string. trim_in.awk - trims spaces from input lines. backslash_in.awk - treats backslash symbol at the end of line as "this line will continue on the next one". ini.awk - functions for reading Win .ini files. ftrans_in.awk - handle data file transitions ord.awk - character to id and id to character convertors ====================================================================== SCRIPTS RunAWK also provides a few scripts: alt_getopt - program arguments parser aware of long options, alternative to POSIX getopts and getopt(1). In addition to alt_getopt(1) utility alt_getopt.sh shell library is also provided that provides an alternative way for handling options. alt_getopt.sh - shell library functionally equivalent to alt_getopt(1) ====================================================================== EXAMPLES Lots of examples are available in examples/ subdirectory. ====================================================================== PACKAGES 1) NetBSD, DragonFlyBSD, Linux, Solaris... (pkgsrc) RunAWK is packaged in pkgsrc as wip/runawk. 2) FreeBSD RunAWK is packaged in FreeBSD ports as lang/runawk 3) Debian/lenny/x86 Add the following lines deb http://mova.org/~cheusov/pub/debian lenny main deb-src http://mova.org/~cheusov/pub/debian lenny main to /etc/apt/sources.list and then using apt or aptitude commands. Binary packages are available only for Debian/Lenny/i386. Ubuntu users need to recompile the package for their system. runawk-runawk-1.6.1/a_getopt/000077500000000000000000000000001343160141100161275ustar00rootroot00000000000000runawk-runawk-1.6.1/a_getopt/Makefile000066400000000000000000000002451343160141100175700ustar00rootroot00000000000000SCRIPTS += alt_getopt MAN += alt_getopt.1 FILES += alt_getopt.sh CLEANFILES = alt_getopt.1 .PHONY: _manpages _manpages: ${MAN} .include runawk-runawk-1.6.1/a_getopt/alt_getopt000077500000000000000000000070661343160141100202300ustar00rootroot00000000000000#!/usr/bin/env runawk # Copyright (c) 2010 Aleksey Cheusov # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #use "alt_assert.awk" #use "alt_getopt.awk" #use "shquote.awk" #use "embed_str.awk" #env "LC_ALL=C" #.begin-str help # alt_getopt is a command options parser, it gets options # specification and application's options as arguments and outputs # shell commands to be executed. # Usage: # alt_getopt -h # alt_getopt [OPTIONS] opt1 sh_cmd1 [opt2 sh_cmd2...] -- [args] # OPTIONS: # -h|--help display this screen # -c do not output 'shift' command, variable # __shifts_cnt is assigned instead #.end-str function __takes_arg (opt){ if (!opt in __getopt_opts) return 0 if (__getopt_opts [opt] == takes_arg) return 1 if (__getopt_opts [opt] == "") return 0 return __getopt_opts [__getopt_opts [opt]] == takes_arg } BEGIN { start = 1 if (ARGV [1] == "-h" || ARGV [1] == "--help"){ print EMBED_STR ["help"] > "/dev/stderr" exitnow(0) } if (ARGV [1] == "-c"){ delete ARGV [1] ++start output_shift_cnt = 1 } for (i=start; i < ARGC; i += 2){ if (ARGV [i] == "--"){ delete ARGV [i] ++i break } if (ARGV [i] == "" || ARGV [i+1] == ""){ print "bad arguments, see alt_getopt -h for more information" \ > "/dev/stderr" } if (ARGV [i] ~ /^[A-Za-z0-9!@%^=+\/,.]$/){ shopts = shopts ARGV [i] action [ARGV [i]] = ARGV [i+1] }else if (ARGV [i] ~ /^=[A-Za-z0-9!@%^=+\/,.]$/){ opt = substr(ARGV [i], 2) shopts = shopts opt ":" action [opt] = ARGV [i+1] }else if (ARGV [i] ~ /^[A-Za-z0-9!@%^=+\/,.][ |][^ |]+$/){ split(ARGV [i], arr, /[ |]/) shopts = shopts arr [1] long_opts [arr [2]] = arr [1] action [arr [1]] = ARGV [i+1] }else if (ARGV [i] ~ /^=[A-Za-z0-9!@%^=+\/,.][ |][^ |]+$/){ split(substr(ARGV [i], 2), arr, /[ |]/) shopts = shopts arr [1] ":" long_opts [arr [2]] = arr [1] action [arr [1]] = ARGV [i+1] }else if (ARGV [i] ~ /^[^=][^ |]*$/){ long_opts [ARGV [i]] = "" action [ARGV [i]] = ARGV [i+1] }else if (ARGV [i] ~ /^=[^ |]+$/){ opt = substr(ARGV [i], 2) long_opts [opt] = takes_arg action [opt] = ARGV [i+1] }else{ abort("unknown format of'" ARGV [i] "'") } delete ARGV [i] delete ARGV [i+1] } first = i while (getopt(shopts, 1)){ if (__takes_arg(optopt)) print action [optopt] shquote(optarg) else print action [optopt] } shifts_cnt = 0 for (i=first; i < ARGC; ++i){ if (ARGV [i] == "") ++shifts_cnt } if (output_shift_cnt) print "shifts=" shifts_cnt else print "shift", shifts_cnt exitnow(0) } runawk-runawk-1.6.1/a_getopt/alt_getopt.pod000066400000000000000000000034121343160141100207750ustar00rootroot00000000000000=head1 NAME alt_getopt - parse command options =head1 SYNOPSIS cmds=`alt_getopt opt1 action1 [opt2 action2...] -- "$@"` eval "$cmds" =head1 DESCRIPTION B is a command options parser. It conforms to POSIX and supports long options, that is works the same way as getopt_long(3) found in *BSD and GNU libc. =head1 EXAMPLES The following shell script accepts the options: -v (or --verbose), -h (or --help), long option --fake without short synonym, --len accepting argument, -o (or --output) accepting argument, short options -f and -F without long synonyms etc. If option is applied, appropriate shell command is executed. #!/bin/sh help () { echo 'help here'; } process_args (){ alt_getopt \ 'v|verbose' 'verbose=1' \ 'h help' help \ 'fake' fake_flag=1 \ '=len' len= \ '=o output' output= \ '=m msg' "msg=" \ 'V version' "echo 'alt_getopt-0-1-0'" \ f 'flag=1' \ F 'flag=' \ =n number= \ -- "$@" } cmds=`process_args "$@"` eval "$cmds" echo "flag=$flag" echo "msg=$msg" ... Another way to handle options using alt_getopt.sh #!/bin/sh . alt_getopt.sh help () { cat 1>&2 < =head1 SEE ALSO L L runawk-runawk-1.6.1/a_getopt/alt_getopt.sh000077500000000000000000000012271343160141100206320ustar00rootroot00000000000000# -*- mode: sh; -*- __nl=' ' __shq (){ __cmd=`printf '%s\n' "$1" | sed "s|'|'\\\\\''|g"` printf "%s\n" "'$__cmd'" } add_arg (){ if test $# -ne 2 -a $# -ne 3; then echo 'add_arg function requires either 2 or three arguments' 1>&2 exit 10 fi if test $# -eq 3; then help_msg="${help_msg}$3$__nl" fi __i=`__shq "$1"` __args="$__args $__i" __i=`__shq "$2"` __args="$__args $__i" } __run_alt_getopt (){ eval "alt_getopt $__args" "$@" } process_args (){ __args="$__args --" for i in "$@"; do __i=`__shq "$1"` __args="$__args $__i" shift done __cmds=`eval alt_getopt -c $__args` eval "$__cmds" } runawk-runawk-1.6.1/doc/000077500000000000000000000000001343160141100150725ustar00rootroot00000000000000runawk-runawk-1.6.1/doc/INSTALL000066400000000000000000000062631343160141100161320ustar00rootroot00000000000000====================================================================== INSTALLATION 0) Maybe runawk is already packaged for your platform. See PACKAGES section below and your system's packages management tools. 1) We need bmake (portable version of NetBSD make) for building runawk. I'd recommend to use latest stable version of bmake. http://crufty.net/help/sjg/bmake.html http://freshmeat.net/projects/bmake/ <<<***!!! GNU make IS NOT GOOD !!!***>>> 2) We also need mk-configure >= 0.21.0. http://sourceforge.net/projects/mk-configure/ 3) Uncompress tarball you've downloaded like this gzip -dc runawk-X-Y-Z.tar.gz | tar -xf- 2) cd runawk-X.Y.Z 3) mkcmake 4) mkcmake test If this step fails on your system, PLEASE LET ME KNOW. 5) mkcmake install There is a lot of Makefile variables that can be changed during build and installation. MODULESDIR - directory where modules are installed to [${PREFIX}/share/runawk] AWK_PROG - path to the default AWK interpreter STDIN_FILENAME - path to stdin device file [-] PREFIX - where runawk(1) is installed to MANDIR - root directory for manual pages DESTDIR - fake root for installation CPPFLAGS CFLAGS LDFLAGS LDADD ... See mk-configure(7) for details. 6) RunAWK distribution consists of the following subprojects: - runawk -- runawk executable - modules -- modules written in .awk - doc -- README, COPYRIGHT, NEW, TODO files - examples -- samples of use for runawk and its modules - a_getopt -- alt_getopt(1) and alt_getopt.sh By default only "runawk", "modules" and "a_getopt" are built and installed. However you can easily build and install any subproject like the following mkcmake all-examples install-examples mkcmake all-doc install-doc etc. See mk-configure(7) and ./Makefile for details. You can also set subprojects you need in SUBPRJ_DFLT variable. export SUBPRJ_DFLT='runawk modules examples a_getopt doc' mkcmake all install 7) Non-standard variable you may want to change. EGDIR - directiory where examples/ will be installed to ($PREFIX/share/doc/runawk/examples) MODULESDIR - directory where modules/ will be installed to ($PREFIX/share/runawk) DOCDIR - directory where doc/ will be installed to ($PREFIX/share/doc/runawk) AWK_PROG - path to the default AWK interpreter (/usr/bin/awk) STDIN_FILENAME - path to stdin device file (-) ------------------------------ Examples of building and installing: 0) mkcmake all install 1) export PREFIX=/usr SYSCONFDIR=/etc; \ mkcmake all install DESTDIR=/tmp/fakeroot 2) export PREFIX=/usr SYSCONFDIR=/etc export SUBPRJ_DFLT='runawk modules a_getopt examples doc' export AWK_PROG=/bin/awk mkcmake all install DESTDIR=/tmp/fakeroot 3) env CC='icc -no-gcc' \ PREFIX=/home/cheusov/local \ CPPFLAGS=-I/usr/pkg/include \ LDFLAGS='-L/usr/pkg/lib -Wl,-rpath -Wl,/usr/pkg/lib' \ LDADD=-lextralib \ CFLAGS='-O2 -fomit-frame-pointers' \ mkcmake -s all install runawk-runawk-1.6.1/doc/LICENSE000066400000000000000000000020661343160141100161030ustar00rootroot00000000000000Copyright (c) 2007-2014 Aleksey Cheusov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. runawk-runawk-1.6.1/doc/Makefile000066400000000000000000000001231343160141100165260ustar00rootroot00000000000000FILES = LICENSE NEWS ../README TODO FILESDIR = ${DOCDIR} .include runawk-runawk-1.6.1/doc/NEWS000066400000000000000000000672541343160141100156070ustar00rootroot00000000000000====================================================================== Version 1.6.1, by Aleksey Cheusov, Fri, 15 Feb 2019 21:19:26 +0300 Fix in regression test (broken Solaris shell) Sort .awk files locale-independently to get reproducible build ====================================================================== Version 1.6.0, by Aleksey Cheusov, Fri, 26 Dec 2014 12:34:12 +0300 Environment variable RUNAWK_KEEPTMP was introduced. If it set, temporary files are kept. This is useful for debugging. io.awk:file_size was fixed (its behaviour depended on FS value) AWK_PROGS used for testing is now settable from environment. A few typos in runawk_modules.3 were fixed. Thanks to Andrew Shadura! ====================================================================== Version 1.5.1, by Aleksey Cheusov, Sat, 28 Jun 2014 18:00:25 +0300 Compilation failure on Hurd was fixed. mk-configure >= 0.26.0 is required for build. ====================================================================== Version 1.5.0, by Aleksey Cheusov, Sun, 8 Sep 2013 12:10:47 +0300 Options -i, -I and all long options were completely removed. Option -T was added. For details see the man page. Option -v is documented in manpage. Fixes for gcc compilation warnings. Fixes for compilation with non-empty MAKEOBJDIR. Typo fixes in NEW, runcmd.awk and man pages. ====================================================================== Version 1.4.4, by Aleksey Cheusov, Sat, 10 Nov 2012 13:57:35 +0300 Fix for bug in removing subdirs in temporary directory. Improvements and bug fix in runawk_modules.3 ====================================================================== Version 1.4.3, by Aleksey Cheusov, Sun, 9 Sep 2012 21:54:21 +0300 runawk: - Clean-ups in usage message - system(3) is not used anymore for removing temporary directory modules: - Function print_help() has been moved from power_getopt.awk to init_getopt.awk ====================================================================== Version 1.4.2, by Aleksey Cheusov, Sun, 19 Aug 2012 23:00:39 +0300 runawk_modules.3 was added where all modules are documented Long options are considered deprecated -i and -I options were removed man pages are included to a distribution tarball, so pod2man is not needed for building ====================================================================== Version 1.4.1, by Aleksey Cheusov, Sun, 22 Jul 2012 14:57:19 +0300 Minor fixes in documentation Path to AWK interpreter is detected at build time (not hardcoded /usr/bin/awk). This fixes runawk on, for example, Haiku. Clean-ups in build system. mk-configure-0.23.0 is required. ====================================================================== Version 1.4.0, by Aleksey Cheusov, Sun, 27 Nov 2011 21:41:09 +0300 exitnow.awk: - Fix: exitnow(status) finishes the execution of the script without running END sections even if status == 0. New module io.awk that includes the following functions: is_{file,dir,exec,socket,fifo,blockdev,chardev,symlink}, file_size and file_type. tokenre.awk: - Function splitre0() was added that splits $0 More regression tests were added. ====================================================================== Version 1.3.2, by Aleksey Cheusov, Sun, 9 Oct 2011 14:11:32 +0300 Internal arrays are relocated automatically. This fixes use of runawk(1) in combination with xargs(1), e.g. cat files.txt | xargs runawk -e '...' ====================================================================== Version 1.3.1, by Aleksey Cheusov, Fri, 7 Jan 2011 16:45:30 +0200 runawk.1 and alt_getopt.1 are included to tarball, so pod2man is not needed for installation. No functional changes in source code. ====================================================================== Version 1.3.0, by Aleksey Cheusov, Tue, 4 Jan 2011 20:14:04 +0200 fix in runawk.c for warning message produced by Intel C compiler. fix for shquote("") from modules/shquote.awk. Source code is reorganized and it is easy to install examples, modules, alt_getopt, runawk executable and TODO/README/... files individually. See doc/INSTALL for details. mk-configure >= 0.21 is required ====================================================================== Version 1.2.0, by Aleksey Cheusov, Sat, 23 Oct 2010 00:35:35 +0300 Due to incompatibilities between traditional BSD mk files and mk files shipped with bmake by Simon J. Gerraty, I've decided to switch runawk from BSD mk files to mk-configure software build system. This makes Makefile significantly smaller, easier to understand and use and gives tons of new capabilities. Obviously this makes development even easier than before. Updated installation instruction is in README. New functions in heapsort.awk: "heapsort_fields" and "heapsort0" for sorting $1, $2 ... New function in tokenre.awk: "splitre". New samples of use (regression tests): examples/demo_tokenre4, demo_heapsort4. ====================================================================== Version 1.1.0, by Aleksey Cheusov, Wed, 6 Oct 2010 22:51:56 +0300 Makefile: - initialize {BIN,MAN}{OWN,GRP} to `id -{u,g}n`. You don't need to set these variables manually for unprivileged installation. Option -F is added to runawk. It passes field separator to AWK interpreter. New tool alt_getopt(1), an alternative to getopt(1) and POSIX shell's getopts. alt_getopt is a command options parser that undestands long options. It is implemented in runawk and uses its modules. Also alt_getopt.sh shell include file is implemented and installed. Examples: examples/demo_alt_getopt*.sh multisub.awk: ability to skip a matched text is added, see the documentation at the top of multisub.awk and examples/demo_multisub for the sample. Function multisub now has optional third argument. New module glob.awk for working with glob patterns. See examples/demo_glob* for the samples. min.awk: new functions min3, min4, min5, min_key, min_value and key_of_min_value max.awk: new functions max3, max4, max5, max_key, max_value and key_of_max_value New module ord.awk from GNU awk. New module ftrans_in.awk from GNU awk (fixed and modified by me). Example: examples/demo_ftrans. New example: examples/demo_tokenre3. Thanks to Vlad Shakhov for the idea. New example: examples/demo_minmax. ====================================================================== Version 1.0.0, by Aleksey Cheusov, Sun, 5 Sep 2010 16:39:47 +0300 New functions for sorting indices in hash heapsort.awk: heapsort_indices quicksort.awk: quicksort_indices sort.awk: sort_indices New module ini.awk for reading .ini files. ====================================================================== Version 0.21.0, by Aleksey Cheusov, Sun, 28 Mar 2010 13:43:48 +0300 fixed: compilation failure on recent Linux-es (warn_unused_result attribute of system(3) function in recent glibc). fixed: compilation failures on FreeBSD ("assignment discards qualifiers from pointer target type" warning which is critical with -Werror). fixed: compilation failure with Intel C Compiler Now one can pass arguments to awk program specified with -e option after --, that is like the following runawk -e '' -- New simple modules: - trim.awk: this modules provides a set of simple functions for trimming spaces from the string. - backslash_in.awk treats backslash symbol at the end of input line as "this line will continue on the next line". $ cat ~/tmp/9.txt Some text here \ and here too. \ This is still the first line. This is the second. And this is third one that\ continues on the next line \ and the next line too. Ok, we finally have four lines of text. $ runawk -f backslash_in.awk -e '{print}' ~/tmp/9.txt Some text here and here too. This is still the first line. This is the second. And this is third one that continues on the next line and the next line too. Ok, we finally have four lines of text. $ - trim_in.awk trims spaces from input lines. - CR_in.awk removes CR symbols from input lines. ====================================================================== Version 0.20.0, by Aleksey Cheusov, Thu, 4 Mar 2010 18:33:03 +0200 New module: fieldwidths.awk: By default AWK interpreter splits input lines into tokens according to regular expression that defines "spaces" between them using special variable FS. Sometimes it is useful to define a fixed-size fields for tokens. This is what this module is for. The functionality of fieldwidths.awk is very close to GNU awk's FIELDWIDTHS variable but is available for all flavours of AWK ;-) New module: tmpfile.awk: This module provides a function `tmpfile' for generating temporary filenames. All these filenames are under temporary directory created (if necessary) by runawk(1) which is removed automatically during normal exit or when runawk(1) reveives SIGINT, SIGQUIT, SIGTERM, SIGHUP or SIGPIPE. Thus, this module provides a safe way to work with temporary files. new runawk directive: #interp-var that specifies an environment variable name that keeps a preferred AWK interpreter. See a manual page for details. new runawk directive: #safe-use that #use module if it exists. Example is below. For more details see a manual page. foobar application: #!/usr/bin/env runawk #safe-use "~/.foobarrc" "/etc/foobar.conf" BEGIN { print foo, bar, baz } config file ~/.foobarrc for foobar application: BEGIN { foo = "foo10" bar = "bar20" baz = 123 } fix in power_getopt.awk: arguments equal to "" (empty string) are now processed correctly. power_getopt.awk: after options processing ARGV [1], ARGV [2], ..., ARGV [ARGC-1] are set to non-option arguments. new in heapsort.awk: functions sift_down and sift_up. fix in tokenre.awk: There is no need to initialize TRE variable, it is already initialized to "" at startup. This fixes a problem with 'runawk -v TRE=lalala ...' Minor fixes and rewords in the runawk.1 and README. ====================================================================== Version 0.19.0, by Aleksey Cheusov, Sun, 3 Jan 2010 15:23:31 +0200 fix in runawk.c: \n was missed in "running '%s' failed: %s" error message. The problem was seen on ancient (12 years old) HP-UX fix in teets/test.mk: "diff -u" is not portable (SunOS, HP-UX), DIFF_PROG variable is introduced to fix the problem fix in modules/power_getopt.awk: after printing help message we should exit immediately not running END section, s/exit/exitnow/ new function heapsort_values in heapsort.awk module new function quicksort_values in quicksort.awk module new function sort_values in sort.awk module ====================================================================== Version 0.18.0, by Aleksey Cheusov, Sat, 7 Nov 2009 17:08:16 +0200 Makefile: !!! "install-dirs" target has been renamed to "installdirs" !!! - At compile time MODULESDIR can contain a *list* of colon-separated directories, e.g. /usr/local/share/runawk:/usr/local/share/awk - power_getopt.awk, alt_getopt.awk and init_getopt.awk: - Support for multiply applied options, e.g. -vvv for increasing verbosity level. If option without arguments is multiply applied, getarg() function returns a number of times it was applied, not just 0 or 1. New modules: - init_getopt.awk using alt_getopt.awk and used by power_getopt.awk. Its goal is to initialize `long_opts' and `long_opts' variables but not run `getopt' function. - heapsort.awk - heapsort :-) - quicksort.awk - quicksort :-) - sort.awk - either heapsort or quicksort, the default is heapsort. Unfortunately GAWK's asort() and asorti() functions do *not* satisfy my needs. Another (and more important) reason is a portability. Improvements, clean-ups and fixes in regression tests. runawk-0-18-0 was successfully tested on the following platforms: NetBSD-5.0/x86, NetBSD-2.0/alpha, OpenBSD-4.5/x86, FreeBSD-7.1/x86, FreeBSD-7.1/spark, Linux/x86 and Darwin/ppc. ====================================================================== Version 0.17.0, by Aleksey Cheusov, Sat, 12 Sep 2009 01:29:31 +0300 runawk: - ADDED: new option for runawk for #use'ing modules: -f. runawk can also be used for oneliners! ;-) runawk -f abs.awk -e 'BEGIN {print abs(-123); exit}' - In a multilined code passed to runawk using option -e, spaces are allowed before #directives. - After inventing alt_getopt.awk module there is no reason for heuristics that detects whether to add `-' to AWK arguments or not. So I've removed this heuristics. Use alt_getopt.awk module or other "smart" module for handling options correctly! alt_getopt.awk and power_getopt.awk: - FIX: for "abc:" short options specifier BSD and GNU getopt(3) accept "-acb" and understand it as "-a -cb", they also accept "-ac b" and also translate it to "-a -cb". Now alt_getopt.awk and power_getopt.awk work the same way. power_getopt.awk: - -h option doesn't print usage information, --help (and its short synonym) does. New modules: - shquote.awk, implementing shquote() function. shquote(str): `shquote' transforms the string `str' by adding shell escape and quoting characters to include it to the system() and popen() functions as an argument, so that the arguments will have the correct values after being evaluated by the shell. Inspired by NetBSD's shquote(3) from libc. - runcmd.awk, implementing functions runcmd1() and xruncmd1() runcmd1(CMD, OPTS, FILE): wrapper for function system() that runs a command CMD with options OPTS and one filename FILE. Unlike system(CMD " " OPTS " " FILE) the function runcmd1() handles correctly FILE and CMD containing spaces, single quote, double quote, tilde etc. xruncmd1(FILE): safe wrapper for 'runcmd(1)'. awk exits with error if running command failed. - isnum.awk, implementing trivial isnum() function, see the source code. - alt_join.awk, implementing the following functions: join_keys(HASH, SEP): returns string consisting of all keys from HASH separated by SEP. join_values(HASH, SEP): returns string consisting of all values from HASH separated by SEP. join_by_numkeys (ARRAY, SEP [, START [, END]]): returns string consisting of all values from ARRAY separated by SEP. Indices from START (default: 1) to END (default: +inf) are analysed. Collecting values is stopped on index absent in ARRAY. ====================================================================== Version 0.16.0, by Aleksey Cheusov, Sun, 5 Apr 2009 12:45:44 +0300 Lots of demo programs for most runawk modules were created and they are in examples/ subdirectory now. New MEGA module ;-) power_getopt.awk See the documentation and demo program examples/demo_power_getopt. It makes options handling REALLY easy. New modules: embed_str.awk has_suffix.awk has_prefix.awk readfile.awk modinfo.awk Minor fixes and improvements in dirname.awk and basename.awk. Now they are fully compatible with dirname(1) and basename(1) RUNAWK sets the following environment variables for the child awk subprocess: RUNAWK_MODC - A number of modules (-f filename) passed to AWK RUNAWK_MODV_ - Full path to the module #n, where n is in [0..RUNAWK_MODC) range. RUNAWK sets RUNAWK_ART_STDIN environment variable for the child awk subprocess to 1 if additional/artificial `-' was added to the list to awk's arguments. Makefile: bmake-ism were removed. Now Makefile is fully compatible with FreeBSD make. CLEANFILES target is used instead of hand-made rules Minor fix in 'test_all' target ====================================================================== Version 0.15.0, by Aleksey Cheusov, Fri, 19 Dec 2008 21:41:00 +0200 new module alt_getopt.awk that implements 'getopt' function compatible with "Utility Syntax Guidelines" described in "Single UNIX Specification" http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02 "getopt" function from this module is similar to C function getopt(3) (Idiotic GNU getopt(3) must die!) Better heuristics for adding `-' to the list awk's arguments, now it better conforms to "Utility Syntax Guidelines". Makefile: STDIN_FILENAME defaults to `-', not `/dev/stdin' Interix has no /dev/stdin file Makefile: WARNS=4 ====> WARNS?= 4 Makefile: CPPFLAGS -> CFLAGS, FreeBSD make mk scripts don't support CPPFLAGS Lots of regression tests for 'getopt' function ====================================================================== Version 0.14.3, by Aleksey Cheusov, Sat, 18 Oct 2008 19:39:47 +0300 The following code no longer fails with NAWK under NetBSD runawk -e ' { print "123" } ' /dev/null fixed: compilation bug under FreeBSD (WARNS=4 -> warning -> error) caused by comparison of signed and unsigned values More verbose output when stat(filename) failed modules/str2regexp.awk: adapted to buggy MAWK ====================================================================== Version 0.14.2, by Aleksey Cheusov, Fri, 29 Aug 2008 17:28:34 +0300 Temporary file is removed if runawk is killed by SIGINT, SIGQUIT, SIGTERM, SIGHUP or SIGPIPE signals. (Temporary file is created by 'runawk -e ...') ====================================================================== Version 0.14.1, by Aleksey Cheusov, Sat, 19 Jul 2008 22:53:45 +0300 FIXED: The following code doesn't work with runawk-0.14.0 runawk -e ' #use "anymodule.awk" ' This code requires a creation of the temporary file that was removed in runawk-0.14.0. Now temporary file is created using mkstemp(3). Regression tests are created for testing. ====================================================================== Version 0.14.0, by Aleksey Cheusov, Sat, 12 Jul 2008 17:29:22 +0300 Temporary file is not needed anymore for -e option. FIXED: #env didn't work under Linux/glibc. FIXED: compilation error under FreeBSD. Lots of new regression tests. Code clean-ups. fgetln is not required anymore. No hacks about it. If error happens while processing a #directive, a correct line number is output ====================================================================== Version 0.13.0, by Aleksey Cheusov, Sun, 15 Jun 2008 11:30:06 +0300 ADDED: option -v|--assign that works like AWK's -v option. This is to pass some variables to AWK interpreter. Example: runawk -v var=123 -e 'BEGIN {print var }' modules/xgetline.awk: better error message/clean-ups modules/abort.awk: NR is also printed to stderr minor fixes in *.c clean-ups and fixes in 'make test'. Now it doesn't depend on my own system and runawk directory 'make test' exits with non-zero exit status if regression tests fail Makefile: ported to ancient pmake-1.45 found in some Linux distros ====================================================================== Version 0.12.a, by Aleksey Cheusov, Mon, Tue, 4 Mar fix in alt_assert.awk ====================================================================== Version 0.12.0, by Aleksey Cheusov, Mon, 3 Mar 2008 23:04:10 +0200 new directive '#env' is implemented. It sets environment for running awk subprocess using setenv(3) Example: #!/usr/local/bin/runawk #env "LC_ALL=C" $1 ~ /^[A-Z]+$/ { # A-Z is valid if LC_CTYPE=C print $1 } New modules match_br.awk match_br(STRING, BR_OPEN, BR_CLOSE) return start position (or zero if failure) of the substring surrounded by balanced (), [], {} or similar characters Also sets RSTART and RLENGTH variables just like the standard 'match' function does For example: print match_br("A (B (), C(D,C,F (), 123))", "(", ")") print RSTART, RLENGTH -| 3 -| 3 -| 24 braceexpand.awk braceexp(STRING) implement shell-like brace expansion For example: print braceexpand("ab{,22{,7,8}}z{8,9}") -| abz8 abz9 ab22z8 ab22z9 ab227z8 ab227z9 ab228z8 ab228z9 exitnow.awk see the code. exitnow.awk is used by alt_assert.awk and abort.awk abort.awk abort(MSG, EXIT_STATUS) -- print MSG to stderr and exits program with EXIT_STATUS. if EXIT_STATUS is zero of is not specified, 1 is assigned. dirname.awk similar to UNIX's dirname(1) basename.awk similar to UNIX's basename(1) xgetline.awk xgetline0([FILE]) Safe analog to 'getline < FILE' or 'getline' (if no FILE is specified). 0 at the end means that input line is assigned to $0. xgetline([FILE]) Safe analog to 'getline __input < FILE' and 'getline __input' (if no FILE is specified) In both cases "safe" means that returned value is analysed and if it is less than zero (file reading error happens) program will be terminated emmidiately with appropriate error message printed to stderr. Both functions return zero if end of file is reached or non-zero if reading was sucessfull. Example: while (xgetline("/etc/passwd")){ print "user: " __input } xclose.awk xsystem.awk -- safe wrappers over 'close' and 'system' functions ====================================================================== Version 0.11.0, by Aleksey Cheusov, Sat, 9 Feb 2008 17:35:59 +0200 New modules tokenre.awk: By default AWK splits input strings into tokens according to regular expression that defines "space" between tokens using special variable FS. In many situations it is more useful to define regular expressions for tokens themselves. This is what this module does. tokenre(STRING, REGEXP) `tokenre' extracts substrings from STRING according to REGEXP from the left to the right and assigns $1, $2 etc. and NF variable. tokenre0(REGEXP) Does the the same as `tokenre' but splits $0 instead TRE - variable. If it is set to not empty string, splitting is made by default for all input strings. For example: tokenre("print \"Hello world!\"", "\"([^\"]|\\\")*\"|[[:alnum:]_]+") | NF == 2 | $1 == print | $2 == "Hello world!" str2regexp.awk str2regex(STRING) returns a regular expression that matches given STRING For example: print str2regexp("all special symbols: ^$(){}[].*+?|\\") -| all special symbols: [^][$][(][)][{][}][[]\][.][*][+][?][|]\\ multisub.awk multisub(STRING, SUBST_REPLS) `multisub' is a substitution function. It searches for a list of substrings, specified in SUBST_REPL in a left-most longest order and (if found) replaces found fragments with appropriate replacement. SUBST_REPL format: "SUBSTRING1:REPLACEMENT1 SUBSTRING2:REPLACEMENT2...". Three spaces separate substring:replacement pairs from each other. For example: print multisub("ABBABBBBBBAAB", "ABB:c BBA:d AB:e") |- ccBBde new target 'test_all' runs tests for all available awk interpreters ====================================================================== Version 0.10.1, by Aleksey Cheusov, Fri, 1 Feb 2008 21:25:48 +0200 FIXED: If AWK interpreter segfaults or killed by any other signal, runawk exits with exit status 0. Affected runawk versions: all. Now this is fixed and runawk exits with exit status 128+SIGNAL just like many shells. EXIT STATUS section has been added to the manual page. ====================================================================== Version 0.10.0, by Aleksey Cheusov, Wed, 23 Jan 2008 00:38:31 +0200 ADDED: The environment variable RUNAWK_AWKPROG overrides the default awk interpreter which is set at compile time. Documentation updated accordingly. FIXED: unsafe use of strdup(3) I've copied MIT License text to code from www.opensource.org. Do you see any difference? ADDED: new trivial module pow.awk that implements function "pow" fix: MKMAN and MKCATPAGES make's standard variables are checked during installation In order to build runawk not in a directory you can either build it like this (standard way) cd /src/dir; make all install MAKEOBJDIR=/obj/dir or like this cd /obj/dir; make -f /src/dir/Makefile all install optional config.h is #included if you need it other minor fixes and improvements both in code and documentation ====================================================================== Version 0.9.0, by Aleksey Cheusov, Sun, 23 Dec 2007 22:20:23 +0200 I switched to BSD make. I really hate automake and its approach in general. I'm not expert in BSD, but their 'make' looks much better. But using it makes some changes in building process, see README/INSTALLATION section for a brief description. ADDED: man page for runawk. HTML version runawk.html can also be generated from runawk.pod using pod2html, see Makefile. ADDED: -i/-I options for forcing/disabling adding /dev/stdin to the list of awk arguments. See man page for more information. A few AWK modules are installed to PREFIX/share/runawk: abs.awk, min.awk, max.awk and alt_assert.awk. This directory is also checked while searching for modules. See man page for more details. AWK_PROG and STDIN_FILENAME Makefile variables can be passed to make program to change a path to an actual AWK interpreter (/usr/bin/awk by default) and stdin file (/dev/stdin by default). Lots of improvements in documentation ADDED: regression tests. Run them by running 'make test' and let me know if somethiung fails. debugging output is sent stdout, not stderr ADDED: long synonyms for short options, --help, --version etc. clean-ups in Makefile options handling improvements ====================================================================== Version 0.8.1, by Aleksey Cheusov, Wed, 24 Oct 2007 14:46:12 +0300 FIXED: default stdin file should be /std/stdin, not /dev/stderr, I've made a typo. ====================================================================== Version 0.8.0, by Aleksey Cheusov, Sun, 21 Oct 2007 17:19:46 +0300 FIXED: return code of execvp is not analysed, i.e. when running an interpreter fails, runawk silently exits with zero exit status. Now it fails with exit status 1 and print an error to stderr. stdin filename defaults to "/dev/stdin" ROOT variable in Makefile has been renamed to more commonly used PREFIX realloc(2) is not used anymore. arrays[ARRAY_SZ] are used now. AWK and STDIN_FILENAME variables are removed from Makefile. Use CPPFLAGS for changing defaults. ====================================================================== Version 0.7.0, by Aleksey Cheusov, Sat, 22 Sep 2007 02:30:26 +0300 First publicly available release. See README for a documentation ====================================================================== runawk-runawk-1.6.1/doc/TODO000066400000000000000000000023571343160141100155710ustar00rootroot00000000000000plan -1: - gener{it,ate}/chpp/m1/m5 -- general purpose text preprocessor plan 0: - floor, ceil functions - glob() - disable memoization - support X11-like long options, e.g. -display, -geometry etc. - grep(1) in runawk? (POSIX grep -E with some of GNU grep extensions) - gawk/hash.awk (using gawk extensions): remove_by_key(@cond_func) and remove_by_value(@cond_func) - qstack.awk: stack_push, stack_pop, stack_top, stack_isempty, stack_clean queue_push, queue_pop, queue_back, queue_front, queue_isempty, queue_clean, queue_push_back, queue_pop_front - inspect.awk: inspect_str, inspect_hash for displaying invisible characters plan 1: - strtonum from gawk? - random numbers generator from /dev/[u]random - tokenre_in.awk: synonym for tokenre.awk - reference to EGDIR from mk-configure.7 - {string,hash,math}.awk -- accumulative modules - msub() - cleverer replacement for multisub - bre2ere.awk Basic RE to Extended RE convertor - libconfig/libconfuse analog written in/for AWK - csv.awk -- module for "comma separated values" format described in RFC4180 - hash.awk - functions for working with hashes. items_count() ? - support for Windows - remove fflush() ? - quicksort has quadratic complexity when sorting equal values - tr.awk ? runawk-runawk-1.6.1/examples/000077500000000000000000000000001343160141100161435ustar00rootroot00000000000000runawk-runawk-1.6.1/examples/Makefile000066400000000000000000000002531343160141100176030ustar00rootroot00000000000000EXAMPLES != cd ${.CURDIR}; echo demo_* FILES = ${EXAMPLES:N*~:M*.in} SCRIPTS = ${EXAMPLES:N*~:N*.in} FILESDIR = ${EGDIR} SCRIPTSDIR = ${EGDIR} .include runawk-runawk-1.6.1/examples/demo_alt_getopt000077500000000000000000000013661343160141100212450ustar00rootroot00000000000000#!/usr/bin/env runawk #use "alt_getopt.awk" BEGIN { long_opts ["verbose"] = "v" long_opts ["help"] = "h" long_opts ["fake"] = "" long_opts ["len"] = takes_arg long_opts ["output"] = "o" while (getopt("hVvo:n:")){ if (optopt == "h"){ print "option `h'" }else if (optopt == "V"){ print "option `V'" }else if (optopt == "v"){ print "option `v'" }else if (optopt == "o"){ print "option `o':", optarg }else if (optopt == "n"){ print "option `n':", optarg }else if (optopt == "fake"){ print "option `fake'" }else if (optopt == "len"){ print "option `len':", optarg }else{ abort() } fflush() } for (i=1; i < ARGC; ++i){ if (ARGV [i] != "") printf "ARGV [%s] = %s\n", i, ARGV [i] } exit 0 } runawk-runawk-1.6.1/examples/demo_alt_getopt.sh000077500000000000000000000015431343160141100216530ustar00rootroot00000000000000#!/bin/sh # this is a demo for alt_getopt(1) program, not for alt_getopt.awk module! help () { cat 1>&2 <'" \ f 'flag=1' \ F 'flag=' \ q 'quiet="1"; verbose=0' \ =n number= \ -- "$@" # You MUST specify -- here } a=`process_args "$@"` eval "$a" echo "verbose=$verbose" echo "fake_flag=$fake_flag" echo "len=$len" echo "output=$output" echo "msg=$msg" echo "n=$number" echo "flag=$flag" echo "quiet=$quiet" i=1 while test $# -ne 0; do printf "arg [%d]=%s\n" "$i" "$1" i=`expr $i + 1` shift done runawk-runawk-1.6.1/examples/demo_alt_getopt2.sh000077500000000000000000000013451343160141100217350ustar00rootroot00000000000000#!/bin/sh # this is a demo for alt_getopt(1) program and alt_getopt.sh shell module . alt_getopt.sh help () { cat 1>&2 < flag with value # =-LONG-FLAG long flag with value # =S short flag with value # -X short flag # =Y short flag with value # -P print ARGC and ARGV #.end-str # Very powerful easy for use module for handling options BEGIN { if (getarg("P")){ print "ARGC=" ARGC for (i=1; i < ARGC; ++i){ printf "ARGV [%d]=%s\n", i, ARGV [i] } exit (0) } print "The following option were applied" for (i in options){ print "options [" i "]=" options [i] } print "f --- " getarg("f") print "flag --- " getarg("flag") print "long-flag --- " getarg("long-flag") print "s --- " getarg("s") print "F --- " getarg("F", "default1") print "FLAG --- " getarg("FLAG", "default2") print "LONG-FLAG --- " getarg("LONG-FLAG", "default3") print "S --- " getarg("S", "default4") print "X --- " getarg("X") print "Y --- " getarg("Y", "default5") exit 0 } runawk-runawk-1.6.1/examples/demo_power_getopt2000077500000000000000000000005021343160141100216720ustar00rootroot00000000000000#!/usr/bin/env runawk #use "power_getopt.awk" #.begin-str help # power_getopt - program demonstrating a power of power_getopt.awk module # usage: power_getopt [OPTIONS] # OPTIONS: # -?|--help display this screen #.end-str BEGIN { # the only implemented functionality is -?|--help options exit 0 } runawk-runawk-1.6.1/examples/demo_quicksort000077500000000000000000000004601343160141100211210ustar00rootroot00000000000000#!/usr/bin/env runawk #use "quicksort.awk" # This demo sorts the input lines as strings and outputs them to stdout # Input files for this demo: examples/demo_quicksort.in { array [++count] = $0 } END { quicksort(array, remap, 1, count) for (i=1; i <= count; ++i){ print array [remap [i]] } } runawk-runawk-1.6.1/examples/demo_quicksort2000077500000000000000000000010571343160141100212060ustar00rootroot00000000000000#!/usr/bin/env runawk #use "quicksort.awk" #use "alt_assert.awk" # This is a regression test for quicksort.awk module BEGIN { srand() cnt = 400 start = 20 end = start + cnt sum = 0 for (i=start; i <= end; ++i){ arr [i] = int (rand() * 50) sum += arr [i] } quicksort(arr, remap, start, end) end_sum = 0 for (i=start; i <= end; ++i){ # printf "arr [%s]=%s\n", i, arr [remap [i]] assert(i == start || arr [remap [i-1]] <= arr [remap [i]], "failed!") end_sum += arr [remap [i]] } assert(sum == end_sum, "sum != end_sum") exit 0 } runawk-runawk-1.6.1/examples/demo_quicksort3000077500000000000000000000005711343160141100212070ustar00rootroot00000000000000#!/usr/bin/env runawk #use "quicksort.awk" # This demo sorts the input lines as (key, value) pair # and outputs sorted pairs. # Input file for this demo: examples/demo_heapsort3.in { val = $2 val += NR * 0.00001 # for regression tests hash [$1] = val } END { count = quicksort_values(hash, remap) for (i=1; i <= count; ++i){ print remap [i], hash [remap [i]] } } runawk-runawk-1.6.1/examples/demo_readfile000077500000000000000000000004751343160141100206560ustar00rootroot00000000000000#!/usr/bin/env runawk #use "readfile.awk" # This demo reads an entire file, stores its content in a variable and # then print it. # Input files for this demo: examples/demo_readfile.in* BEGIN { if (ARGC != 2){ print "usage: demo_readfile " exit 1 } content = readfile(ARGV [1]) print content } runawk-runawk-1.6.1/examples/demo_readfile.in000066400000000000000000000000221343160141100212440ustar00rootroot00000000000000line1 line2 line3 runawk-runawk-1.6.1/examples/demo_runcmd000077500000000000000000000006531343160141100203710ustar00rootroot00000000000000#!/usr/bin/env runawk #use "runcmd.awk" # Demo foir runcmd.awk module BEGIN { fn1 = "file name.txt" fn2 = "~file&name'foobar'.txt" xruncmd1("touch", "", fn1) xruncmd1("echo", "foobar >", fn2) xruncmd1("ls", "-1", fn1) xruncmd1("ls", "", fn2) ret = runcmd1("grep", "baz", fn2) assert(1 == ret, "runcmd failed, exit status: " ret) xruncmd1("rm", "-f", fn1) xruncmd1("rm", "", fn2) print "succeeded" exit 0 } runawk-runawk-1.6.1/examples/demo_shquote000077500000000000000000000004061343160141100205650ustar00rootroot00000000000000#!/usr/bin/env runawk #use "shquote.awk" #use "xsystem.awk" # This demo runs shquote ($0) for each input line and outputs the result. # Input files for this demo: examples/demo_shquote.in { print shquote($0) xsystem("printf 'printf: %s\n' " shquote($0)) } runawk-runawk-1.6.1/examples/demo_shquote.in000066400000000000000000000001121343160141100211610ustar00rootroot00000000000000' '' ''' \ \\ \\\ \\' '\' Apple's apple file name.txt *&;<>#~^$`!][(){}? runawk-runawk-1.6.1/examples/demo_splitre000077500000000000000000000010331343160141100205540ustar00rootroot00000000000000#!/usr/bin/env runawk #use "tokenre.awk" # This demo splits input line into tokens according to regexp that # defines lexem of hypotetic programming language. # Input files for this demo: examples/demo_tokenre2.in* BEGIN { re = "if|then|else|while|do|end" re = re "|" "[0-9]+([.][0-9]+)?" re = re "|" ":=|=|<|>|!=|[+]|-|[*]|/|[.][.]" re = re "|" "[()]" re = re "|" "[[:alpha:]_][[:alnum:]_]*" re = re "|" "'[^']*'" } { cnt = splitre0(arr, re) for (i=1; i <= cnt; ++i){ print arr [i] } print "" } runawk-runawk-1.6.1/examples/demo_str2regexp000077500000000000000000000003251343160141100212020ustar00rootroot00000000000000#!/usr/bin/env runawk #use "str2regexp.awk" # This demo converts string ($0) to regexp that matches this string # Input files for this demo: examples/demo_str2regexp.in* { print $0 " --> " str2regexp($0) } runawk-runawk-1.6.1/examples/demo_tmpfile000077500000000000000000000007311343160141100205360ustar00rootroot00000000000000#!/usr/bin/env runawk #use "tmpfile.awk" #use "exitnow.awk" # This demo generates temporary file names and outputs them to stdout BEGIN { tmpfile1 = tmpfile() tmpfile2 = tmpfile() tmpsubdir = tmpfile() print "file 1" > tmpfile1 print "file 2" > tmpfile2 system("mkdir " tmpsubdir) tmpfile3 = tmpsubdir "/file3" print "file 3" > tmpfile3 close(tmpfile1) close(tmpfile2) close(tmpfile3) system("cat " tmpfile1 " " tmpfile2 " " tmpfile3) exitnow(0) } runawk-runawk-1.6.1/examples/demo_tokenre000077500000000000000000000006721343160141100205510ustar00rootroot00000000000000#!/usr/bin/env runawk #use "tokenre.awk" # This demo splits input line into tokens according to regexp that # defines a token, not between tokens. # # Suported tokens: # - sequence of non-space and not " characters # - "la-la-la even spaces here " # Input files for this demo: examples/demo_tokenre.in* BEGIN { TRE="\"[^\"]*\"|[^\"[:space:]]+" } { print "NF=" NF for (i=1; i <= NF; ++i){ printf "$%d=%s\n", i, $i } } runawk-runawk-1.6.1/examples/demo_tokenre.in000066400000000000000000000006431343160141100211510ustar00rootroot00000000000000wn: UNIX "UNIX guru" "UNIX operating system" "UNIX system" jargon: Unix "Unix brain damage" "Unix conspiracy" "Unix weenie" foldoc: "berkeley unix" "bsd unix" "call unix" "united kingdom unix users group" unix "unix box" "unix brain damage" "unix conspiracy" "unix international" "unix man page" "unix manual page" "unix system v" "unix to unix copy" "unix weenie" "unix wizard" "usg unix" runawk-runawk-1.6.1/examples/demo_tokenre2000077500000000000000000000010101343160141100206160ustar00rootroot00000000000000#!/usr/bin/env runawk #use "tokenre.awk" # This demo splits input line into tokens according to regexp that # defines lexem of hypotetic programming language. # Input files for this demo: examples/demo_tokenre2.in* BEGIN { TRE = "if|then|else|while|do|end" TRE = TRE "|" "[0-9]+([.][0-9]+)?" TRE = TRE "|" ":=|=|<|>|!=|[+]|-|[*]|/|[.][.]" TRE = TRE "|" "[()]" TRE = TRE "|" "[[:alpha:]_][[:alnum:]_]*" TRE = TRE "|" "'[^']*'" } { for (i=1; i <= NF; ++i){ print $i } print "" } runawk-runawk-1.6.1/examples/demo_tokenre2.in000066400000000000000000000001651343160141100212320ustar00rootroot00000000000000a := 1 b := 2.3 while a+b < 10 do a := a+1 end print 'Hello world!' print 'a = ' .. a print 'b = ' .. b runawk-runawk-1.6.1/examples/demo_tokenre3000077500000000000000000000011171343160141100206270ustar00rootroot00000000000000#!/usr/bin/env runawk #use "tokenre.awk" # This demo extracts e-mails and URLs from input text and outputs them # Using tokenre.awk for searching was inspired by talks with Vlad Shakhov # Input files for this demo: examples/demo_tokenre3.in* BEGIN { # regexp for emails and URLs are just examples and therefore don't # conform to appropriate RFCs. domains = "(com|org|net|ru|by|ua)" TRE = "[^ [:punct:]]+@([^ [:punct:]]+[.])+" domains TRE = TRE "|" "(https?|ftp|dict)://([^ [:punct:]]+[.])+" domains "(/[^ [:punct:]]*)?" } { for (i=1; i <= NF; ++i){ print $i } } runawk-runawk-1.6.1/examples/demo_tokenre3.in000066400000000000000000000005571343160141100212400ustar00rootroot00000000000000RunAWK is hosted here: http://sourceforge.net/projects/runawk/ and here http://freshmeat.net/projects/runawk/ dictd.xdsl.by serves dictionary protocol (RFC2229) server dict://dictd.xdsl.by/ runawk's author and dictd's current maintainer is me , dictd's original author is Rick Faith Two and emails. runawk-runawk-1.6.1/examples/demo_tokenre4000077500000000000000000000012461343160141100206330ustar00rootroot00000000000000#!/usr/bin/env runawk #use "tokenre.awk" # This demo extracts e-mails and URLs from input text and outputs them # Using tokenre.awk for searching was inspired by talks with Vlad Shakhov # Input files for this demo: examples/demo_tokenre3.in* BEGIN { # regexp for emails and URLs are just examples and therefore don't # conform to appropriate RFCs. domains = "(com|org|net|ru|by|ua)" re = "[^ [:punct:]]+@([^ [:punct:]]+[.])+" domains re = re "|" "(https?|ftp|dict)://([^ [:punct:]]+[.])+" domains "(/[^ [:punct:]]*)?" } { cnt = splitre($0, arr, re) for (i=1; i <= cnt; ++i){ if (i > 1) printf " " printf "%s", arr [i] } if (cnt) printf "\n" } runawk-runawk-1.6.1/examples/demo_trim000066400000000000000000000006061343160141100200470ustar00rootroot00000000000000#!/usr/bin/env runawk #use "trim.awk" # This is a demo for trim.awk module # Input files for this demo: examples/demo_trim.in { printf "trim_l(\"%s\")=\"%s\"\n", $0, trim_l($0) printf "trim_r(\"%s\")=\"%s\"\n", $0, trim_r($0) printf "trim_c(\"%s\")=\"%s\"\n", $0, trim_c($0) printf "trim_lr(\"%s\")=\"%s\"\n", $0, trim_lr($0) printf "trim_lrc(\"%s\")=\"%s\"\n", $0, trim_lrc($0) } runawk-runawk-1.6.1/examples/demo_trim.in000066400000000000000000000001561343160141100204540ustar00rootroot00000000000000Van Der Graaf Generator Peter Hammill King Crimson Robert Fripp Jethro Tull Jan Anderson runawk-runawk-1.6.1/examples/demo_trim_in000066400000000000000000000002301343160141100205260ustar00rootroot00000000000000#!/usr/bin/env runawk #use "trim_in.awk" # This is a demo for trim_in.awk module # Input files for this demo: examples/demo_trim_in.in { print $0 } runawk-runawk-1.6.1/modules/000077500000000000000000000000001343160141100157755ustar00rootroot00000000000000runawk-runawk-1.6.1/modules/CR_in.awk000066400000000000000000000011771343160141100175010ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 CR_in.awk # # As the name of this module says (_in suffix) this module reads and # optionally changes input lines. # # Carriage-Return symbol at the end of input lines is removed. # This symbol usually appears in Windows text files. # If you want to adapt your script to accept windows files on input, # just put # # #use "CR_in.awk" # # in the very beginning of your script. # { gsub(/\r+$/, "") } runawk-runawk-1.6.1/modules/Makefile000066400000000000000000000010241343160141100174320ustar00rootroot00000000000000MODULES != cd ${.CURDIR}; LC_ALL=C ls *.awk gawk/*.awk FILES = ${MODULES} FILESDIR = ${MODULESDIR} FILESNAME_gawk/ord.awk = gawk/ord.awk MAN = runawk_modules.3 .PHONY: _manpages _manpages: ${MAN} .PATH: ${.OBJDIR} CLEANFILES += runawk_modules.3 runawk_modules.pod runawk_modules.pod: ${MODULES} pod_header.txt pod_footer.txt { set -e; cd ${.CURDIR}; \ cat pod_header.txt; \ awk '/^# =head/, NF==0 {if (/^#/) print substr($$0, 3)}' \ ${MODULES}; \ cat pod_footer.txt; } > ${.TARGET} .include runawk-runawk-1.6.1/modules/abort.awk000066400000000000000000000013411343160141100176070ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # #use "exitnow.awk" # =head2 abort.awk # # =over 2 # # =item I # # print MSG to stderr and exits program with # EXIT_STATUS. EXIT_STATUS defaults to 1. # # =back # function abort (msg, status){ printf "error: %s\n", msg > "/dev/stderr" printf " ARGV[0]=%s\n", ARGV[0] > "/dev/stderr" printf " $0=`%s`\n", $0 > "/dev/stderr" printf " NF=%d\n", NF > "/dev/stderr" printf " FNR=%d\n", FNR > "/dev/stderr" printf " FILENAME=%s\n", FILENAME > "/dev/stderr" if (!status){ status = 1 } exitnow(status) } runawk-runawk-1.6.1/modules/abs.awk000066400000000000000000000006001343160141100172420ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 abs.awk # # =over 2 # # =item I # # return absolute value of V. # # =back # function abs (v){ if (v < 0) return -v else return v } runawk-runawk-1.6.1/modules/alt_assert.awk000066400000000000000000000010621343160141100206410ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ #use "abort.awk" # =head2 alt_assert.awk # # =over 2 # # =item I # # print an # error message MSG to standard error and terminates # the program with STATUS exit code if CONDITION is false. # # =back # function assert (cond, msg, status){ if (!cond){ abort("assertion failed: " msg, status) } } runawk-runawk-1.6.1/modules/alt_getopt.awk000066400000000000000000000104711343160141100206460ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 alt_getopt.awk # # =over 2 # # =item I # # This function processes ARGV array and # returns TRUE if option is received, # received option is saved in 'optopt' variable, option argument (if any) # is saved in 'optarg' variable. Long options (like --help or # --long-option) present in GNU libc and BSD systems are also supported. # # NOTE: alt_getopt.awk module follows rules # from SUS/POSIX "Utility Syntax Guidelines" # # =back # ############################################################### # # EXAMPLE # #!/usr/bin/env runawk # # #use "alt_getopt.awk" # # BEGIN { # long_opts ["verbose"] = "v" # long_opts ["help"] = "h" # long_opts ["fake"] = "" # long_opts ["len"] = takes_arg # long_opts ["output"] = "o" # # while (getopt("hVvo:n:")){ # if (optopt == "h"){ # print "option `h'" # }else if (optopt == "V"){ # print "option `V'" # }else if (optopt == "v"){ # print "option `v'" # }else if (optopt == "o"){ # print "option `o':", optarg # }else if (optopt == "n"){ # print "option `n':", optarg # }else if (optopt == "fake"){ # print "option `fake'" # }else if (optopt == "len"){ # print "option `len':", optarg # }else{ # abort() # } # } # # for (i=1; i < ARGC; ++i){ # if (ARGV [i] != "") # printf "ARGV [%s] = %s\n", i, ARGV [i] # } # # exit 0 # } ############################################################### #use "alt_assert.awk" function __getopt_errexit (msg, status) { print msg > "/dev/stderr" exitnow(status) } function __getopt_addstdin ( i) { for (i=1; i < ARGC; ++i){ if (ARGV [i] != __getopt_fill){ return } } ARGV [1] = "-" } BEGIN { opterr = "" takes_arg = -1 } function __getopt_prepare (\ short_opts, i, len, nc) # local vars { if ("-" in __getopt_opts){ # already initialized return } len = length(short_opts) for (i=1; i <= len; ++i){ if (i < len && substr(short_opts, i+1, 1) == ":"){ __getopt_opts [substr(short_opts, i, 1)] = takes_arg ++i }else{ __getopt_opts [substr(short_opts, i, 1)] = "" } } for (i in long_opts){ __getopt_opts [i] = long_opts [i] } } function __getopt_process_short_opts (\ i, opts) # local vars { opts = substr(ARGV [i], 2) optopt = substr(opts, 1, 1) if (! (optopt in __getopt_opts)){ __getopt_errexit("Unknown option `-" optopt "'", 2) } if (__getopt_opts [optopt] == takes_arg){ if (length(opts) == 1){ optarg = ARGV [i+1] ARGV [i] = ARGV [i+1] = __getopt_fill }else{ optarg = substr(opts, 2) ARGV [i] = __getopt_fill } return 1 } if (length(opts) > 1) ARGV [i] = "-" substr(opts, 2) else ARGV [i] = __getopt_fill return 1 } function __getopt_process_long_opts (\ i, opt,val,prefix,eq) { opt = substr(ARGV [i], 3) eq = (opt ~ /[=]/) sub(/[=].*$/, "", opt) prefix = "--" if ((opt in __getopt_opts) && __getopt_opts [opt] != "" && __getopt_opts [opt] != takes_arg) { prefix = "-" opt = __getopt_opts [opt] } if (opt in __getopt_opts){ optopt = opt val = __getopt_opts [opt] if (val == ""){ assert(!eq, "Unexpected argument for option `" opt "'") ARGV [i] = __getopt_fill return 1 }else if (val == takes_arg){ if (eq){ optarg = ARGV [i] sub(/^[^=]*=/, "", optarg) }else{ optarg = ARGV [i+1] ARGV [i+1] = __getopt_fill } ARGV [i] = __getopt_fill return 1 } } __getopt_errexit("Unknown option `" prefix opt "'", 2) } function getopt (\ short_opts, no_stdin, i) # local vars { __getopt_prepare(short_opts) for (i = 1; i < ARGC; ++i){ optarg = "" if (ARGV [i] == __getopt_fill){ continue } if (ARGV [i] == "--"){ ARGV [i] = __getopt_fill __getopt_addstdin() return 0 } if (ARGV [i] !~ /^-/ || ARGV [i] == "-"){ return 0 } if (ARGV [i] ~ /^--/){ return __getopt_process_long_opts(i) } assert(ARGV [i] ~ /^-/) return __getopt_process_short_opts(i) } if (!no_stdin) __getopt_addstdin() return 0 } runawk-runawk-1.6.1/modules/alt_join.awk000066400000000000000000000026241343160141100203040ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 alt_join.awk # # =over 2 # # =item I # # return string consisting of all keys from HASH separated by SEP. # # =item I # # return string consisting of all values from HASH separated by SEP. # # =item I # # return string consisting of all values from ARRAY # separated by SEP. Indices from START (default: 1) to END # (default: +inf) are analysed. Collecting values is stopped # on index absent in ARRAY. # # =back # function join_keys (hash, sep, k,ret,flag){ ret = "" for (k in hash){ if (flag){ ret = ret sep k }else{ flag = 1 ret = k } } return ret } function join_values (hash, sep, k,ret,flag){ ret = "" for (k in hash){ if (flag){ ret = ret sep hash [k] }else{ flag = 1 ret = hash [k] } } return ret } function join_by_numkeys (array, sep, start, end, ret,flag){ ret = "" if (start == "") start = 1 if (end == "") end = 1.0E+37 for (; start <= end && (start in array); ++start){ if (flag){ ret = ret sep array [start] }else{ flag = 1 ret = array [start] } } return ret } runawk-runawk-1.6.1/modules/backslash_in.awk000066400000000000000000000014541343160141100211260ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 backslash_in.awk # # As the name of this module (_in suffix) says this module # reads and optionally changes input lines. # # Backslash character at the end of line is treated as a sign # that current line is continued on the next one. # Example is below. # # Input: # a b c\ # d e f g # a # b # e\ # f # # What your program using backslash_in.awk will obtain: # a b cd e f g # a # b # e f # #use "xgetline.awk" { while ($0 ~ /\\/){ assert(xgetline() > 0, "unexpected end of file") $0 = substr($0, 1, length($0)-1) __input } } runawk-runawk-1.6.1/modules/basename.awk000066400000000000000000000013161343160141100202550ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ #use "has_suffix.awk" # =head2 basename.awk # # =over 2 # # =item I # # return filename portion of the PATH # (the same as I) # # =back # # See example/demo_basename for the sample of usage # function basename (pathname, suffix){ sub(/\/$/, "", pathname) if (pathname == "") return "/" sub(/^.*\//, "", pathname) if (suffix != "" && has_suffix(pathname, suffix)) pathname = substr(pathname, 1, length(pathname) - length(suffix)) return pathname } runawk-runawk-1.6.1/modules/braceexpand.awk000066400000000000000000000030331343160141100207540ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 braceexpand.awk # # =over 2 # # =item I # # shell-like brace expansion. # # For example: # print braceexpand("ab{,22{,7,8}}z{8,9}") # -| abz8 abz9 ab22z8 ab22z9 ab227z8 ab227z9 ab228z8 ab228z9 # # =back # #use "match_br.awk" BEGIN { __runawk_expanded = 0 } function __runawk_braceexpand1 (s, left,mid,right,len,accu,i,ch,deep) { __runawk_expanded = 0 if (match_br(s, "{", "}")){ left = substr(s, 1, RSTART-1) mid = substr(s, RSTART+1, RLENGTH-2) "," right = substr(s, RSTART+RLENGTH) len = RLENGTH-1 s = "" accu = "" deep = 0 for (i=1; i <= len; ++i){ ch = substr(mid, i, 1) if (deep == 0 && ch == ","){ if (s != ""){ s = s " " } accu = __runawk_braceexpand1(accu) if (gsub(/ /, ",", accu)){ s = s __runawk_braceexpand1(left "{" accu "}" right) }else{ s = s left accu right } accu = "" }else{ accu = accu ch if (ch == "{") ++deep else if (ch == "}") --deep } } __runawk_expanded = 1 } return s } function braceexpand (s, arr,i,cnt,cont){ cont = 1 while (cont){ cont = 0 cnt = split(s, arr, / /) s = "" for (i=1; i <= cnt; ++i){ if (i > 1) s = s " " s = s __runawk_braceexpand1(arr [i]) cont = (cont || __runawk_expanded) } } return s } runawk-runawk-1.6.1/modules/dirname.awk000066400000000000000000000010741343160141100201220ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 dirname.awk # # =over 2 # # =item I # # return dirname portion of the PATH # (the same as I) # # =back # # See example/demo_dirname for the sample of usage # function dirname (pathname){ if (!sub(/\/[^\/]*\/?$/, "", pathname)) return "." else if (pathname != "") return pathname else return "/" } runawk-runawk-1.6.1/modules/embed_str.awk000066400000000000000000000020131343160141100204410ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 embed_str.awk # # This module reads a program's file, find .begin-str/.end-str pairs # and reads lines between them. # # I - Associative array with string index # # Example: # Input: # .begin-str mymsg # Line1 # Line2 # .end-str # Output (result) # EMBED_STR ["mymsg"]="Line1\nLine2" # # See example/demo_embed_str for the sample of usage # #use "xgetline.awk" #use "modinfo.awk" #use "xclose.awk" BEGIN { _embed_str_id = "" while (xgetline0(MODMAIN)){ if ($0 ~ /^#[.]begin-str/){ _embed_str_id = $2 }else if ($0 ~ /^#[.]end-str/){ _embed_str_id = "" }else if (_embed_str_id != ""){ if (EMBED_STR [_embed_str_id] != "") _nl = "\n" else _nl = "" EMBED_STR [_embed_str_id] = EMBED_STR [_embed_str_id] _nl substr($0, 3) } } xclose(MODMAIN) } runawk-runawk-1.6.1/modules/exitnow.awk000066400000000000000000000010431343160141100201740ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 exitnow.awk # # =over 2 # # =item I # # similar to the statement 'exit' but do not run # END sections. # # =back # function exitnow (exit_status){ __runawk_exit_status = exit_status __runawk_exit = 1 exit exit_status } END { if (__runawk_exit){ exit __runawk_exit_status } } runawk-runawk-1.6.1/modules/fieldwidths.awk000066400000000000000000000027011343160141100210070ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 fieldwidth.awk # # By default AWK interpreter splits input lines into tokens according # to regular expression that defines "spaces" between them using # special variable FS. Sometimes it is useful to define a fixed-size # fields for tokens. This is what this module is for. The # functionality of fieldwidths.awk is very close to GNU awk's # FIELDWIDTHS variable. # # =over 2 # # =item I # # extracts substrings from STRING according to FW # from the left to the right and assigns $1, $2 etc. and NF # variable. FW is a space separated list of numbers that specify # fields widths. # # =item I # # Does the the same as `fieldwidths' function but splits $0 instead. # # =item I # # global variable. If it is set to non-empty string, all input # lines are split automatically and the value of variable FS is # ignored in this case. # # =back # # See example/demo_fieldwidths for the sample of usage # function fieldwidths (s, fw, arr,cnt,i){ cnt = split(fw, arr, " ") for (i=1; s != "" && i <= cnt; ++i){ $i = substr(s, 1, arr [i]) s = substr(s, arr [i]+1) } NF = i-1 } function fieldwidths0 (fw){ fieldwidths($0, fw) } { if (FW != ""){ fieldwidths0(FW) } } runawk-runawk-1.6.1/modules/ftrans_in.awk000066400000000000000000000012401343160141100204610ustar00rootroot00000000000000# ftrans.awk --- handle data file transitions # # user supplies beginfile() and endfile() functions # # Arnold Robbins, arnold@skeeve.com, Public Domain, November 1992 # Aleksey Cheusov, vle@gmx.net, Public Domain, September 2010 # (fix and adaptation for nawk by B.Kernighan) # =head2 ftrans_in.awk # # beginfile() function provided by user is called before file reading # # endfile() function provided by user is called after file reading # FNR == 1 { if (_filename_ != "") endfile(_filename_) _filename_ = (FILENAME == "" ? "-" : FILENAME) # for nawk beginfile(_filename_) } END { if (_filename_ != "") # fix for Arnold's version endfile(_filename_) } runawk-runawk-1.6.1/modules/gawk/000077500000000000000000000000001343160141100167265ustar00rootroot00000000000000runawk-runawk-1.6.1/modules/gawk/ord.awk000066400000000000000000000021031343160141100202120ustar00rootroot00000000000000# ord.awk --- do ord and chr # Global identifiers: # _ord_: numerical values indexed by characters # _ord_init: function to initialize _ord_ # # Arnold Robbins, arnold@skeeve.com, Public Domain # 16 January, 1992 # 20 July, 1992, revised # =head2 ord.awk # # =over 2 # # =item I # # return numeral code of CHAR # # =item I # # return symbol from the CODE # # =back # BEGIN { _ord_init() } function _ord_init( low, high, i, t) { low = sprintf("%c", 7) # BEL is ascii 7 if (low == "\a") { # regular ascii low = 0 high = 127 } else if (sprintf("%c", 128 + 7) == "\a") { # ascii, mark parity low = 128 high = 255 } else { # ebcdic(!) low = 0 high = 255 } for (i = low; i <= high; i++) { t = sprintf("%c", i) _ord_[t] = i } } function ord(str, c) { # only first character is of interest c = substr(str, 1, 1) return _ord_[c] } function chr(c) { # force c to be numeric by adding 0 return sprintf("%c", c + 0) } runawk-runawk-1.6.1/modules/glob.awk000066400000000000000000000022151343160141100174240ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 glob.awk # # =over 2 # # =item I # # convert glob PATTERN # (http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_13) # to equivalent extended regular expression # (http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap09.html#tag_09_04) # # =back # #use "multisub.awk" BEGIN { __g2e="^:\\^ $:[$] (:[(] ):[)] {:[{] }:[}]" __g2e=__g2e " \\[([^\\[\\]]|\\\\\\[|\\\\\\])*\\]:& .:[.] *:.* +:[+]" __g2e=__g2e " ?:. |:[|] \\\\:\\\\" __g2e=__g2e " \\^:\\^ \\$:[$] \\(:[(] \\):[)] \\{:[{] \\}:[}]" __g2e=__g2e " \\[:\\[ \\]:\\] \\.:[.] \\*:[*] \\+:[+] \\?:[?]" __g2e=__g2e " \\|:[|] \\:" } function glob2ere (p){ return multisub(p, __g2e, "&") } function glob (s, p, re){ if (p in __runawk_glob2ere) re = __runawk_glob2ere [p] else re = __runawk_glob2ere [p] = ("^" glob2ere(p) "$") return s ~ re } runawk-runawk-1.6.1/modules/has_prefix.awk000066400000000000000000000011051343160141100206260ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 has_prefix.awk # # =over 2 # # =item I # # return TRUE if STRING begins with PREFIX # # =back # # See example/demo_has_prefix for the sample of usage # function has_prefix (s, pre, pre_len, s_len){ pre_len = length(pre) s_len = length(s) return pre_len <= s_len && substr(s, 1, pre_len) == pre } runawk-runawk-1.6.1/modules/has_suffix.awk000066400000000000000000000011131343160141100206340ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 has_suffix.awk # # =over 2 # # =item I # # return TRUE if STRING ends with SUFFIX # # =back # # See example/demo_has_suffix for the sample of usage # function has_suffix (s, suf, suf_len, s_len){ suf_len = length(suf) s_len = length(s) return suf_len <= s_len && substr(s, s_len - suf_len + 1) == suf } runawk-runawk-1.6.1/modules/heapsort.awk000066400000000000000000000110541343160141100203270ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 heapsort.awk # # =over 2 # # =item I # # The content of `src_array' is sorted using awk's rules for # comparing values. Values with indices in range [start, end] are # sorted. `src_array' array is not changed. # Instead dest_remap array is generated such that # # Result: # src_array [dest_remap [start]] <= # <= src_array [dest_remap [start+1]] <= # <= src_array [dest_remap [start+2]] <= ... <= # <= src_array [dest_remap [end]] # # `heapsort' algorithm is used. # Examples: see demo_heapsort and demo_heapsort2 executables. # # =item I # # The same as `heapsort' described above, but hash values are sorted. # # Result: # src_array [dest_remap [1]] <= # <= src_array [dest_remap [2]] <= # <= src_array [dest_remap [3]] <= ... <= # <= src_array [dest_remap [count]] # # `count', a number of elements in `src_hash', is a return value. # # Examples: see demo_heapsort3 executable. # # =item I # # The same as `heapsort' described above, but hash indices are sorted. # # Result: # dest_remap [1] <= # <= dest_remap [2] <= # <= dest_remap [3] <= ... <= # <= dest_remap [count] # # `count', a number of elements in `src_hash', is a return value. # # Examples: demo_ini # # =item I # # The same as function "heapsort0" but $1, $2... array is sorted. # Note that $1, $2... are not changed, but dest_remap array is filled in! # The variable "start" default to 1, "end" -- to NF. # If "strnum" is set to 1, values are forcibly compared as strings. # If "strnum" is set to 2, values are forcibly compared as numbers. # # =item I # # The same as "heapsort_fields" but $1, $2... are changed. # # =back # function sift_down (array, root, start, end, index_remap, n0, v){ while (1){ n0 = root - start + 1 + root if (n0 > end) return if (n0 < end && array [index_remap [n0]] < array [index_remap [n0+1]]) ++n0 if (array [index_remap [root]] >= array [index_remap [n0]]) return v = index_remap [root] index_remap [root] = index_remap [n0] index_remap [n0] = v root = n0 } } function sift_up (array, root, start, end, index_remap, n0, v){ while (1){ n0 = int((root - start + 1)/2) - 1 + start if (n0 < start) return if (array [index_remap [root]] >= array [index_remap [n0]]) return v = index_remap [root] index_remap [root] = index_remap [n0] index_remap [n0] = v root = n0 } } function heapsort (array, index_remap, start, end, i,v){ for (i=start; i <= end; ++i){ index_remap [i] = i } for (i=int((start+end)/2); i >= start; --i){ sift_down(array, i, start, end, index_remap) } for (; end > start; --end){ v = index_remap [start] index_remap [start] = index_remap [end] index_remap [end] = v sift_down(array, start, start, end-1, index_remap) } } function heapsort_values (hash, remap_idx, array, remap, i, cnt) { cnt = 0 for (i in hash) { ++cnt array [cnt] = hash [i] remap [cnt] = i } heapsort(array, remap_idx, 1, cnt) for (i=1; i <= cnt; ++i) { remap_idx [i] = remap [remap_idx [i]] } return cnt } function heapsort_indices (hash, remap_idx, array, i, cnt) { cnt = 0 for (i in hash) { ++cnt array [cnt] = i } heapsort(array, remap_idx, 1, cnt) for (i=1; i <= cnt; ++i) { remap_idx [i] = array [remap_idx [i]] } return cnt } function heapsort_fields (index_remap, start, end, str, i,arr) { if (start == "") start = 1 if (end == "") end = NF if (str == 1){ for (i=start; i <= end; ++i){ arr [i] = ($i "") } }else if (str == 2){ for (i=start; i <= end; ++i){ arr [i] = $i + 0 } }else{ for (i=start; i <= end; ++i){ arr [i] = $i } } heapsort(arr, index_remap, start, end) } function heapsort0 (start, end, str, i,arr,remap) { if (start == "") start = 1 if (end == "") end = NF if (str == 1){ for (i=start; i <= end; ++i){ arr [i] = ($i "") } }else if (str == 2){ for (i=start; i <= end; ++i){ arr [i] = $i + 0 } }else{ for (i=start; i <= end; ++i){ arr [i] = $i } } heapsort(arr, remap, start, end) for (i=start; i <= end; ++i){ $i = arr [remap [i]] } } runawk-runawk-1.6.1/modules/ini.awk000066400000000000000000000041671343160141100172700ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 ini.awk # # This module provides functions for manipulating .ini files. # See example/demo_ini for the sample of use. # # =over 2 # # =item I # # Reads .ini file FILENAME and fills array RESULT, e.g. # RESULT [] = etc. # If SEPARATOR is not specified, `.' symbols is used by default. # # =back # # Features: # # - spaces are allowed everywhere, i.e. at the beginning and end of # line, around `=' separator. THEY ARE STRIPPED! # - comment lines start with `;' or `#' sign. Comment lines are ignored. # - values can be surrounded by signle or double quote. In this case # spaces are presenrved, otherwise they are removed from # beginning and at the end of line and replaced with single space # in the middle of the line. # - Escape character are not supported (yet?). # #use "alt_assert.awk" #use "xgetline.awk" #use "trim.awk" function __runawk_register_value (s, n, v, r, sep){ r [s sep n] = v } function read_inifile (inifile, result, sep) { if (sep == "") sep = "." while (xgetline(inifile)){ sub(/^[[:space:]]*[;#].*$/, "", __input) sub(/[;#][^"']*$/, "", __input) sub(/^[[:space:]]+/, "", __input) sub(/[[:space:]]+$/, "", __input) if (__input == "") continue ############ [section] if (__input ~ /^\[.+\]$/){ section = substr(__input, 2, length(__input)-2) continue } ############ name = value idx = match(__input, /=/) assert(idx > 0, "`=' cannot be found") name = trim_lrc(substr(__input, 1, idx-1)) value = trim_lr(substr(__input, idx+1)) # name = "value" if (value ~ /^".*"$/ || value ~ /^'.*'$/){ __runawk_register_value(\ section, name, substr(value, 2, length(value)-2), result, sep) continue } assert(value !~ /^["']|["']$/, "wrong value") # name = v a l u e __runawk_register_value(section, name, trim_c(value), result, sep) } } runawk-runawk-1.6.1/modules/init_getopt.awk000066400000000000000000000037421343160141100210340ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 init_getopt.awk # # Initialization step for power_getopt.awk module. In some cases it # makes sense to process options in a while() loop. This module # allows doing this. See the documentation about how options are # initialized in power_getopt.awk module. # # =over 2 # # =item I # # display help message. # # =back # #use "alt_getopt.awk" #use "embed_str.awk" function print_help ( i){ for (i = 1; i <= _help_msg_cnt; ++i){ if (_help_msg_arr [i] ~ /^[ \t]*=/){ sub(/=/, "-", _help_msg_arr [i]) } print _help_msg_arr [i] > "/dev/stderr" } } BEGIN { if ("help" in EMBED_STR){ _help_msg = EMBED_STR ["help"] _help_msg_cnt = split(_help_msg, _help_msg_arr, /\n/) for (i = 1; i <= _help_msg_cnt; ++i){ if (match(_help_msg_arr [i], /^[ \t]*[-=][^ \t]+/)){ _opt = substr(_help_msg_arr [i], RSTART, RLENGTH) sub(/^[ \t]+/, "", _opt) if (_opt ~ /^-.[|]--.+$/){ # -h|--help _sopt = substr(_opt, 1, 2) _lopt = substr(_opt, 4) }else if (_opt ~ /^=.[|]--.+$/){ # =h|--help _sopt = substr(_opt, 1, 2) _lopt = "=" substr(_opt, 5) }else if (_opt ~ /^[-=].$/){ # -h or =h _sopt = _opt _lopt = "" }else if (_opt ~ /^[-=]-.+$/){ # --help or =-help _sopt = "" _lopt = _opt } if (_sopt ~ /^-.$/){ # -h short_opts = short_opts substr(_sopt, 2, 1) }else if (_sopt ~ /^=.$/){ # =F short_opts = short_opts substr(_sopt, 2, 1) ":" } sub(/^[-=]/, "", _sopt) if (_lopt ~ /^--.+$/){ # --help long_opts [substr(_lopt, 3)] = _sopt }else if (_lopt ~ /^=-.+$/){ # =-FLAG if (_sopt != "") long_opts [substr(_lopt, 3)] = _sopt else long_opts [substr(_lopt, 3)] = takes_arg } } } } } runawk-runawk-1.6.1/modules/io.awk000066400000000000000000000055561343160141100171230ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 io.awk # # This module provides a number of IO functions. # # =over 2 # # =item I # # returns 1 if the specified FILENAME # is a regular file or 0 otherwise. # # =item I # # returns 1 if the specified FILENAME # is a socket or 0 otherwise. # # =item I # # returns 1 if the specified FILENAME # is a dir or 0 otherwise. # # =item I # # returns 1 if the specified FILENAME # is executable or 0 otherwise. # # =item I # # returns 1 if the specified FILENAME # is a FIFO or 0 otherwise. # # =item I # # returns 1 if the specified FILENAME # is a block special file or 0 otherwise. # # =item I # # returns 1 if the specified FILENAME # is a character special file or 0 otherwise. # # =item I # # returns 1 if the specified FILENAME # is a symlink or 0 otherwise. # # =item I # # returns the size of the specified FILENAME. # If USE_STAT_NOT_LSTAT is True, stat(2) is used instead of lstat(2). # # Return value: # -2 if file doesn't exist # -1 if file is not a regular file # filesize otherwise # # =item I # # returns a single letter that corrspond to the file # type. If USE_STAT_NOT_LSTAT is True, stat(2) is used instead of lstat(2). # # Return value: # - -- regular file # d -- directory # c -- character device # b -- block device # p -- FIFO # l -- symlink # s -- socket # # =back # # See example/demo_io for the sample of usage # #use "shquote.awk" function is_file (fn){ return !system("test -f " shquote(fn)) } function is_socket (fn){ return !system("test -S " shquote(fn)) } function is_dir (fn){ return !system("test -d " shquote(fn)) } function is_exec (fn){ return !system("test -x " shquote(fn)) } function is_fifo (fn){ return !system("test -p " shquote(fn)) } function is_blockdev (fn){ return !system("test -b " shquote(fn)) } function is_chardev (fn){ return !system("test -c " shquote(fn)) } function is_symlink (fn){ return !system("test -h " shquote(fn)) } function file_size (fn, stat, d0,arr,cmd){ cmd = "ls -ld " (stat ? "-L " : "") shquote(fn) " 2>/dev/null" if (0 < (cmd | getline d0)){ close(cmd) if (d0 ~ /^-/){ split(d0, arr, " ") return arr [5] }else{ return -1; } }else{ close(cmd) return -2 } } function file_type (fn, stat, d0,cmd){ cmd = "ls -ld " (stat ? "-L " : "") shquote(fn) " 2>/dev/null" if (0 < (cmd | getline d0)){ close(cmd) return substr(d0, 1, 1) }else{ close(cmd) return "" } } runawk-runawk-1.6.1/modules/isnum.awk000066400000000000000000000005731343160141100176410ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 isnum.awk # # =over 2 # # =item I # # returns 1 if an argument is a number # # =back # function isnum (v){ return v == v + 0 } runawk-runawk-1.6.1/modules/match_br.awk000066400000000000000000000017541343160141100202670ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 match_br.awk # # =over 2 # # =item I # # return start position (or zero if failure) of the substring # surrounded by balanced (), [], {} or similar characters # Also sets RSTART and RLENGTH variables just like # the standard 'match' function does # # For example: # print match_br("A (B (), C(D,C,F (), 123))", "(", ")") # print RSTART, RLENGTH # -| 3 # -| 3 # -| 24 # # =back # function match_br (s, br_open, br_close, len,i,cnt){ len = length(s) cnt = 0 for (i=1; i <= len; ++i){ ch = substr(s, i, 1) if (ch == br_open){ if (cnt == 0){ RSTART = i } ++cnt }else if (ch == br_close){ --cnt if (cnt == 0){ RLENGTH=i-RSTART+1 return RSTART } } } return 0 } runawk-runawk-1.6.1/modules/max.awk000066400000000000000000000027761343160141100173020ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 max.awk # # =over 2 # # =item I # # maximum functions # # =item I # # returns a maximum key in HASH or DFLT if it is empty # # =item I # # returns a maximum value in HASH or DFLT if it is empty # # =item I # # returns A KEY OF maximum value in HASH or DFLT if it is empty # # =back # function max (a, b){ return (a > b ? a : b) } function max3 (a, b, c, m){ m = (a > b ? a : b) return (m > c ? m : c) } function max4 (a, b, c, d, m){ m = (a > b ? a : b) m = (m > c ? m : c) return (m > d ? m : d) } function max5 (a, b, c, d, e, m){ m = (a > b ? a : b) m = (m > c ? m : c) m = (m > d ? m : d) return (m > e ? m : e) } function max_key(hash, dflt, i){ for (i in hash){ dflt = i break } for (i in hash){ if (i > dflt) dflt = i } return dflt } function max_value(hash, dflt, i){ for (i in hash){ dflt = hash [i] break } for (i in hash){ if (hash [i] > dflt) dflt = hash [i] } return dflt } function key_of_max_value(hash, dflt, i,v){ for (i in hash){ dflt = i v = hash [i] break } for (i in hash){ if (hash [i] > v){ dflt = i v = hash [i] } } return dflt } runawk-runawk-1.6.1/modules/min.awk000066400000000000000000000027751343160141100172770ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 min.awk # # =over 2 # # =item I # # minimum functions # # =item I # # returns a minimum key in HASH or DFLT if it is empty # # =item I # # returns a minimum value in HASH or DFLT if it is empty # # =item I # # returns A KEY OF minimum value in HASH or DFLT if it is empty # # =back # function min (a, b){ return (a < b ? a : b) } function min3 (a, b, c, m){ m = (a < b ? a : b) return (m < c ? m : c) } function min4 (a, b, c, d, m){ m = (a < b ? a : b) m = (m < c ? m : c) return (m < d ? m : d) } function min5 (a, b, c, d, e, m){ m = (a < b ? a : b) m = (m < c ? m : c) m = (m < d ? m : d) return (m < e ? m : e) } function min_key(hash, dflt, i){ for (i in hash){ dflt = i break } for (i in hash){ if (i < dflt) dflt = i } return dflt } function min_value(hash, dflt, i){ for (i in hash){ dflt = hash [i] break } for (i in hash){ if (hash [i] < dflt) dflt = hash [i] } return dflt } function key_of_min_value(hash, dflt, i,v){ for (i in hash){ dflt = i v = hash [i] break } for (i in hash){ if (hash [i] < v){ dflt = i v = hash [i] } } return dflt } runawk-runawk-1.6.1/modules/modinfo.awk000066400000000000000000000013741343160141100201410ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 modinfo.awk # # This module provides the following variables # # =over 2 # # =item I # # A number of modules (-f ) passed to an awk interpreter # # =item I # # Array with [0..MODC) indexes of those modules # # =item I # # Path to the main module, i.e. program filename # # =back # # See example/demo_modinfo for the sample of usage # BEGIN { MODC = ENVIRON ["RUNAWK_MODC"] + 0 # force to number for (i=0; i < MODC; ++i){ MODV [i] = ENVIRON ["RUNAWK_MODV_" i] } MODMAIN = MODV [MODC-1] } runawk-runawk-1.6.1/modules/multisub.awk000066400000000000000000000046111343160141100203470ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 multisub.awk # # =over 2 # # =item I # # is a substitution function. It searches for # a list of substrings, specified in SUBST_REPL # in a left-most longest order and (if found) replaces # found fragments with appropriate replacement. # SUBST_REPL format: "SUBSTRING1:REPLACEMENT1 SUBSTRING2:REPLACEMENT2...". # Three spaces separate substring:replacement pairs from each other. # If KEEP is specified and some REPLACEMENT(N) is equal to it, then # appropriate SUBSTRING(N) is treated as a regular expression # and matched text is kept as is, i.e. not changed. # # For example: # print multisub("ABBABBBBBBAAB", "ABB:c BBA:d AB:e") # |- ccBBde # # =back # #use "alt_assert.awk" #use "str2regexp.awk" BEGIN { __runawk_multisub_num = -1 } function __runawk_multisub_prepare (repls, keep, arr, i, repl_left, repl_right, re) # local vars { if (!repls){ return -1 }else if (repls in __runawk_multisub){ return __runawk_multisub [repls] }else{ ++__runawk_multisub_num __runawk_multisub [repls] = __runawk_multisub_num split(repls, arr, / /) for (i in arr){ # split into 'repl_left' and 'repl_right' repl_right = repl_left = arr [i] sub(/:.*$/, "", repl_left) sub(/^.*:/, "", repl_right) # whole regexp if (re != ""){ re = re "|" } # substr to repl if (repl_right != keep){ __runawk_tr_repl [__runawk_multisub_num, repl_left] = repl_right repl_left = str2regexp(repl_left) } re = re repl_left } __runawk_tr_regexp [__runawk_multisub_num] = re return __runawk_multisub_num } } function multisub (str, repls, keep, n,middle,beg,end,ret,repl) #local vars { n = __runawk_multisub_prepare(repls, keep) if (n < 0 || !match(str, __runawk_tr_regexp [n])){ return str }else{ middle = substr(str, RSTART, RLENGTH) beg = substr(str, 1, RSTART-1) end = substr(str, RSTART+RLENGTH) if ((n SUBSEP middle) in __runawk_tr_repl) ret = beg __runawk_tr_repl [n, middle] multisub(end, repls) else ret = beg middle multisub(end, repls) return ret } } BEGIN { assert("ccBBde" == multisub("ABBABBBBBBAAB", "ABB:c BBA:d AB:e"), "Email bug to the author") } runawk-runawk-1.6.1/modules/pod_footer.txt000066400000000000000000000005111343160141100206730ustar00rootroot00000000000000=head1 AUTHOR Copyright (c) 2007-2014 Aleksey Cheusov =head1 BUGS/FEEDBACK Please send any comments, questions, bug reports etc. to me by e-mail or register them at sourceforge project home. Feature requests are also welcomed. =head1 HOME L =head1 SEE ALSO L runawk-runawk-1.6.1/modules/pod_header.txt000066400000000000000000000002171343160141100206300ustar00rootroot00000000000000=head1 NAME runawk - wrapper for AWK interpreter =head1 MODULES B provides dozens of modules. Below is the documentation for them. runawk-runawk-1.6.1/modules/pow.awk000066400000000000000000000005711343160141100173110ustar00rootroot00000000000000 # Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 pow.awk # # =over 2 # # =item I # # returns the value of X to the exponent Y # # =back # function pow (x, y){ return x ^ y } runawk-runawk-1.6.1/modules/power_getopt.awk000066400000000000000000000044241343160141100212230ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ #use "init_getopt.awk" # =head2 power_getopt.awk # # power_getopt.awk module provides a very easy way to add options # to AWK application and follows rules from # SUS/POSIX "Utility Syntax Guidelines" # # power_getopt.awk analyses '.begin-str help/.end-str' section in # AWK program (main module), and processes options specified there. # The following strings mean options: # -X single letter option # --XXX long option # -X|--XXX single letter option with long synonym # =X single letter option with argument # =-XXX long option with argument # =X|--XXX single letter option and long synonym with argument # # If --help option was applied, usage information is printed # (lines between ".begin-str help" and ".end-str") replacing leading # `=' character with `-'. # # =over 2 # # =item I # # returns either 1 (option OPT was applied) or 0 (OPT was not # applied) for options not accepting the argument, and either # specified value or DEFAULT for options accepting the argument. # # See example/demo_power_getopt for the sample of usage # # =back # function getarg (opt, dflt, tmp){ assert(opt in __getopt_opts, "Bad option `" opt "`") if (opt in long_opts){ tmp = long_opts [opt] if (tmp != "" && tmp != takes_arg) opt = tmp } if (opt in options){ return options [opt] }else if (__getopt_opts [opt] == takes_arg){ return dflt }else{ return 0 } } BEGIN { # options __getopt_fill = "\001getopt_fake\002" while (getopt(short_opts)){ if (optopt in long_opts){ _i = long_opts [optopt] if (_i != "" && _i != takes_arg) optopt = _i } if (__getopt_opts [optopt] == takes_arg) options [optopt] = optarg else ++options [optopt] } __getopt_to = 1 for (__getopt_from = 1; __getopt_from < ARGC; ++__getopt_from){ if (ARGV [__getopt_from] != __getopt_fill){ ARGV [__getopt_to++] = ARGV [__getopt_from] } } ARGC = __getopt_to if (("help" in options) || ("help" in long_opts) && (long_opts ["help"] in options)) { print_help() exitnow(0) } } runawk-runawk-1.6.1/modules/quicksort.awk000066400000000000000000000056561343160141100205410ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 quicksort.awk # # =over 2 # # =item I # # The content of `src_array' is sorted using awk's rules for # comparing values. Values with indices in range [start, end] are # sorted. `src_array' array is not changed. # Instead dest_remap array is generated such that # # Result: # src_array [dest_remap [start]] <= # <= src_array [dest_remap [start+1]] <= # <= src_array [dest_remap [start+2]] <= ... <= # <= src_array [dest_remap [end]] # # `quicksort' algorithm is used. # Examples: see demo_quicksort and demo_quicksort2 executables # # =item I # # The same as `quicksort' described above, but hash values are sorted. # # Result: # src_hash [dest_remap [1]] <= # <= src_hash [dest_remap [2]] <= # <= src_hash [dest_remap [3]] <= ... <= # <= src_hash [dest_remap [count]] # # `count', a number of elements in `src_hash', is a return value. # Examples: see demo_quicksort* executables. # # =item I # # The same as `quicksort' described above, but hash indices are sorted. # # Result: # dest_remap [1] <= # <= dest_remap [2] <= # <= dest_remap [3] <= ... <= # <= dest_remap [count] # # `count', a number of elements in `src_hash', is a return value. # # =back # function __quicksort (array, index_remap, start, end, MedIdx,Med,v,i,storeIdx) { if ((end - start) <= 0) return MedIdx = int((start+end)/2) Med = array [index_remap [MedIdx]] v = index_remap [end] index_remap [end] = index_remap [MedIdx] index_remap [MedIdx] = v storeIdx = start for (i=start; i < end; ++i){ if (array [index_remap [i]] < Med){ v = index_remap [i] index_remap [i] = index_remap [storeIdx] index_remap [storeIdx] = v ++storeIdx } } v = index_remap [storeIdx] index_remap [storeIdx] = index_remap [end] index_remap [end] = v __quicksort(array, index_remap, start, storeIdx-1) __quicksort(array, index_remap, storeIdx+1, end) } function quicksort (array, index_remap, start, end, i) { for (i=start; i <= end; ++i) index_remap [i] = i __quicksort(array, index_remap, start, end) } function quicksort_values (hash, remap_idx, array, remap, i, j, cnt) { cnt = 0 for (i in hash) { ++cnt array [cnt] = hash [i] remap [cnt] = i } quicksort(array, remap_idx, 1, cnt) for (i=1; i <= cnt; ++i) { remap_idx [i] = remap [remap_idx [i]] } return cnt } function quicksort_indices (hash, remap_idx, array, i, cnt) { cnt = 0 for (i in hash) { ++cnt array [cnt] = i } quicksort(array, remap_idx, 1, cnt) for (i=1; i <= cnt; ++i) { remap_idx [i] = array [remap_idx [i]] } return cnt } runawk-runawk-1.6.1/modules/readfile.awk000066400000000000000000000014331343160141100202550ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ #use "xgetline.awk" #use "xclose.awk" # =head2 readfile.awk # # =over 2 # # =item I # # read entire file and return its content as a string # # =back # # See example/demo_readfile for the sample of usage # function readfile (fn, ret){ # Unfortunately there is no way portable accross all awk flavours # to read an entire file content by single 'getline' command. # This is why I use loop here. ret = "" while (xgetline(fn)){ if (ret == "") ret = __input else ret = ret "\n" __input } xclose(fn) return ret } runawk-runawk-1.6.1/modules/runcmd.awk000066400000000000000000000016131343160141100177720ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 runcmd.awk # # =over 2 # # =item I # # wrapper for system() function # that runs a command CMD with options OPTS and one filename FILE. # Unlike system(CMD " " OPTS " " FILE) the function runcmd1 handles # correctly FILE containing spaces, single quote, double quote, # tilde etc. # # =item I # # safe wrapper for 'runcmd1'. # awk exits with error if runcmd1() function failed. # # =back # #use "alt_assert.awk" #use "shquote.awk" function runcmd1 (cmd, opts, file){ return system(shquote(cmd) " " opts " " shquote(file)) } function xruncmd1 (cmd, opts, file){ assert(runcmd1(cmd, opts, file) == 0, "runcmd1() failed") } runawk-runawk-1.6.1/modules/shquote.awk000066400000000000000000000020311343160141100201650ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 shquote.awk # # =over 2 # # =item I # # transforms the string `str' by adding shell escape and # quoting characters to include it to the system() and popen() # functions as an argument, so that the arguments will have the # correct values after being evaluated by the shell. # # For example: # print shquote("file name.txt") # |- 'file name.txt' # print shquote("'") # |- \' # print shquote("Peter's") # |- 'Peter'\''s' # print shquote("*&;<>#~") # |- '*&;<>#~' # # =back # # This module was inspired by NetBSD shquote(3) # http://netbsd.gw.com/cgi-bin/man-cgi?shquote+3+NetBSD-current # and shquote(1) by Alan Barrett # http://ftp.sunet.se/pub/os/NetBSD/misc/apb/shquote.20080906/ # function shquote (str){ gsub(/'/, "'\\''", str) return "'" str "'" } runawk-runawk-1.6.1/modules/sort.awk000066400000000000000000000040001343160141100174620ustar00rootroot00000000000000 # Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 sort.awk # # =over 2 # # =item I # # Call either heapsort function from heapsort.awk (if # RUNAWK_SORTTYPE environment variable is "heapsort") or quicksort # from quicksort.awk (if RUNAWK_SORTTYPE is "quicksort"). # Sorttype defaults to "heapsort". # # =item I # # Call either heapsort_values function from heapsort.awk (if # RUNAWK_SORTTYPE environment variable is "heapsort") or # quicksort_values from quicksort.awk (if RUNAWK_SORTTYPE is # "quicksort"). Sorttype defaults to "heapsort". # # =item I # # Call either heapsort_indices function from heapsort.awk (if # RUNAWK_SORTTYPE environment variable is "heapsort") or # quicksort_indices from quicksort.awk (if RUNAWK_SORTTYPE is # "quicksort"). Sorttype defaults to "heapsort". # # =back # #use "abort.awk" #use "heapsort.awk" #use "quicksort.awk" BEGIN { if (!__sort_type) __sort_type = ENVIRON ["RUNAWK_SORTTYPE"] if (!__sort_type) __sort_type = "heapsort" } function sort (array, index_remap, start, end) { if (__sort_type == "heapsort") heapsort(array, index_remap, start, end); else if (__sort_type == "quicksort") quicksort(array, index_remap, start, end); else abort("Bad __sort_type in sort.awk") } function sort_values (src_hash, index_remap) { if (__sort_type == "heapsort") return heapsort_values(src_hash, index_remap); else if (__sort_type == "quicksort") return quicksort_values(src_hash, index_remap); else abort("Bad __sort_type in sort.awk") } function sort_indices (src_hash, index_remap) { if (__sort_type == "heapsort") return heapsort_indices(src_hash, index_remap); else if (__sort_type == "quicksort") return quicksort_indices(src_hash, index_remap); else abort("Bad __sort_type in sort.awk") } runawk-runawk-1.6.1/modules/str2regexp.awk000066400000000000000000000022011343160141100206010ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 str2regexp.awk # # =over 2 # # =item I # # returns a regular expression that matches given STRING # # =back # # For example: # print str2regexp("all special symbols: ^$(){}[].*+?|\\") # -| all special symbols: [^][$][(][)][{][}][[]\][.][*][+][?][|]\\ # #use "alt_assert.awk" function __runawk_mawk_bug_test (tmp){ # returns true if buggy MAWK tmp = "\\\\" gsub(/\\/, "\\\\", tmp) return (tmp != "\\\\\\\\") } BEGIN { __buggy_mawk = __runawk_mawk_bug_test() } function str2regexp (s){ gsub(/\[/, "---runawk-open-sq-bracket---", s) gsub(/\]/, "---runawk-close-sq-bracket---", s) gsub(/[?{}|()*+.$]/, "[&]", s) gsub(/\^/, "[\\^]", s) if (s ~ /\\/){ if (!__buggy_mawk){ # normal AWK gsub(/\\/, "\\\\", s) }else{ # MAWK /-( gsub(/\\/, "\\\\\\\\\\", s) } } gsub(/---runawk-open-sq-bracket---/, "\\[", s) gsub(/---runawk-close-sq-bracket---/, "\\]", s) return s } runawk-runawk-1.6.1/modules/tmpfile.awk000066400000000000000000000017761343160141100201540ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 tmpfile.awk # # This module provides a function `tmpfile' for generating temporary # filenames. All these filenames are under temporary directory created # (if necessary) by runawk(1) which is removed automatically during # normal exit or when runawk(1) reveives SIGINT, SIGQUIT, SIGTERM, # SIGHUP or SIGPIPE. # # =over 2 # # =item I # # returns a temporary file name. # # =item I # # global variable that keeps tempdir created by runawk -t # # =back # # See example/demo_tmpfile for the sample of usage # #use "alt_assert.awk" BEGIN { runawk_tmpdir = ENVIRON ["_RUNAWK_TMPDIR"] assert(runawk_tmpdir != "", "_RUNAWK_TMPDIR is unset! This should not happen.") _runawk_tmpdir_cnt = 0 } function tmpfile (){ return (runawk_tmpdir "/" _runawk_tmpdir_cnt++) } runawk-runawk-1.6.1/modules/tokenre.awk000066400000000000000000000030521343160141100201500ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 tokenre.awk # # By default AWK splits input lines into tokens according to regular # expression that defines "spaces" between tokens using special # variable FS. In many situations it is more useful to define regular # expressions for tokens themselves. This is what this module does. # # =over 2 # # =item I # # extracts substrings from STRING # according to REGEXP from the left to the right and assigns $1, $2 # etc. and NF variable. # # =item I # # Does the the same as `tokenre' but splits $0 instead. # # =item I # # The same as `tokenre' but ARR[1], ARR[2]... are assigned. # A number of extracted tokens is a return value. # # =item I # # global variable. If it is set to non-empty string, all input # lines are split automatically. # # =back # # See example/demo_tokenre for the sample of usage function tokenre (s, re){ NF = 0 while (match(s, re)){ ++NF $NF = substr(s, RSTART, RLENGTH) s = substr(s, RSTART+RLENGTH) } } function tokenre0 (re){ tokenre($0, re) } function splitre (s, arr, re, cnt){ cnt = 0 while (match(s, re)){ ++cnt arr [cnt] = substr(s, RSTART, RLENGTH) s = substr(s, RSTART+RLENGTH) } return cnt } function splitre0 (arr, re){ return splitre($0, arr, re) } { if (TRE != ""){ tokenre0(TRE) } } runawk-runawk-1.6.1/modules/trim.awk000066400000000000000000000024661343160141100174640ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 trim.awk # # =over 2 # # =item I # # Removes leading Tab and Space characters from STRING and returns # the result. # # =item I # # Removes Tab and Space characters at the end of STRING and returns # the result. # # =item I # # Replaces sequences of Tab and Space characters in STRING with REPL # and returns the result. If REPL is not specified, it defaults to # single Space character. # # =item I # # Equal to trim_l(trim_r(STRING)) # # =item I # # Equal to trim_l(trim_r(trim_c(STRING, REPL))) # # =back # # See example/demo_trim for the sample of usage # function trim_l (s){ sub(/^[ \t]+/, "", s) return s } function trim_r (s){ sub(/[ \t]+$/, "", s) return s } function trim_c (s, repl){ if (repl == "") repl = " " gsub(/[ \t][ \t]+/, repl, s) return s } function trim_lr (s){ sub(/[ \t]+$/, "", s) sub(/^[ \t]+/, "", s) return s } function trim_lrc (s, repl){ if (repl == "") repl = " " gsub(/[ \t][ \t]+/, repl, s) sub(/[ \t]+$/, "", s) sub(/^[ \t]+/, "", s) return s } runawk-runawk-1.6.1/modules/trim_in.awk000066400000000000000000000020071343160141100201410ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 trim_in.awk # # As the name of this module says (_in suffix) this module reads and # potentially changes input lines. # # Leading, ending spaces and/or spaces in the middle of input lines # are removed depending on TRIM variable. # TRIM values: # "l" - remove leading space characters # "r" - remove ending space characters # "c" - remove extra space characters in the middle of input lines # "lr" - See l and r # "lrc" - See l, r and c # "lc" - See l and c # "cr" - See c and r # By default TRIM variable is set to "lr". TRIM set to a single space # character means no trimming. # BEGIN { if (TRIM == ""){ TRIM = "lr" } } { if (index(TRIM, "c") > 0) gsub(/[ \t][ \t]+/, " ") if (index(TRIM, "l") > 0) sub(/^[ \t]+/, "") if (index(TRIM, "r") > 0) sub(/[ \t]+$/, "") } runawk-runawk-1.6.1/modules/xclose.awk000066400000000000000000000007371343160141100200050ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 xclose.awk # # =over 2 # # =item I # # safe wrapper for 'close'. # awk exits with error if close() function failed. # # =back # #use "alt_assert.awk" function xclose (fn){ assert(close(fn) == 0, "close(\"" fn "\") failed") } runawk-runawk-1.6.1/modules/xgetline.awk000066400000000000000000000026141343160141100203230ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 xgetline.awk # # =over 2 # # =item I # # Safe analog to 'getline < FILE' or 'getline' (if no FILE is specified). # 0 at the end means that input line is assigned to $0. # # =item I # # Safe analog to 'getline __input < FILE' and 'getline __input' # (if no FILE is specified) # # =back # # In both cases "safe" means that returned value is analysed and # if it is less than zero (file reading error happens) program will # be terminated emmidiately with appropriate error message sent to stderr. # Both functions return zero if end of file is reached or non-zero otherwise. # # Example: # while (xgetline("/etc/passwd")){ # print "user: " __input # } # #use "alt_assert.awk" function xgetline0 (fn, ret){ if (fn == ""){ ret = getline assert(ret >= 0, "getline failed") }else{ ret = (getline < fn) assert(ret >= 0, "getline < " fn " failed") } return (ret > 0) } function xgetline (fn, ret){ if (fn == ""){ ret = getline __input assert(ret >= 0, "getline failed") }else{ ret = (getline __input < fn) assert(ret >= 0, "getline < " fn " failed") } return (ret > 0) } runawk-runawk-1.6.1/modules/xsystem.awk000066400000000000000000000007461343160141100202240ustar00rootroot00000000000000# Written by Aleksey Cheusov , public domain # # This awk module is a part of RunAWK distribution, # http://sourceforge.net/projects/runawk # ############################################################ # =head2 xsystem.awk # # =over 2 # # =item I # # safe wrapper for 'system'. # awk exits with error if system() function failed. # # =back # #use "alt_assert.awk" function xsystem (fn){ assert(system(fn) == 0, "system(\"" fn "\") failed") } runawk-runawk-1.6.1/runawk/000077500000000000000000000000001343160141100156345ustar00rootroot00000000000000runawk-runawk-1.6.1/runawk/Makefile000066400000000000000000000022121343160141100172710ustar00rootroot00000000000000################################################## # default directory for creating temp files and dirs TEMPDIR = /tmp .if !defined(AWK_PROG) .if exists(/usr/xpg4/bin/awk) # Solaris' /usr/bin/awk sucks so much... :-( # /usr/xpg4/bin/awk sucks too but sucks less. # I'd recommend you use GNU awk, nawk from NetBSD cvs tree # or mawk-1.3.4 or later. AWK_PROG = /usr/xpg4/bin/awk .else MKC_REQUIRE_PROGS += awk AWK_PROG = ${PROG.awk} .endif .endif # !defined(AWK_PROG) STDIN_FILENAME?= - #/dev/stdin ################################################## WARNS ?= 4 WARNERR ?= no PROG = runawk SRCS = runawk.c dynarray.c file_hier.c MAN = runawk.1 MKC_FEATURES = strlcpy strlcat CFLAGS += -DAWK_PROG='"${AWK_PROG}"' CFLAGS += -DSTDIN_FILENAME='"${STDIN_FILENAME}"' CFLAGS += -DMODULESDIR='"${MODULESDIR}:${MODULESDIR}/gawk"' CFLAGS += -DRUNAWK_VERSION='"${VERSION}"' CFLAGS += -DTEMPDIR='"${TEMPDIR}"' CLEANFILES += *~ core* *.core ktrace* *.tmp tests/_* *.html1 *.cat1 *.1 CLEANFILES += ChangeLog runawk.html _test.res .PHONY: _manpages _manpages: ${MAN} ################################################## .include runawk-runawk-1.6.1/runawk/common.h000066400000000000000000000024761343160141100173060ustar00rootroot00000000000000/* * Copyright (c) 2012-2014 Aleksey Cheusov * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _COMMON_H_ #define _COMMON_H_ #include #include #ifndef PATH_MAX #define PATH_MAX 4096 /* Some systems doesn't have PATH_MAX */ #endif #endif // _COMMON_H_ runawk-runawk-1.6.1/runawk/dynarray.c000066400000000000000000000040421343160141100176310ustar00rootroot00000000000000/* * Copyright (c) 2011-2014 Aleksey Cheusov * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include "common.h" #include "dynarray.h" void da_init (dynarray_t * array) { array->size = 0; array->allocated = 0; array->array = NULL; } void da_push (dynarray_t * array, char *item) { if (array->allocated == array->size){ array->allocated = array->allocated * 4 / 3 + 100; array->array = realloc ( array->array, array->allocated * sizeof (*array->array)); } array->array [array->size++] = item; } void da_push_dup (dynarray_t * array, const char *item) { char *dup = (item ? strdup (item) : NULL); da_push (array, dup); } void da_free_items (dynarray_t * array) { size_t i; for (i=0; i < array->size; ++i){ if (array->array [i]){ free ((void *) array->array [i]); array->array [i] = NULL; } } } void da_destroy (dynarray_t * array) { if (array->array) free (array->array); array->array = NULL; array->size = 0; array->allocated = 0; } runawk-runawk-1.6.1/runawk/dynarray.h000066400000000000000000000027471343160141100176500ustar00rootroot00000000000000/* * Copyright (c) 2011-2012 Aleksey Cheusov * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _DYNARRAY_H_ #define _DYNARRAY_H_ typedef struct { size_t size; size_t allocated; char **array; } dynarray_t; void da_init (dynarray_t * array); void da_push (dynarray_t * array, char *item); void da_push_dup (dynarray_t * array, const char *item); void da_destroy (dynarray_t * array); void da_free_items (dynarray_t * array); #endif /* _DYNARRAY_H_ */ runawk-runawk-1.6.1/runawk/file_hier.c000066400000000000000000000045051343160141100177320ustar00rootroot00000000000000/* * Copyright (c) 2012-2014 Aleksey Cheusov * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include "common.h" #include "file_hier.h" void file_hier ( const char *dir, void (*proc_file) (const char *fn), void (*proc_dir) (const char *fn)) { char buffer [PATH_MAX]; size_t dir_len = strlen (dir)+1; struct stat sb; struct dirent *dp; DIR *dirp; if (dir_len+1 > sizeof (buffer)){ return; } dirp = opendir(dir); if (dirp != NULL) { strlcpy (buffer, dir, sizeof (buffer)); strlcat (buffer, "/", sizeof (buffer)); while (dp = readdir(dirp), dp != NULL){ if (dp->d_name [0] == '.'){ if (dp->d_name [1] == 0 || (dp->d_name [1] == '.' && dp->d_name [2] == 0)) { /* ignore . and .. */ continue; } } buffer [dir_len] = 0; strlcat (buffer, dp->d_name, sizeof (buffer)); if (0 == lstat (buffer, &sb)){ if (S_ISDIR (sb.st_mode)){ file_hier (buffer, proc_file, proc_dir); }else{ proc_file (buffer); } }else{ fprintf (stderr, "stat(\"%s\") failed: %s\n", buffer, strerror (errno)); } } closedir (dirp); proc_dir (dir); }else{ fprintf (stderr, "opendir(\"%s\") failed: %s\n", dir, strerror (errno)); } } runawk-runawk-1.6.1/runawk/file_hier.h000066400000000000000000000024501343160141100177340ustar00rootroot00000000000000/* * Copyright (c) 2012 Aleksey Cheusov * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _FILE_HIER_H_ #define _FILE_HIER_H_ void file_hier ( const char *dir, void (*proc_file) (const char *fn), void (*proc_dir) (const char *fn)); #endif /* _FILE_HIER_H_ */ runawk-runawk-1.6.1/runawk/runawk.c000066400000000000000000000367551343160141100173270ustar00rootroot00000000000000/* * Copyright (c) 2007-2014 Aleksey Cheusov * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include "common.h" #include "dynarray.h" #include "file_hier.h" #ifndef BUFSIZ #define BUFSIZ 4096 #endif #ifndef STDIN_FILENAME #define STDIN_FILENAME "/dev/stdin" #endif #ifndef AWK_PROG #define AWK_PROG "awk" #endif #ifndef ARRAY_SZ #define ARRAY_SZ 1000 #endif #ifndef RUNAWK_VERSION #define RUNAWK_VERSION "x.y.z" #endif #ifndef TEMPDIR #define TEMPDIR "/tmp" #endif #ifndef MODULESDIR #define MODULESDIR "/usr/local/share/runawk" #endif static void usage (void) { puts ("\ runawk - wrapper for an AWK interpreter\n\ usage: runawk [OPTIONS] program_file [arguments...]\n\ runawk [OPTIONS] -e program [arguments...]\n\ OPTIONS:\n\ -h display this screen\n\ -V display version information\n\ -d debugging mode, list argv array for awk and\n\ do not run AWK interpreter\n\ -e program to run\n\ -v assign the value val to the variable var\n\ -f add awk_module to a program\n\ -t create a temporary directory and pass it to\n\ AWK interpreter subprocess\n\ "); } static const char *runawk_version = RUNAWK_VERSION; static void version (void) { printf ("runawk %s written by Aleksey Cheusov\n", runawk_version); } static int create_tmpdir = 0; static pid_t awk_pid = -1; static int killing_sig = 0; static int double_dash = 0; static char temp_fn [PATH_MAX] = "/tmp/runawk.XXXXXX"; static int temp_fn_created = 0; static char *temp_dir = NULL; static char *awkpath = NULL; static size_t awkpath_len = 0; static char cwd [PATH_MAX]; static const char *interp = AWK_PROG; static const char *sys_awkdir = MODULESDIR; static char *interp_var = NULL; static int debug = 0; static dynarray_t new_argv; static dynarray_t includes; static void remove_file (const char *fn) { if (unlink (fn)){ fprintf (stderr, "unlink(\"%s\") failed: %s\n", fn, strerror (errno)); } } static void remove_dir (const char *dir) { if (rmdir (dir)){ fprintf (stderr, "rmdir(\"%s\") failed: %s\n", dir, strerror (errno)); } } static void clean_and_exit (int status) { const char *keep = getenv ("RUNAWK_KEEPTMP"); if (!keep && temp_fn_created) unlink (temp_fn); if (temp_dir){ if (!keep) file_hier (temp_dir, remove_file, remove_dir); if (temp_dir) free (temp_dir); } if (awkpath) free (awkpath); if (killing_sig) exit (128 + killing_sig); else exit (status); } static void mktempdir (void) { const char *dir = getenv ("RUNAWK_TMPDIR"); if (!dir) dir = getenv ("TMPDIR"); if (!dir) dir = TEMPDIR; temp_dir = tempnam (dir, "awk."); if (!temp_dir){ perror ("tempnam(3) failed"); clean_and_exit (52); } if (mkdir (temp_dir, 0700)){ perror ("mkdir(3) failed"); clean_and_exit (53); } } static char *xstrdup (const char *s) { char *ret = strdup (s); if (!ret){ perror ("strdup(3) failed"); clean_and_exit (33); } return ret; } static void *xmalloc (size_t size) { char *ret = malloc (size); if (!ret){ perror ("malloc(3) failed"); clean_and_exit (33); } return ret; } static void xputenv (char *s) { if (putenv (s)){ perror ("putenv(3) failed"); clean_and_exit (43); } } static const char *search_file (const char *dir, const char *name) { /* search in AWKPATH env. */ const char *curr_dir = NULL; char buf [PATH_MAX]; size_t i; /* dir argument */ snprintf (buf, sizeof (buf), "%s/%s", dir, name); if (!access (buf, R_OK)){ return xstrdup (buf); } /* AWKPATH env. and system paths */ for (i = 0; i < awkpath_len; ++i){ if (awkpath [i] && (i == 0 || awkpath [i-1] == 0)){ curr_dir = awkpath + i; snprintf (buf, sizeof (buf), "%s/%s", curr_dir, name); if (!access (buf, R_OK)){ return xstrdup (buf); } } } return NULL; } static void invalid_directive (int num, const char *line, const char *fn) { char *copy = xstrdup (line); char * nl = strchr (copy, '\n'); if (nl) *nl = 0; fprintf (stderr, "error: invalid directive at line #%d,\n line=`%s`\n file=`%s`\n", num, copy, fn); free (copy); } static int add_file_uniq (const char *dir, const char *name, int safe_use); static char *extract_qstring ( const char *line, int line_num, const char *fn, const char *s) { const char *p = NULL; const char *n = NULL; char *ret = NULL; size_t len = 0; p = s + strspn (s, " "); if (*p != '"'){ invalid_directive (line_num, line, fn); clean_and_exit (37); } ++p; n = strpbrk (p, "\"\n"); if (!n || *n == '\n'){ invalid_directive (line_num, line, fn); clean_and_exit (37); } len = n - p; ret = xmalloc (len+1); memcpy ((void *) ret, (const void *) p, len); ret [len] = 0; return ret; } static int add_file_uniq_safe (const char *dir, const char *name) { char buffer [4000]; const char *fn; if (name [0] == '~'){ snprintf (buffer, sizeof (buffer), "%s%s", getenv ("HOME"), name+1); fn = buffer; }else{ fn = name; } return add_file_uniq (dir, fn, 1); } typedef enum { qstr_spaces, qstr_str } qstr_state_t; static void list_of_qstrings ( const char *dir, int line_num, const char *fn, const char *line, const char *s, int (*fun) (const char *dir, const char *name)) { char buffer [2000]; const char *p; const char *start = NULL; size_t len; int state = qstr_spaces; int success = 0; for (p=s; *p; ++p){ switch (state){ case qstr_spaces: switch (*p){ case ' ': case '\t': case '\r': break; case '\n': goto eol; case '"': state = qstr_str; start = p+1; break; default: invalid_directive (line_num, line, fn); clean_and_exit (51); } break; case qstr_str: switch (*p){ case '"': len = p-start; if (len+1 > sizeof (buffer)) len = sizeof (buffer) - 1; memcpy (buffer, start, len); buffer [len] = 0; state = qstr_spaces; success = (success || fun (dir, buffer)); break; default: break; } break; } } eol: if (state == qstr_str){ invalid_directive (line_num, line, fn); clean_and_exit (52); } } static void scan_buffer ( const char *name, const char *dir, const char *buffer, off_t sz, int allow_spaces) { char *env_str = NULL; const char *p = buffer; int line_num = 1; for (; sz--; ++p){ if (*p == '\n') ++line_num; if (*p != '#') continue; if (p != buffer){ if (allow_spaces){ switch (p[-1]){ case '\n': case ' ': case '\t': break; default: continue; } }else{ if (p [-1] != '\n') continue; } } if (!strncmp (p, "#use ", 5)){ add_file_uniq (dir, extract_qstring (p, line_num, name, p + 5), 0); }else if (!strncmp (p, "#safe-use ", 10)){ list_of_qstrings (dir, line_num, name, p, p+10, add_file_uniq_safe); }else if (!strncmp (p, "#interp ", 8)){ interp = extract_qstring (p, line_num, name, p + 8); }else if (!strncmp (p, "#interp-var ", 12)){ interp_var = extract_qstring (p, line_num, name, p + 12); }else if (!strncmp (p, "#env ", 5)){ env_str = (char *) extract_qstring (p, line_num, name, p + 5); xputenv (env_str); } } } static int scan_file (const char *name, int safe_use) { char dir [PATH_MAX]; FILE *fd = NULL; size_t len = 0; struct stat stat_buf; char *buffer = NULL; off_t file_size = 0; size_t n = 0; /**/ len = strlen (name); strncpy (dir, name, sizeof (dir)); while (len--){ if (dir [len] == '/'){ dir [len] = 0; break; } } /**/ if (stat (name, &stat_buf)){ if (safe_use) return 0; fprintf (stderr, "stat(\"%s\") failed: %s\n", name, strerror (errno)); clean_and_exit (35); } file_size = stat_buf.st_size; fd = fopen (name, "r"); if (!fd){ fprintf (stderr, "fopen(%s) failed: %s\n", name, strerror (errno)); clean_and_exit (35); } buffer = xmalloc (file_size + 1); n = fread (buffer, 1, file_size, fd); if (n < (size_t) file_size){ perror ("fread(3) failed"); clean_and_exit (35); } buffer [file_size] = 0; scan_buffer (name, dir, buffer, file_size, 0); free (buffer); if (fclose (fd)){ perror ("fclose(3) failed"); clean_and_exit (36); } return 1; } static void add_buffer (const char *buffer, size_t len) { int fd = -1; /* recursive snanning for #xxx directives */ scan_buffer ("", "-", buffer, len, 1); if (includes.size == 0 && !double_dash){ da_push_dup (&new_argv, buffer); }else{ fd = mkstemp (temp_fn); temp_fn_created = 1; if (fd == -1){ perror ("mkstemp(3) failed"); clean_and_exit (40); } if (write (fd, buffer, len) != (ssize_t) len){ perror ("write(2) failed"); clean_and_exit (40); } if (close (fd)){ perror ("close(2) failed"); clean_and_exit (40); } /* add to queue */ da_push_dup (&new_argv, "-f"); da_push_dup (&new_argv, temp_fn); da_push_dup (&includes, temp_fn); } } static int add_file (const char *dir, const char *name, int safe_use) { const char *new_name = NULL; size_t len; if (name [0] != '/'){ /* name -> path */ new_name = search_file (dir, name); if (!new_name){ if (safe_use) return 0; fprintf (stderr, "Cannot find module `%s`, check AWKPATH environment variable\n", name); clean_and_exit (34); } name = new_name; } /* recursive snanning for #xxx directives */ if (scan_file (name, safe_use)){ /* add to queue */ len = strlen (name); if (len > 11 && !strcmp (name+len-12, "/tmpfile.awk")){ create_tmpdir = 1; } da_push_dup (&new_argv, "-f"); da_push_dup (&new_argv, name); da_push_dup (&includes, name); return 1; }else{ return 0; } } static int add_file_uniq ( const char *dir, const char *name, int safe_use) { size_t i; const char *p; const char *inc; for (i=0; i < includes.size; ++i){ inc = includes.array [i]; p = strstr (inc, name); if (p && (p == inc || (p [-1] == '/' && p [strlen (p)] == 0))){ return 1; } } return add_file (dir, name, safe_use); } static void handler (int sig) { killing_sig = sig; if (awk_pid != -1){ kill (awk_pid, sig); } } static void set_sig_handler (void) { static const int sigs [] = { SIGINT, SIGQUIT, SIGTERM, SIGHUP, SIGPIPE }; struct sigaction sa; size_t i; sa.sa_handler = handler; sigemptyset (&sa.sa_mask); sa.sa_flags = 0; for (i=0; i < sizeof (sigs)/sizeof (sigs [0]); ++i){ int sig = sigs [i]; sigaction (sig, &sa, NULL); } } static void putenv_RUNAWK_MODx (void) { size_t i; char buf [30 + PATH_MAX]; /* RUNAWK_MODC */ snprintf (buf, sizeof (buf), "RUNAWK_MODC=%u", (unsigned) includes.size); xputenv (xstrdup (buf)); /* RUNAWK_MODV */ for (i=0; i < includes.size; ++i){ snprintf (buf, sizeof (buf), "RUNAWK_MODV_%u=%s", (unsigned) i, includes.array [i]); xputenv (xstrdup (buf)); } } int main (int argc, char **argv) { char buffer [4000]; const char *progname = NULL; int child_status = 0; const char *env_interp = getenv ("RUNAWK_AWKPROG"); const char *prog_specified = NULL; const char *awkpath_env = NULL; int c; size_t i; size_t j; da_init (&new_argv); da_init (&includes); set_sig_handler (); /* environment RUNAWK_AWKPROG overrides compile-time option */ if (env_interp){ interp = env_interp; } if (argc == 0){ usage (); return 30; } /* AWKPATH env. */ awkpath_env = getenv ("AWKPATH"); if (!awkpath_env) awkpath_env = ""; awkpath_len = strlen (awkpath_env) + 1 + strlen (sys_awkdir); awkpath = xmalloc (awkpath_len + 1); snprintf (awkpath, awkpath_len + 1, "%s:%s", awkpath_env, sys_awkdir); for (j=0; j < awkpath_len; ++j){ if (awkpath [j] == ':'){ awkpath [j] = 0; } } /* cwd */ if (!getcwd (cwd, sizeof (cwd))){ perror ("getcwd (3) failed"); clean_and_exit (32); } da_push_dup (&new_argv, NULL); /* progname */ while (c = getopt (argc, argv, "+de:f:F:htTVv:"), c != EOF){ switch (c){ case 'd': debug = 1; break; case 'e': if (prog_specified){ fprintf (stderr, "multiple -e are not allowed\n"); clean_and_exit (39); } prog_specified = optarg; break; case 'F': da_push_dup (&new_argv, "-F"); da_push_dup (&new_argv, optarg); break; case 'f': add_file (cwd, optarg, 0); break; case 'h': usage (); clean_and_exit (0); break; case 't': create_tmpdir = 1; break; case 'T': da_push_dup (&new_argv, "-F"); da_push_dup (&new_argv, "\t"); break; case 'v': da_push_dup (&new_argv, "-v"); da_push_dup (&new_argv, optarg); break; case 'V': version (); clean_and_exit (0); break; default: usage (); exit (1); } } argv += optind; argc -= optind; progname = interp; /* */ if (prog_specified){ add_buffer (prog_specified, strlen (prog_specified)); }else{ /* program_file */ if (argc < 1){ usage (); clean_and_exit (30); } add_file (cwd, *argv, 0); progname = *argv; #if 0 setprogname (*argv); setproctitle (*argv); #endif --argc; ++argv; } /* AWK interpreter name */ if (interp_var) interp_var = getenv (interp_var); if (interp_var && interp_var [0]) interp = interp_var; /* exec */ new_argv.array [0] = xstrdup (progname); if (includes.size) da_push_dup (&new_argv, "--"); for (i=0; i < (size_t) argc; ++i){ da_push_dup (&new_argv, argv [i]); } da_push_dup (&new_argv, NULL); putenv_RUNAWK_MODx (); /* create temporary directory */ if (create_tmpdir){ mktempdir (); snprintf (buffer, sizeof (buffer), "_RUNAWK_TMPDIR=%s", temp_dir); xputenv (buffer); } /**/ if (debug){ for (i=0; i < new_argv.size - 1; ++i){ printf ("new_argv [%u] = %s\n", (unsigned) i, new_argv.array [i]); } }else{ awk_pid = fork (); switch (awk_pid){ case -1: perror ("fork(2) failed"); clean_and_exit (42); break; case 0: /* child */ execvp (interp, (char *const *) new_argv.array); fprintf (stderr, "running '%s' failed: %s\n", interp, strerror (errno)); exit (1); break; default: /* parent */ waitpid (-1, &child_status, 0); da_free_items (&new_argv); da_destroy (&new_argv); da_free_items (&includes); da_destroy (&includes); if (killing_sig){ clean_and_exit (0); }else if (WIFSIGNALED (child_status)){ clean_and_exit (128 + WTERMSIG (child_status)); }else if (WIFEXITED (child_status)){ clean_and_exit (WEXITSTATUS (child_status)); }else{ clean_and_exit (200); } } } clean_and_exit (0); return 0; /* this should not happen but fixes gcc warning */ } runawk-runawk-1.6.1/runawk/runawk.pod000066400000000000000000000244351343160141100176570ustar00rootroot00000000000000=head1 NAME runawk - wrapper for AWK interpreter =head1 SYNOPSIS B I<[options]> I B I<-e> I =head1 MOTIVATION After years of using AWK for programming I've found that despite of its simplicity and limitations AWK is good enough for scripting a wide range of different tasks. AWK is not as poweful as their bigger counterparts like Perl, Ruby, TCL and others but it has their own advantages like compactness, simplicity and availability on almost all UNIX-like systems. I personally also like its data-driven nature and token orientation, very useful techniques for text processing utilities. Unfortunately awk interpreters lacks some important features and sometimes do not work as good as they could do. Problems I see (some of them, of course) =over 2 =item 1 AWK lacks support for modules. Even if I create small programs, I often want to use functions created earlier and already used in other scripts. That is, it whould great to organise functions into so called libraries (modules). =item 2 In order to pass arguments to C<#!/usr/bin/awk -f> script (not to awk interpreter), it is necessary to prepend a list of arguments with -- (two minus signes). In my view, this looks badly. Also such behaviour violates POSIX/SUS "Utility Syntax Guidelines". Example: awk_program: #!/usr/bin/awk -f BEGIN { for (i=1; i < ARGC; ++i){ printf "ARGV [%d]=%s\n", i, ARGV [i] } } Shell session: % awk_program --opt1 --opt2 /usr/bin/awk: unknown option --opt1 ignored /usr/bin/awk: unknown option --opt2 ignored % awk_program -- --opt1 --opt2 ARGV [1]=--opt1 ARGV [2]=--opt2 % In my opinion I script should work like this % awk_program --opt1 --opt2 ARGV [1]=--opt1 ARGV [2]=--opt2 % =item 3 When C<#!/usr/bin/awk -f> script handles arguments (options) and wants to read from stdin, it is necessary to add /dev/stdin (or `-') as a last argument explicitly. Example: awk_program: #!/usr/bin/awk -f BEGIN { if (ARGV [1] == "--flag"){ flag = 1 ARGV [1] = "" # to not read file named "--flag" } } { print "flag=" flag " $0=" $0 } Shell session: % echo test | awk_program -- --flag % echo test | awk_program -- --flag /dev/stdin flag=1 $0=test % Ideally I should work like this % echo test | awk_program --flag flag=1 $0=test % =item 4 igawk(1) which is shipped with GNU awk can not be used in shebang. On most (all?) UNIXes scripts beginning with #!/usr/local/bin/igawk -f will not work. =back B was created to solve all these problems =head1 OPTIONS =over 6 =item B<-d> Turn on a debugging mode. =item B<-e> I Specify program. If I<-e> is not specified, the AWK code is read from I. =item B<-f> I Activate I. This works the same way as #use "awk_module.awk" directive in the code. Multiple B<-f> options are allowed. =item B<-F> I Set the input field separator FS to the regular expression I. =item B<-h> Display help information. =item B<-t> If this option is applied, a temporary directory is created by B and path to it is passed to B child process. Temporary directory is created under ${RUNAWK_TMPDIR} (if it is set), or ${TMPDIR} (if it is set) or /tmp directory otherwise. If I<#use "tmpfile.awk"> is detected in a program this option is activated automatically. =item B<-T> Set FS to TAB character. This is equivalent to B<-F'\t'> =item B<-V> Display version information. =item B<-v> I=I Assign the value I to the variable I before execution of the program begins. =back =head1 DETAILS/INTERNALS =head2 Standalone script Under UNIX-like OS-es you can use B by beginning your script with #!/usr/local/bin/runawk line or something like this instead of #!/usr/bin/awk -f or similar. =head2 AWK modules In order to activate modules you should add them into awk script like this #use "module1.awk" #use "module2.awk" that is the line that specifies module name is treated as a comment line by normal AWK interpreter but is processed by B especially. Unless you run B with option B<-e>, I<#use> must begin with column 0, that is no spaces or tabs symbols are allowed before it and no symbols are allowed between I<#> and I. Also note that AWK modules can also "use" another modules and so forth. All them are collected in a depth-first order and each one is added to the list of awk interpreter arguments prepanded with -f option. That is I<#use> directive is *NOT* similar to I<#include> in C programming language, runawk's module code is not inserted into the place of I<#use>. Runawk's modules are closer to Perl's "use" command. In case some module is mentioned more than once, only one -f will be added for it, i.e duplications are removed automatically. Position of I<#use> directive in a source file does matter, i.e. the earlier module is mentioned, the earlier -f will be generated for it. Example: file prog: #!/usr/local/bin/runawk #use "A.awk" #use "B.awk" #use "E.awk" PROG code ... file B.awk: #use "A.awk" #use "C.awk" B code ... file C.awk: #use "A.awk" #use "D.awk" C code ... A.awk and D.awk don't contain #use directive If you run runawk prog file1 file2 or /path/to/prog file1 file2 the following command awk -f A.awk -f D.awk -f C.awk -f B.awk -f E.awk -f prog -- file1 file2 will actually run. You can check this by running runawk -d prog file1 file2 =head2 Module search strategy Modules are first searched in a directory where main program (or module in which #use directive is specified) is placed. If it is not found there, then AWKPATH environment variable is checked. AWKPATH keeps a colon separated list of search directories. Finally, module is searched in system runawk modules directory, by default PREFIX/share/runawk but this can be changed at compile time. An absolute path to the module can also be specified. =head2 Program as an argument Like some other interpreters B can obtain the script from a command line like this /path/to/runawk -e ' #use "alt_assert.awk" { assert($1 >= 0 && $1 <= 10, "Bad value: " $1) # your code below ... }' B can also be used for writing oneliners runawk -f abs.awk -e 'BEGIN {print abs(-1)}' =head2 Selecting a preferred AWK interpreter For some reason you may prefer one AWK interpreter or another. The reason may be efficiency for a particular task, useful but not standard extensions or enything else. To tell B what AWK interpreter to use, one can use I<#interp> directive file prog: #!/usr/local/bin/runawk #use "A.awk" #use "B.awk" #interp "/usr/pkg/bin/nbawk" # your code here ... Note that I<#interp> directive should also begin with column 0, no spaces are allowed before it and between I<#> and I. Sometimes it also makes sense to give users ability to select their preferred AWK interpreter without changing the source code. In B it is possible using special directive I<#interp-var> which sets an environment variable name assignable by user that specifies an AWK interpreter. For example, the following script file foobar: #!/usr/bin/env runawk #interp-var "FOOBAR_AWK" BEGIN { print "This is a FooBar application" } can be run as env FOOBAR_AWK=mawk foobar or just foobar In the former case B will be used as AWK interpreter, in the latter -- the default AWK interpreter. =head2 Using existing modules only In UNIX world it is common practise to write configuration files in a programming language of the application. That is, if application is written in Bourne shell, configuration files for such application are often written in Bourne as well. Using RunAWK one can do the same for applications written in AWK. For example, the following code will use ~/.foobarrc file if it exists otherwise /etc/foobar.conf will be used if it exists. file foobar: #!/usr/bin/env runawk #safe-use "~/.foobarrc" "/etc/foobar.conf" BEGIN { print foo, bar, baz } file ~/.foobarrc: BEGIN { foo = "foo10" bar = "bar20" baz = 123 } Of course, I<#safe-use> directive may be used for other purposes as well. I<#safe-use> directive accepts as much modules as you want, but at most one can be included using awk option -f, others are silently ignored, also note that modules are analysed from left to right. Leading tilde in the module name is replaced with user's home directory. Another example: file foobar: #!/usr/bin/env runawk #use "/usr/share/foobar/default.conf" #safe-use "~/.foobarrc" "/etc/foobar.conf" your code is here Here the default settings are set in /usr/share/foobar/default.conf, and configuration files (if any) are used for overriding them. =head2 Setting environment In some cases you may want to run AWK interpreter with a specific environment. For example, your script may be oriented to process ASCII text only. In this case you can run AWK with LC_CTYPE=C environment and use regexp ranges. B provides I<#env> directive for this. String inside double quotes is passed to L libc function. Example: file prog: #!/usr/local/bin/runawk #env "LC_ALL=C" $1 ~ /^[A-Z]+$/ { # A-Z is valid if LC_CTYPE=C print $1 } =head1 EXIT STATUS If AWK interpreter exits normally, B exits with its exit status. If AWK interpreter was killed by signal, B exits with exit status 128+signal. =head1 ENVIRONMENT =over 6 =item I Colon separated list of directories where B modules are searched. =item I Sets the path to the AWK interpreter, used by default, i.e. this variable overrides the compile-time default. Note that #interp directive overrides this. =item I If set, temporary files are not deleted. =back =head1 AUTHOR Copyright (c) 2007-2014 Aleksey Cheusov =head1 BUGS/FEEDBACK Please send any comments, questions, bug reports etc. to me by e-mail or register them at sourceforge project home. Feature requests are also welcomed. =head1 HOME L =head1 SEE ALSO L runawk-runawk-1.6.1/test/000077500000000000000000000000001343160141100153045ustar00rootroot00000000000000runawk-runawk-1.6.1/test/Makefile000066400000000000000000000020241343160141100167420ustar00rootroot00000000000000DIFF_PROG ?= diff -u TESTTEMPDIR = ${.CURDIR}/.. .export TESTTEMPDIR all: @echo 'running tests...'; \ export SRCDIR=${.CURDIR}/..; \ if { ${.CURDIR}/test.sh > ${.OBJDIR}/_test.res; \ ${DIFF_PROG} ${.CURDIR}/test.out ${.OBJDIR}/_test.res; };\ then echo ' succeeded'; \ else echo ' failed'; false; \ fi # test using all available awk version except mawk which # is definitely buggy, oawk is also NOT supported AWK_PROGS ?= /usr/bin/awk /usr/bin/nawk /usr/bin/gawk \ /usr/pkg/bin/nawk /usr/pkg/bin/gawk /usr/pkg/bin/nbawk #\ # /usr/pkg/heirloom/bin/posix/awk /usr/pkg/heirloom/bin/posix2001/awk # /usr/pkg/heirloom/bin/nawk # /usr/bin/mawk /usr/pkg/bin/mawk /usr/pkg/bin/mawk-uxre .PHONY: test_all test_all: .for awk in ${AWK_PROGS} @if test -x ${awk}; then \ echo testing ${awk}; \ export RUNAWK_AWKPROG=${awk}; cd ${.CURDIR} && ${MAKE} all; \ echo ''; \ fi .endfor CLEANFILES += ${TESTTEMPDIR}/temp1.awk ${TESTTEMPDIR}/temp2.awk ${TESTTEMPDIR}/temp3.awk DISTCLEANFILES += _test.res .include runawk-runawk-1.6.1/test/mods1/000077500000000000000000000000001343160141100163275ustar00rootroot00000000000000runawk-runawk-1.6.1/test/mods1/module1.1.awk000066400000000000000000000001341343160141100205360ustar00rootroot00000000000000#use "module1.2.awk" #use "module1.3.awk" BEGIN { print "Hello World1.1" } runawk-runawk-1.6.1/test/mods1/module1.2.awk000066400000000000000000000000451343160141100205400ustar00rootroot00000000000000BEGIN { print "Hello World1.2" } runawk-runawk-1.6.1/test/mods1/module1.3.awk000066400000000000000000000000731343160141100205420ustar00rootroot00000000000000#use "module1.2.awk" BEGIN { print "Hello World1.3" } runawk-runawk-1.6.1/test/mods1/test_modinfo000066400000000000000000000003521343160141100207440ustar00rootroot00000000000000#!/usr/bin/env runawk #use "module1.1.awk" #use "module2.1.awk" #use "module2.3.awk" #use "modinfo.awk" BEGIN { print "MODC=" MODC for (i=0; i < MODC; ++i){ printf "MODV [%d]=%s\n", i, MODV [i] } print "MODMAIN=" MODMAIN } runawk-runawk-1.6.1/test/mods2/000077500000000000000000000000001343160141100163305ustar00rootroot00000000000000runawk-runawk-1.6.1/test/mods2/module2.1.awk000066400000000000000000000000741343160141100205430ustar00rootroot00000000000000#use "module2.2.awk" BEGIN { print "Hello World 2.1" } runawk-runawk-1.6.1/test/mods2/module2.2.awk000066400000000000000000000000461343160141100205430ustar00rootroot00000000000000BEGIN { print "Hello World 2.2" } runawk-runawk-1.6.1/test/mods2/module2.3.awk000066400000000000000000000000741343160141100205450ustar00rootroot00000000000000#use "module2.2.awk" BEGIN { print "Hello World 2.3" } runawk-runawk-1.6.1/test/mods3/000077500000000000000000000000001343160141100163315ustar00rootroot00000000000000runawk-runawk-1.6.1/test/mods3/failed1.awk000066400000000000000000000000061343160141100203360ustar00rootroot00000000000000#use runawk-runawk-1.6.1/test/mods3/failed2.awk000066400000000000000000000000271343160141100203420ustar00rootroot00000000000000 #interp "trtrtr runawk-runawk-1.6.1/test/mods3/failed3.awk000066400000000000000000000000451343160141100203430ustar00rootroot00000000000000 #env 'LC_ALL=C' runawk-runawk-1.6.1/test/mods3/failed4.awk000066400000000000000000000000711343160141100203430ustar00rootroot00000000000000#interp "/invalid/path" BEGIN { print "Hello World!" } runawk-runawk-1.6.1/test/mods3/test5.awk000066400000000000000000000003531343160141100201020ustar00rootroot00000000000000#env "LC_ALL=C" #env "FOO=BAR" BEGIN { print ("y" ~ /^[a-z]$/) print ("Y" ~ /^[a-z]$/) print ("z" ~ /^[a-z]$/) print ("Z" ~ /^[a-z]$/) print ("env FOO=" ENVIRON ["FOO"]) print ("env TESTVAR=" ENVIRON ["TESTVAR"]) } runawk-runawk-1.6.1/test/test.out000066400000000000000000001003521343160141100170150ustar00rootroot00000000000000-------------------------------------------------- ------ args: -d _test_program new_argv [0] = _test_program new_argv [1] = -f new_argv [3] = -- -------------------------------------------------- ------ args: -d _test_program --long-option new_argv [0] = _test_program new_argv [1] = -f new_argv [3] = -- new_argv [4] = --long-option -------------------------------------------------- ------ args: -d _test_program -o=file new_argv [0] = _test_program new_argv [1] = -f new_argv [3] = -- new_argv [4] = -o=file -------------------------------------------------- ------ args: -d _test_program fn1 fn2 new_argv [0] = _test_program new_argv [1] = -f new_argv [3] = -- new_argv [4] = fn1 new_argv [5] = fn2 -------------------------------------------------- ------ args: -d -f abs.awk -e BEGIN {print abs(-123), abs(234); exit} new_argv [0] = awk new_argv [1] = -f new_argv [2] = /ROOT/../modules/abs.awk new_argv [3] = -f new_argv [4] = /tmp/runawk.NNNNNN new_argv [5] = -- -------------------------------------------------- ------ args: -d -f alt_assert.awk -e BEGIN {exit} new_argv [0] = awk new_argv [1] = -f new_argv [2] = /ROOT/../modules/exitnow.awk new_argv [3] = -f new_argv [4] = /ROOT/../modules/abort.awk new_argv [5] = -f new_argv [6] = /ROOT/../modules/alt_assert.awk new_argv [7] = -f new_argv [8] = /tmp/runawk.NNNNNN new_argv [9] = -- -------------------------------------------------- ------ args: -V xxx -------------------------------------------------- ------ args: -h runawk - wrapper for an AWK interpreter -------------------------------------------------- ------ args: -e BEGIN {print "Hello World"} Hello World -------------------------------------------------- ------ args: -v one=1 -e BEGIN {print one} {print "unbelievably"} /dev/null 1 -------------------------------------------------- ------ args: -v two=2 -e BEGIN {print two} 2 -------------------------------------------------- ------ args: -e BEGIN {print "Hello World"} /dev/null Hello World -------------------------------------------------- ------ args: -v var1=123 -v var2=321 -e BEGIN {print var1, var2} 123 321 -------------------------------------------------- ------ args: _test.tmp Hello World1.2 Hello World1.3 Hello World1.1 Hello World 2.2 Hello World 2.1 Hello World 2.3 -------------------------------------------------- ------ args: _test.tmp Cannot find module `module2.1.awk`, check AWKPATH environment variable -------------------------------------------------- ------ args: /ROOT/mods1/test_modinfo Hello World1.2 Hello World1.3 Hello World1.1 Hello World 2.2 Hello World 2.1 Hello World 2.3 MODC=8 MODV [0]=/ROOT/mods1/module1.2.awk MODV [1]=/ROOT/mods1/module1.3.awk MODV [2]=/ROOT/mods1/module1.1.awk MODV [3]=/ROOT/mods2/module2.2.awk MODV [4]=/ROOT/mods2/module2.1.awk MODV [5]=/ROOT/mods2/module2.3.awk MODV [6]=/ROOT/../modules/modinfo.awk MODV [7]=/ROOT/mods1/test_modinfo MODMAIN=/ROOT/mods1/test_modinfo -------------------------------------------------- ------ args: /ROOT/mods3/failed1.awk error: invalid directive at line #1, line=`#use ` file=`/ROOT/mods3/failed1.awk` -------------------------------------------------- ------ args: /ROOT/mods3/failed2.awk error: invalid directive at line #2, line=`#interp "trtrtr` file=`/ROOT/mods3/failed2.awk` -------------------------------------------------- ------ args: /ROOT/mods3/failed3.awk error: invalid directive at line #3, line=`#env 'LC_ALL=C' ` file=`/ROOT/mods3/failed3.awk` -------------------------------------------------- ------ args: /ROOT/mods3/failed4.awk running '/invalid/path' failed: No such file or directory -------------------------------------------------- ------ args: /ROOT/mods3/test5.awk 1 0 1 0 env FOO=BAR env TESTVAR=testval -------------------------------------------------- ------ args: -e #interp "/invalid/path" BEGIN {print "Hello World!"} running '/invalid/path' failed: No such file or directory -------------------------------------------------- ------ args: #interp-var directive 123 running '/invalid/path' failed -------------------------------------------------- ------ args: #safe-use directive --- #safe-use test: --- new_argv [0] = awk new_argv [1] = -f new_argv [2] = /path/temp1.awk new_argv [3] = -f new_argv [4] = /tmp/runawk.NNNNNN new_argv [5] = -- --- #safe-use test: --- new_argv [0] = awk new_argv [1] = -f new_argv [2] = /path/temp1.awk new_argv [3] = -f new_argv [4] = /tmp/runawk.NNNNNN new_argv [5] = -- --- #safe-use test: --- new_argv [0] = awk new_argv [1] = -f new_argv [2] = /path/temp2.awk new_argv [3] = -f new_argv [4] = /tmp/runawk.NNNNNN new_argv [5] = -- --- #safe-use test: --- new_argv [0] = awk new_argv [1] = #safe-use "/bad/path3" "/bad/path2" "/bad/path1" BEGIN { print 123 exit 0 } -------------------------------------------------- ------ args: -e #use "/invalid/path/file.awk" stat("/invalid/path/file.awk") failed: No such file or directory -------------------------------------------------- ------ args: -d -e BEGIN { for (i=0; i < ARGC; ++i){ printf "ARGV [%s]=%s\n", i, ARGV [i] } } -- -a -b -c new_argv [0] = awk new_argv [1] = BEGIN { for (i=0; i < ARGC; ++i){ printf "ARGV [%s]=%s\n", i, ARGV [i] } } new_argv [2] = -a new_argv [3] = -b new_argv [4] = -c -------------------------------------------------- ------ args: -e BEGIN { for (i=1; i < ARGC; ++i){ printf "ARGV [%s]=%s\n", i, ARGV [i] } } -- file1 file2 file3 ARGV [1]=file1 ARGV [2]=file2 ARGV [3]=file3 -------------------------------------------------- ------ args: -d -e #env "LC_ALL=C" #env "FOO2=bar2" BEGIN { ... } new_argv [0] = awk new_argv [1] = #env "LC_ALL=C" #env "FOO2=bar2" BEGIN { ... } -------------------------------------------------- ------ args: -e #env "LC_ALL=C" #env "FOO2=bar2" BEGIN { print ("y" ~ /^[a-z]$/) print ("Y" ~ /^[a-z]$/) print ("z" ~ /^[a-z]$/) print ("Z" ~ /^[a-z]$/) print ("env FOO2=" ENVIRON ["FOO2"]) } 1 0 1 0 env FOO2=bar2 -------------------------------------------------- ------ args: -e BEGIN {print 1} -e BEGIN {print 2} multiple -e are not allowed -------------------------------------------------- ------ args: -d -e #use "alt_assert.awk" BEGIN { print "Hello world!" abort("just a test", 7) } /dev/null new_argv [0] = awk new_argv [1] = -f new_argv [2] = /ROOT/../modules/exitnow.awk new_argv [3] = -f new_argv [4] = /ROOT/../modules/abort.awk new_argv [5] = -f new_argv [6] = /ROOT/../modules/alt_assert.awk new_argv [7] = -f new_argv [8] = /tmp/runawk.NNNNNN new_argv [9] = -- new_argv [10] = /dev/null -------------------------------------------------- ------ args: -e #use "alt_assert.awk" BEGIN { abort("just a test", 7) } error: just a test ARGV[0]=awk $0=`` NF=0 FNR=0 FILENAME= -------------------------------------------------- ------ args: -f abs.awk -e BEGIN {print abs(-123), abs(234); exit} 123 234 -------------------------------------------------- ------ args: -f alt_assert.awk -e BEGIN {assert(0, "Hello assert!")} error: assertion failed: Hello assert! ARGV[0]=awk $0=`` NF=0 FNR=0 FILENAME= -------------------------------------------------- ------ args: -Te { for (i=1; i <= NF; ++i){ printf "$%d=%s\n", i, $i } } $1= a b c $1=a $2= b $3=c -------------------------------------------------- ------ args: ../examples/demo_multisub -------------------------------------------------- ------ args: ../examples/demo_tokenre ../examples/demo_tokenre.in NF=5 $1=wn: $2=UNIX $3="UNIX guru" $4="UNIX operating system" $5="UNIX system" NF=4 $1=jargon: $2=Unix $3="Unix brain damage" $4="Unix conspiracy" NF=1 $1="Unix weenie" NF=4 $1=foldoc: $2="berkeley unix" $3="bsd unix" $4="call unix" NF=3 $1="united kingdom unix users group" $2=unix $3="unix box" NF=3 $1="unix brain damage" $2="unix conspiracy" $3="unix international" NF=3 $1="unix man page" $2="unix manual page" $3="unix system v" NF=4 $1="unix to unix copy" $2="unix weenie" $3="unix wizard" $4="usg unix" -------------------------------------------------- ------ args: ../examples/demo_tokenre2 ../examples/demo_tokenre2.in a := 1 b := 2.3 while a + b < 10 do a := a + 1 end print 'Hello world!' print 'a = ' .. a print 'b = ' .. b -------------------------------------------------- ------ args: ../examples/demo_tokenre3 ../examples/demo_tokenre3.in http://sourceforge.net/projects http://freshmeat.net/projects dict://dictd.xdsl.by/ vle@gmx.net faith@dict.org fake@domain.com foo@bar.baz.ru -------------------------------------------------- ------ args: ../examples/demo_tokenre4 ../examples/demo_tokenre3.in http://sourceforge.net/projects http://freshmeat.net/projects dict://dictd.xdsl.by/ vle@gmx.net faith@dict.org fake@domain.com foo@bar.baz.ru -------------------------------------------------- ------ args: ../examples/demo_splitre ../examples/demo_tokenre2.in a := 1 b := 2.3 while a + b < 10 do a := a + 1 end print 'Hello world!' print 'a = ' .. a print 'b = ' .. b -------------------------------------------------- ------ args: ../examples/demo_alt_getopt -h - option `h' ARGV [2] = - -------------------------------------------------- ------ args: ../examples/demo_alt_getopt --help option `h' ARGV [1] = - -------------------------------------------------- ------ args: ../examples/demo_alt_getopt -h --help -v --verbose -V -o 123 -o234 option `h' option `h' option `v' option `v' option `V' option `o': 123 option `o': 234 ARGV [1] = - -------------------------------------------------- ------ args: ../examples/demo_alt_getopt --output 123 --output 234 -n 999 -n9999 --len 5 --fake /dev/null option `o': 123 option `o': 234 option `n': 999 option `n': 9999 option `len': 5 option `fake' ARGV [11] = /dev/null -------------------------------------------------- ------ args: ../examples/demo_alt_getopt -hVv -- -1 -2 -3 option `h' option `V' option `v' ARGV [3] = -1 ARGV [4] = -2 ARGV [5] = -3 -------------------------------------------------- ------ args: ../examples/demo_alt_getopt --fake -v -- -1 -2 -3 option `fake' option `v' ARGV [4] = -1 ARGV [5] = -2 ARGV [6] = -3 -------------------------------------------------- ------ args: ../examples/demo_alt_getopt - -1 -2 -3 ARGV [1] = - ARGV [2] = -1 ARGV [3] = -2 ARGV [4] = -3 -------------------------------------------------- ------ args: ../examples/demo_alt_getopt --fake -v - -1 -2 -3 option `fake' option `v' ARGV [3] = - ARGV [4] = -1 ARGV [5] = -2 ARGV [6] = -3 -------------------------------------------------- ------ args: ../examples/demo_alt_getopt -1 -2 -3 Unknown option `-1' -------------------------------------------------- ------ args: ../examples/demo_alt_getopt -hvV option `h' option `v' option `V' ARGV [1] = - -------------------------------------------------- ------ args: ../examples/demo_alt_getopt -ho 123 option `h' option `o': 123 ARGV [1] = - -------------------------------------------------- ------ args: ../examples/demo_alt_getopt -hoV 123 option `h' option `o': V ARGV [2] = 123 -------------------------------------------------- ------ args: ../examples/demo_alt_getopt --unknown Unknown option `--unknown' -------------------------------------------------- ------ args: ../examples/demo_alt_getopt --output=file.out -nNNN --len=LENGTH option `o': file.out option `n': NNN option `len': LENGTH ARGV [1] = - -------------------------------------------------- ------ args: ../examples/demo_alt_getopt --output --file-- option `o': --file-- ARGV [1] = - -------------------------------------------------- ------ args: ../examples/demo_modinfo A number of modules: 9 MODV [0]=/ROOT/../modules/abs.awk MODV [1]=/ROOT/../modules/exitnow.awk MODV [2]=/ROOT/../modules/abort.awk MODV [3]=/ROOT/../modules/alt_assert.awk MODV [4]=/ROOT/../modules/min.awk MODV [5]=/ROOT/../modules/max.awk MODV [6]=/ROOT/../modules/alt_getopt.awk MODV [7]=/ROOT/../modules/modinfo.awk MODV [8]=/ROOT/../examples/demo_modinfo program name: /ROOT/../examples/demo_modinfo -------------------------------------------------- ------ args: ../examples/demo_has_suffix ../examples/demo_has_suffix.in no, `mama' does not end with `mamam' yes, `mama' ends with `mama' no, `mama' does not end with `mam' yes, `mama' ends with `ma' yes, `mama' ends with `a' yes, `mama' ends with `' yes, `file.txt' ends with `.txt' no, `file.txt' does not end with `.log' no, `file.txt' does not end with `.bmp' yes, `file.txt' ends with `file.txt' -------------------------------------------------- ------ args: ../examples/demo_has_prefix ../examples/demo_has_prefix.in no, `mama' does not begin with `mamam' yes, `mama' begins with `mama' yes, `mama' begins with `mam' yes, `mama' begins with `ma' no, `mama' does not begin with `a' yes, `mama' begins with `' no, `file.txt' does not begin with `.txt' no, `file.txt' does not begin with `.log' yes, `file.txt' begins with `file.' yes, `file.txt' begins with `file' no, `file.txt' does not begin with `bzzzzzzzzzzzzz' -------------------------------------------------- ------ args: ../examples/demo_dirname Usage: dirname path -------------------------------------------------- ------ args: ../examples/demo_dirname /path/to/file /path/to -------------------------------------------------- ------ args: ../examples/demo_dirname file.txt . -------------------------------------------------- ------ args: ../examples/demo_dirname / / -------------------------------------------------- ------ args: ../examples/demo_dirname /dir/ / -------------------------------------------------- ------ args: ../examples/demo_basename Usage: basename path -------------------------------------------------- ------ args: ../examples/demo_basename /path/to/file file -------------------------------------------------- ------ args: ../examples/demo_basename file.txt file.txt -------------------------------------------------- ------ args: ../examples/demo_basename / / -------------------------------------------------- ------ args: ../examples/demo_basename /dir/ dir -------------------------------------------------- ------ args: ../examples/demo_basename /path/to/file.txt .txt file -------------------------------------------------- ------ args: ../examples/demo_basename file.txt .txt file -------------------------------------------------- ------ args: ../examples/demo_basename / .txt / -------------------------------------------------- ------ args: ../examples/demo_basename /dir/ .txt dir -------------------------------------------------- ------ args: ../examples/demo_basename /path/to/file.txt .log file.txt -------------------------------------------------- ------ args: ../examples/demo_basename file.txt .log file.txt -------------------------------------------------- ------ args: ../examples/demo_basename / .log / -------------------------------------------------- ------ args: ../examples/demo_basename /dir/ .log dir -------------------------------------------------- ------ args: ../examples/demo_shquote ../examples/demo_shquote.in ''\''' printf: ' ''\'''\''' printf: '' ''\'''\'''\''' printf: ''' '\' printf: \ '\\' printf: \\ '\\\' printf: \\\ '\\'\''' printf: \\' ''\''\'\''' printf: '\' '' printf: 'Apple'\''s' printf: Apple's 'apple' printf: apple 'file name.txt' printf: file name.txt '*&;<>#~^$`!][(){}?' printf: *&;<>#~^$`!][(){}? -------------------------------------------------- ------ args: ../examples/demo_alt_join succeeded -------------------------------------------------- ------ args: ../examples/demo_readfile usage: demo_readfile -------------------------------------------------- ------ args: ../examples/demo_readfile ../examples/demo_readfile.in line1 line2 line3 -------------------------------------------------- ------ args: ../examples/demo_power_getopt The following option were applied f --- 0 flag --- 0 long-flag --- 0 s --- 0 F --- default1 FLAG --- default2 LONG-FLAG --- default3 S --- default4 X --- 0 Y --- default5 ////////////////////////////////////////////////// ------ args: ../examples/demo_power_getopt -ffss --flag --long-flag -------------------------------------------------- F --- default1 FLAG --- default2 LONG-FLAG --- default3 S --- default4 The following option were applied X --- 0 Y --- default5 f --- 3 flag --- 3 long-flag --- 1 options [f]=3 options [long-flag]=1 options [s]=2 s --- 2 ////////////////////////////////////////////////// --LONG-FLAG long flag with value --long-flag long flag only -F|--FLAG flag with value -P print ARGC and ARGV -S short flag with value -X short flag -Y short flag with value -f|--flag flag -h|--help display this screen -s short flag only ------ args: ../examples/demo_power_getopt -h -------------------------------------------------- OPTIONS: power_getopt - program demonstrating a power of power_getopt.awk module usage: power_getopt [OPTIONS] ////////////////////////////////////////////////// ------ args: ../examples/demo_power_getopt -f --long-flag -s -F123 --FLAG=234 --LONG-FLAG 345 -S 456 -------------------------------------------------- F --- 234 FLAG --- 234 LONG-FLAG --- 345 S --- 456 The following option were applied X --- 0 Y --- default5 f --- 1 flag --- 1 long-flag --- 1 options [F]=234 options [LONG-FLAG]=345 options [S]=456 options [f]=1 options [long-flag]=1 options [s]=1 s --- 1 ////////////////////////////////////////////////// ------ args: ../examples/demo_power_getopt -f --long-flag -s -F123 --FLAG=234 --LONG-FLAG 345 -S 456 -P arg1 arg3 arg4 -------------------------------------------------- ARGC=6 ARGV [1]=arg1 ARGV [2]= ARGV [3]=arg3 ARGV [4]=arg4 ARGV [5]= ////////////////////////////////////////////////// -------------------------------------------------- ------ args: ../examples/demo_power_getopt2 --help power_getopt - program demonstrating a power of power_getopt.awk module usage: power_getopt [OPTIONS] OPTIONS: -?|--help display this screen -------------------------------------------------- ------ args: ../examples/demo_power_getopt2 -? power_getopt - program demonstrating a power of power_getopt.awk module usage: power_getopt [OPTIONS] OPTIONS: -?|--help display this screen -------------------------------------------------- ------ args: ../examples/demo_runcmd file name.txt ~file&name'foobar'.txt succeeded -------------------------------------------------- ------ args: ../examples/demo_heapsort2 -------------------------------------------------- ------ args: ../examples/demo_heapsort AWK Ada BCPL C C# C++ Caml Clean Cobol D ECMAScript Eiffel Emacs Lisp Erlang F# Forth Fortran Haskell Java Lisp Lua Miranda Modula-3 Oberon-2 Objective-C Oz PHP PL/1 Pascal Perl Pike Prolog REFAL Rebol Rexx Ruby SML Scheme Simula-67 Smalltalk Snobol TCL UNIX shell csh ksh rc sed -------------------------------------------------- ------ args: ../examples/demo_heapsort3 Fortran 1957 Lisp 1958 Cobol 1959 Snobol 1962 PL/1 1964 REFAL 1966 BCPL 1966 Simula-67 1967 Forth 1970 Pascal 1970 C 1972 Prolog 1972 sed 1973 Scheme 1975 AWK 1977 UNIX_shell 1977 csh 1978 Rexx 1979 Modula-3 1980 Smalltalk 1980 ksh 1982 Ada 1983 C++ 1983 Caml 1985 Miranda 1985 Eiffel 1986 Objective-C 1986 Erlang 1986 Perl 1987 Clean 1987 TCL 1988 rc 1989 SML 1990 Haskell 1990 Oberon-2 1991 Oz 1991 Lua 1993 Pike 1994 Ruby 1995 Java 1995 PHP 1995 Rebol 1997 ECMAScript 1997 D 1999 C# 2001 F# 2002 -------------------------------------------------- ------ args: ../examples/demo_heapsort4 sorted1.1: bilberry cranberry gooseberry raspberry strawberry sorted1.2: bilberry cranberry gooseberry raspberry strawberry sorted1.3: gooseberry cranberry bilberry raspberry strawberry sorted2.1: bilberry cranberry gooseberry raspberry strawberry sorted2.2: bilberry cranberry gooseberry raspberry strawberry sorted2.3: 0 0 0 0 0 sorted1.1: Earth Jupiter Moon Saturn Sun Venus sorted1.2: Earth Jupiter Moon Saturn Sun Venus sorted1.3: Jupiter Venus Moon Sun Earth Saturn sorted2.1: Earth Jupiter Moon Saturn Sun Venus sorted2.2: Earth Jupiter Moon Saturn Sun Venus sorted2.3: 0 0 0 0 0 0 sorted1.1: 1 2 10 20 100 200 sorted1.2: 1 10 100 2 20 200 sorted1.3: 1 2 10 20 100 200 sorted2.1: 1 2 10 20 100 200 sorted2.2: 1 10 100 2 20 200 sorted2.3: 1 2 10 20 100 200 -------------------------------------------------- ------ args: ../examples/demo_quicksort2 -------------------------------------------------- ------ args: ../examples/demo_quicksort AWK Ada BCPL C C# C++ Caml Clean Cobol D ECMAScript Eiffel Emacs Lisp Erlang F# Forth Fortran Haskell Java Lisp Lua Miranda Modula-3 Oberon-2 Objective-C Oz PHP PL/1 Pascal Perl Pike Prolog REFAL Rebol Rexx Ruby SML Scheme Simula-67 Smalltalk Snobol TCL UNIX shell csh ksh rc sed -------------------------------------------------- ------ args: ../examples/demo_quicksort3 Fortran 1957 Lisp 1958 Cobol 1959 Snobol 1962 PL/1 1964 REFAL 1966 BCPL 1966 Simula-67 1967 Forth 1970 Pascal 1970 C 1972 Prolog 1972 sed 1973 Scheme 1975 AWK 1977 UNIX_shell 1977 csh 1978 Rexx 1979 Modula-3 1980 Smalltalk 1980 ksh 1982 Ada 1983 C++ 1983 Caml 1985 Miranda 1985 Eiffel 1986 Objective-C 1986 Erlang 1986 Perl 1987 Clean 1987 TCL 1988 rc 1989 SML 1990 Haskell 1990 Oberon-2 1991 Oz 1991 Lua 1993 Pike 1994 Ruby 1995 Java 1995 PHP 1995 Rebol 1997 ECMAScript 1997 D 1999 C# 2001 F# 2002 -------------------------------------------------- ------ args: ../examples/demo_fieldwidths NF=5 $1=1234 $2=12345 $3=123456 $4=12 $5=1 NF=5 $1= 4 $2= 5 $3= 6 $4= 2 $5=1 NF=4 $1= 4 $2= 5 $3= 6 $4= 2 NF=3 $1=1234 $2=12345 $3=12 NF=1 $1=12 NF=0 -------------------------------------------------- ------ args: ../examples/demo_tmpfile file 1 file 2 file 3 -------------------------------------------------- ------ args: ../examples/demo_trim ../examples/demo_trim.in trim_l("Van Der Graaf Generator ")="Van Der Graaf Generator " trim_r("Van Der Graaf Generator ")="Van Der Graaf Generator" trim_c("Van Der Graaf Generator ")="Van Der Graaf Generator " trim_lr("Van Der Graaf Generator ")="Van Der Graaf Generator" trim_lrc("Van Der Graaf Generator ")="Van Der Graaf Generator" trim_l(" Peter Hammill")="Peter Hammill" trim_r(" Peter Hammill")=" Peter Hammill" trim_c(" Peter Hammill")=" Peter Hammill" trim_lr(" Peter Hammill")="Peter Hammill" trim_lrc(" Peter Hammill")="Peter Hammill" trim_l(" King Crimson")="King Crimson" trim_r(" King Crimson")=" King Crimson" trim_c(" King Crimson")=" King Crimson" trim_lr(" King Crimson")="King Crimson" trim_lrc(" King Crimson")="King Crimson" trim_l("Robert Fripp")="Robert Fripp" trim_r("Robert Fripp")="Robert Fripp" trim_c("Robert Fripp")="Robert Fripp" trim_lr("Robert Fripp")="Robert Fripp" trim_lrc("Robert Fripp")="Robert Fripp" trim_l(" Jethro Tull")="Jethro Tull" trim_r(" Jethro Tull")=" Jethro Tull" trim_c(" Jethro Tull")=" Jethro Tull" trim_lr(" Jethro Tull")="Jethro Tull" trim_lrc(" Jethro Tull")="Jethro Tull" trim_l("Jan Anderson")="Jan Anderson" trim_r("Jan Anderson")="Jan Anderson" trim_c("Jan Anderson")="Jan Anderson" trim_lr("Jan Anderson")="Jan Anderson" trim_lrc("Jan Anderson")="Jan Anderson" -------------------------------------------------- ------ args: ../examples/demo_trim_in ../examples/demo_trim.in Van Der Graaf Generator Peter Hammill King Crimson Robert Fripp Jethro Tull Jan Anderson -------------------------------------------------- ------ args: -v TRIM= ../examples/demo_trim_in ../examples/demo_trim.in Van Der Graaf Generator Peter Hammill King Crimson Robert Fripp Jethro Tull Jan Anderson -------------------------------------------------- ------ args: -v TRIM=c ../examples/demo_trim_in ../examples/demo_trim.in Van Der Graaf Generator Peter Hammill King Crimson Robert Fripp Jethro Tull Jan Anderson -------------------------------------------------- ------ args: ../examples/demo_glob2ere -------------------------------------------------- ------ args: ../examples/demo_backslash_in ../examples/demo_backslash_in.in Some text here and here too. This is still the first line. This is the second. And this is third one that continues on the next line and the next line too. Ok, we finally have four lines of text. -------------------------------------------------- ------ args: ../examples/demo_ini : ../examples/demo_ini.in value [me:citizenship]=Belarus value [me:e-mail]=vle@gmx.net, cheusov@tut.by value [me:full name]=Aleksey Cheusov value [me:hobby]=programming, UNIX-like OSes, open source software, music value [me:home page]=http://mova.org/~cheusov/ value [me:jabber]=cheusov@mova.org value [me:nationality]=Russian value [me:sex]=male value [system:OS]=NetBSD value [system:OSVER]=5.1_RC3 value [system:host]=localhost value [system:network interface]=nfe0 value [tests:val1]= 123 45 value [tests:val2]= 123 45 value [tests:val3]= '123 45' value [tests:val4]= "123 45" value [tests:val5]= "123 ;" value [tests:val6]= '###123 ;' value [tests:val7]=1 2 3 4 5 6 7 -------------------------------------------------- ------ args: ../examples/demo_ini ../examples/demo_ini.in value [me.citizenship]=Belarus value [me.e-mail]=vle@gmx.net, cheusov@tut.by value [me.full name]=Aleksey Cheusov value [me.hobby]=programming, UNIX-like OSes, open source software, music value [me.home page]=http://mova.org/~cheusov/ value [me.jabber]=cheusov@mova.org value [me.nationality]=Russian value [me.sex]=male value [system.OS]=NetBSD value [system.OSVER]=5.1_RC3 value [system.host]=localhost value [system.network interface]=nfe0 value [tests.val1]= 123 45 value [tests.val2]= 123 45 value [tests.val3]= '123 45' value [tests.val4]= "123 45" value [tests.val5]= "123 ;" value [tests.val6]= '###123 ;' value [tests.val7]=1 2 3 4 5 6 7 -------------------------------------------------- ------ args: alt_getopt #1 help help verbose=1 verbose=1 echo 'alt_getopt-0-1-0 written by Aleksey Cheusov ' output='123' output='234' output='file with spaces' number='999' number='9999' len='5' fake_flag=1 help echo 'alt_getopt-0-1-0 written by Aleksey Cheusov ' verbose=1 len='10' len='100' msg='Aleksey'\''s cat is female' msg='backslashes (\) is not a problem too' shift 24 -------------------------------------------------- ------ args: demo_alt_getopt.sh #1 verbose=0 fake_flag= len= output= msg= n= flag= quiet= -------------------------------------------------- ------ args: demo_alt_getopt.sh #1.5 verbose=0 fake_flag= len= output= msg= n= flag= quiet= arg [1]=arg1 arg [2]=arg2 arg [3]=arg3 -------------------------------------------------- ------ args: demo_alt_getopt.sh #2 verbose=0 fake_flag= len= output= msg=Aleksey's cat is female n=123 flag= quiet= arg [1]=arg1 -------------------------------------------------- ------ args: demo_alt_getopt.sh #3 verbose=0 fake_flag= len=123 output= msg=Aleksey's cat is female n= flag= quiet= arg [1]=arg1 arg [2]=arg2 -------------------------------------------------- ------ args: demo_alt_getopt.sh #4 verbose=0 fake_flag= len=123 output= msg=Aleksey's cat is female n= flag=1 quiet= arg [1]=-a1 arg [2]=-a2 -------------------------------------------------- ------ args: demo_alt_getopt.sh #5 blablabla help verbose=3 fake_flag= len=100 output=/path/to/file.out msg= n=123 flag= quiet= -------------------------------------------------- ------ args: demo_alt_getopt.sh #5 blablabla help verbose=0 fake_flag= len=100 output=/path/to/file.out msg= n=123 flag= quiet=1 -------------------------------------------------- ------ args: demo_alt_getopt2.sh #1 demo_alt_getopt2.sh is a demo program for alt_getopt.sh OPTIONS: -h|--help display this help -v|--version display version -o|--output output file -------------------------------------------------- ------ args: demo_alt_getopt2.sh #2 demo_alt_getopt2.sh 0.1.0 output= -------------------------------------------------- ------ args: demo_alt_getopt2.sh #3 output=/path/to/file with spaces.txt -------------------------------------------------- ------ args: demo_alt_getopt2.sh #4 output=file.txt $1=arg1 $2=arg2 $3=arg3 -------------------------------------------------- ------ args: demo_alt_getopt2.sh #5 output= $1=-ofile.txt $2=arg1 -------------------------------------------------- ------ args: demo_alt_getopt2.sh #6 output= $1=-o $2=file.txt $3=arg1 -------------------------------------------------- ------ args: demo_alt_getopt2.sh #7 output=file.txt $1=arg1 -------------------------------------------------- ------ args: demo_minmax #1 -------------------------------------------------- ------ args: ../examples/demo_ftrans /dev/null -------------------------------------------------- ------ args: ../examples/demo_ftrans ../examples/demo_readfile.in #### beginning of ../examples/demo_readfile.in #### line1 line2 line3 #### end of ../examples/demo_readfile.in #### -------------------------------------------------- ------ args: ../examples/demo_ftrans ../examples/demo_readfile.in ../examples/demo_shquote.in ../examples/demo_fieldwidths.in #### beginning of ../examples/demo_readfile.in #### line1 line2 line3 #### end of ../examples/demo_readfile.in #### #### beginning of ../examples/demo_shquote.in #### ' '' ''' \ \\ \\\ \\' '\' Apple's apple file name.txt *&;<>#~^$`!][(){}? #### end of ../examples/demo_shquote.in #### #### beginning of ../examples/demo_fieldwidths.in #### 12341234512345612100000 4 5 6 21 4 5 6 2 12341234512 12 #### end of ../examples/demo_fieldwidths.in #### -------------------------------------------------- ------ args: ../examples/demo_ftrans #### beginning of - #### foo bar baz #### end of - #### -------------------------------------------------- ------ args: -F #1 new_argv [0] = awk new_argv [1] = -F new_argv [2] = : new_argv [3] = {print} -------------------------------------------------- ------ args: -F #2 new_argv [0] = awk new_argv [1] = -F new_argv [2] = : new_argv [3] = {print} -------------------------------------------------- ------ args: -F #3 a=1 4:1 2 3 4 b=2 4:1 2 3 4 -------------------------------------------------- ------ args: xargs + runawk #1 49950000 -------------------------------------------------- ------ args: exitnow.awk #1 -------------------------------------------------- ------ args: ../examples/demo_io File ../Makefile is a generic file: 1 File ../Makefile is a socket: 0 File ../Makefile is a directory: 0 File ../Makefile is executable: 0 File ../Makefile is a FIFO: 0 File ../Makefile is a symlink: 0 File ../Makefile is a block device file: 0 File ../Makefile is a character device file: 0 The size of ../Makefile is 750 bytes The type of ../Makefile is - File /nonexistent is a generic file: 0 File /nonexistent is a socket: 0 File /nonexistent is a directory: 0 File /nonexistent is executable: 0 File /nonexistent is a FIFO: 0 File /nonexistent is a symlink: 0 File /nonexistent is a block device file: 0 File /nonexistent is a character device file: 0 The size of /nonexistent is -2 bytes The type of /nonexistent is File /dev/null is a generic file: 0 File /dev/null is a socket: 0 File /dev/null is a directory: 0 File /dev/null is executable: 0 File /dev/null is a FIFO: 0 File /dev/null is a symlink: 0 File /dev/null is a block device file: 0 File /dev/null is a character device file: 1 The size of /dev/null is -1 bytes The type of /dev/null is c File . is a generic file: 0 File . is a socket: 0 File . is a directory: 1 File . is executable: 1 File . is a FIFO: 0 File . is a symlink: 0 File . is a block device file: 0 File . is a character device file: 0 The size of . is -1 bytes The type of . is d File symlink.tmp is a generic file: 1 File symlink.tmp is a socket: 0 File symlink.tmp is a directory: 0 File symlink.tmp is executable: 1 File symlink.tmp is a FIFO: 0 File symlink.tmp is a symlink: 1 File symlink.tmp is a block device file: 0 File symlink.tmp is a character device file: 0 The size of symlink.tmp is -1 bytes The type of symlink.tmp is l File fifo.tmp is a generic file: 0 File fifo.tmp is a socket: 0 File fifo.tmp is a directory: 0 File fifo.tmp is executable: 0 File fifo.tmp is a FIFO: 1 File fifo.tmp is a symlink: 0 File fifo.tmp is a block device file: 0 File fifo.tmp is a character device file: 0 The size of fifo.tmp is -1 bytes The type of fifo.tmp is p runawk-runawk-1.6.1/test/test.sh000077500000000000000000000333601343160141100166270ustar00rootroot00000000000000#!/bin/sh set -e LC_ALL=C export LC_ALL cd ${SRCDIR}/test unify_paths (){ sed -e "s,/.*/test/,/ROOT/," \ -e 's,/tmp/runawk[.]......,/tmp/runawk.NNNNNN,' \ -e 's,new_argv \[0\] = .*awk.*,new_argv [0] = awk,' \ -e 's,ARGV\[0\]=.*awk.*,ARGV[0]=awk,' \ -e 's,FILENAME=-$,FILENAME=,' \ -e 's,/tmp/awk[.][^/]*/,/tmp/awk.XXXX/,' } runtest_header (){ echo '--------------------------------------------------' printf ' ------ args: %s\n' "$*" | unify_paths } runtest_main (){ $OBJDIR_runawk/runawk "$@" 2>&1 | grep -v '/_test_program' | unify_paths } runtest (){ runtest_header "$@" runtest_main "$@" } runtest_nostderr (){ runtest_header "$@" # runtest_main "$@" '2>/dev/null' $OBJDIR_runawk/runawk "$@" 2>/dev/null | grep -v '/_test_program' | unify_paths } PATH=${SRCDIR}/examples:${SRCDIR}/a_getopt:${OBJDIR_runawk}:$PATH export PATH #################### AWKPATH=${SRCDIR}/modules export AWKPATH trap 'rm -f _test_program _test.tmp' 0 1 2 3 15 touch _test_program runtest -d _test_program runtest -d _test_program --long-option runtest -d _test_program -o=file runtest -d _test_program fn1 fn2 runtest -d -f abs.awk -e 'BEGIN {print abs(-123), abs(234); exit}' runtest -d -f alt_assert.awk -e 'BEGIN {exit}' runtest -V | awk 'NR <= 2 {print $0} NR == 3 {print "xxx"}' runtest -h | awk 'NR <= 3' runtest -e 'BEGIN {print "Hello World"}' runtest -v one=1 -e 'BEGIN {print one} {print "unbelievably"}' /dev/null runtest -v two=2 -e 'BEGIN {print two}' runtest -e 'BEGIN {print "Hello World"}' /dev/null runtest -v var1=123 -v var2=321 -e 'BEGIN {print var1, var2}' unset AWKPATH || true ################## use cat > _test.tmp <&1 | sed 's/failed:.*/failed/' } # success interp_var_test # failure INTERP_VAR_TEST=/invalid/path export INTERP_VAR_TEST interp_var_test unset INTERP_VAR_TEST #################### runtest_header '#safe-use directive' touch $TESTTEMPDIR/temp1.awk touch $TESTTEMPDIR/temp2.awk safe_use_test (){ echo "--- #safe-use test: ---" $OBJDIR_runawk/runawk -d -e " #safe-use \"$1\" \"$2\" \"$3\" BEGIN { print 123 exit 0 } " | unify_paths | sed -e 's,/[^ ]*/temp1.awk,/path/temp1.awk,' \ -e 's,/[^ ]*/temp2.awk,/path/temp2.awk,' } safe_use_test "/bad/path1" "$TESTTEMPDIR/temp1.awk" "/bad/path2" safe_use_test "$TESTTEMPDIR/temp1.awk" "/bad/path2" "/bad/path1" safe_use_test "/bad/path1" "$TESTTEMPDIR/temp3.awk" "$TESTTEMPDIR/temp2.awk" safe_use_test "/bad/path3" "/bad/path2" "/bad/path1" #################### runtest -e ' #use "/invalid/path/file.awk" ' #################### runtest -d -e ' BEGIN { for (i=0; i < ARGC; ++i){ printf "ARGV [%s]=%s\n", i, ARGV [i] } }' -- -a -b -c #################### runtest -e ' BEGIN { for (i=1; i < ARGC; ++i){ printf "ARGV [%s]=%s\n", i, ARGV [i] } }' -- file1 file2 file3 #################### runtest -d -e ' #env "LC_ALL=C" #env "FOO2=bar2" BEGIN { ... }' runtest -e ' #env "LC_ALL=C" #env "FOO2=bar2" BEGIN { print ("y" ~ /^[a-z]$/) print ("Y" ~ /^[a-z]$/) print ("z" ~ /^[a-z]$/) print ("Z" ~ /^[a-z]$/) print ("env FOO2=" ENVIRON ["FOO2"]) } ' runtest -e 'BEGIN {print 1}' -e 'BEGIN {print 2}' #################### AWKPATH=${SRCDIR}/modules export AWKPATH runtest -d -e ' #use "alt_assert.awk" BEGIN { print "Hello world!" abort("just a test", 7) } ' /dev/null runtest -e ' #use "alt_assert.awk" BEGIN { abort("just a test", 7) } ' runtest -f abs.awk -e 'BEGIN {print abs(-123), abs(234); exit}' runtest -f alt_assert.awk -e 'BEGIN {assert(0, "Hello assert!")}' #################### printf ' a b c \na\t b \tc \n' | runtest -Te ' { for (i=1; i <= NF; ++i){ printf "$%d=%s\n", i, $i } }' ############################################################ AWKPATH=${SRCDIR}/modules:${SRCDIR}/modules/gawk export AWKPATH #################### multisub runtest ../examples/demo_multisub #################### tokenre runtest ../examples/demo_tokenre ../examples/demo_tokenre.in runtest ../examples/demo_tokenre2 ../examples/demo_tokenre2.in runtest ../examples/demo_tokenre3 ../examples/demo_tokenre3.in runtest ../examples/demo_tokenre4 ../examples/demo_tokenre3.in #################### splitre runtest ../examples/demo_splitre ../examples/demo_tokenre2.in #################### getopt runtest ../examples/demo_alt_getopt -h - runtest ../examples/demo_alt_getopt --help runtest ../examples/demo_alt_getopt -h --help -v --verbose -V -o 123 -o234 runtest ../examples/demo_alt_getopt --output 123 --output 234 -n 999 -n9999 --len 5 --fake /dev/null runtest ../examples/demo_alt_getopt -hVv -- -1 -2 -3 runtest ../examples/demo_alt_getopt --fake -v -- -1 -2 -3 runtest ../examples/demo_alt_getopt - -1 -2 -3 runtest ../examples/demo_alt_getopt --fake -v - -1 -2 -3 runtest ../examples/demo_alt_getopt -1 -2 -3 runtest ../examples/demo_alt_getopt -hvV runtest ../examples/demo_alt_getopt -ho 123 runtest ../examples/demo_alt_getopt -hoV 123 runtest ../examples/demo_alt_getopt --unknown runtest ../examples/demo_alt_getopt --output='file.out' -nNNN --len=LENGTH runtest ../examples/demo_alt_getopt --output --file-- #################### modinfo runtest ../examples/demo_modinfo #################### has_suffix runtest ../examples/demo_has_suffix ../examples/demo_has_suffix.in #################### has_prefix runtest ../examples/demo_has_prefix ../examples/demo_has_prefix.in #################### dirname runtest ../examples/demo_dirname runtest ../examples/demo_dirname /path/to/file runtest ../examples/demo_dirname file.txt runtest ../examples/demo_dirname / runtest ../examples/demo_dirname /dir/ #################### basename runtest ../examples/demo_basename runtest ../examples/demo_basename /path/to/file runtest ../examples/demo_basename file.txt runtest ../examples/demo_basename / runtest ../examples/demo_basename /dir/ runtest ../examples/demo_basename /path/to/file.txt .txt runtest ../examples/demo_basename file.txt .txt runtest ../examples/demo_basename / .txt runtest ../examples/demo_basename /dir/ .txt runtest ../examples/demo_basename /path/to/file.txt .log runtest ../examples/demo_basename file.txt .log runtest ../examples/demo_basename / .log runtest ../examples/demo_basename /dir/ .log #################### shquote runtest ../examples/demo_shquote ../examples/demo_shquote.in #################### alt_join runtest_nostderr ../examples/demo_alt_join #################### readfile runtest ../examples/demo_readfile runtest ../examples/demo_readfile ../examples/demo_readfile.in #################### power_getopt runtest ../examples/demo_power_getopt echo ////////////////////////////////////////////////// runtest ../examples/demo_power_getopt -ffss --flag --long-flag | sort echo ////////////////////////////////////////////////// runtest ../examples/demo_power_getopt -h 2>&1 | sort echo ////////////////////////////////////////////////// runtest ../examples/demo_power_getopt -f --long-flag -s -F123 --FLAG=234 --LONG-FLAG 345 -S 456 2>&1 | sort echo ////////////////////////////////////////////////// runtest ../examples/demo_power_getopt -f --long-flag -s -F123 --FLAG=234 --LONG-FLAG 345 -S 456 -P arg1 '' arg3 arg4 '' 2>&1 | sort echo ////////////////////////////////////////////////// runtest ../examples/demo_power_getopt2 --help runtest ../examples/demo_power_getopt2 -? #################### runcmd runtest ../examples/demo_runcmd #################### heapsort runtest_header ../examples/demo_heapsort2 for i in 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0; do runtest_main ../examples/demo_heapsort2 done runtest ../examples/demo_heapsort < ../examples/demo_heapsort.in runtest ../examples/demo_heapsort3 < ../examples/demo_heapsort3.in runtest ../examples/demo_heapsort4 < ../examples/demo_heapsort4.in #################### quicksort runtest_header ../examples/demo_quicksort2 for i in 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0; do runtest_main ../examples/demo_quicksort2 done runtest ../examples/demo_quicksort < ../examples/demo_heapsort.in runtest ../examples/demo_quicksort3 < ../examples/demo_heapsort3.in #################### fieldwidths runtest ../examples/demo_fieldwidths < ../examples/demo_fieldwidths.in #################### tmpfile runtest ../examples/demo_tmpfile #################### trim runtest ../examples/demo_trim ../examples/demo_trim.in #################### trim_in runtest ../examples/demo_trim_in ../examples/demo_trim.in runtest -v TRIM=' ' ../examples/demo_trim_in ../examples/demo_trim.in runtest -v TRIM='c' ../examples/demo_trim_in ../examples/demo_trim.in #################### glob.awk runtest ../examples/demo_glob2ere #################### backslash_in runtest ../examples/demo_backslash_in ../examples/demo_backslash_in.in #################### ini runtest ../examples/demo_ini : ../examples/demo_ini.in runtest ../examples/demo_ini '' ../examples/demo_ini.in #################### alt_getopt(1) test_process_args (){ alt_getopt \ 'v|verbose' 'verbose=1' \ 'h help' help \ 'fake' fake_flag=1 \ '=len' len= \ '=o output' output= \ '=m msg' "msg=" \ 'V version' "echo 'alt_getopt-0-1-0 written by Aleksey Cheusov '" \ =n number= \ -- "$@" } runtest_header 'alt_getopt #1' test_process_args \ -h --help -v --verbose -V -o 123 -o234 --output 'file with spaces' -n 999 -n9999 --len 5 --fake \ -hVv --len 10 --len=100 -m "Aleksey's cat is female" \ --msg="backslashes (\) is not a problem too" -- -1 -2 -3 #################### demo_alt_getopt.sh runtest_header 'demo_alt_getopt.sh #1' ../examples/demo_alt_getopt.sh #################### demo_alt_getopt.sh runtest_header 'demo_alt_getopt.sh #1.5' ../examples/demo_alt_getopt.sh arg1 arg2 arg3 #################### demo_alt_getopt.sh runtest_header 'demo_alt_getopt.sh #2' ../examples/demo_alt_getopt.sh -n123 -m "Aleksey's cat is female" arg1 #################### demo_alt_getopt.sh runtest_header 'demo_alt_getopt.sh #3' ../examples/demo_alt_getopt.sh --len=123 -m "Aleksey's cat is female" arg1 arg2 #################### demo_alt_getopt.sh runtest_header 'demo_alt_getopt.sh #4' ../examples/demo_alt_getopt.sh --len 123 -f -m "Aleksey's cat is female" -- -a1 -a2 #################### demo_alt_getopt.sh runtest_header 'demo_alt_getopt.sh #5' ../examples/demo_alt_getopt.sh -n123 --o file.txt -fhFvvv --len=100 \ -o/path/to/file.out 2>&1 #################### demo_alt_getopt.sh runtest_header 'demo_alt_getopt.sh #5' ../examples/demo_alt_getopt.sh -n 123 --o file.txt -fhFvq --len=100 \ -o/path/to/file.out 2>&1 #################### demo_alt_getopt.sh runtest_header 'demo_alt_getopt2.sh #1' ../examples/demo_alt_getopt2.sh -h 2>&1 #################### demo_alt_getopt.sh runtest_header 'demo_alt_getopt2.sh #2' ../examples/demo_alt_getopt2.sh --version 2>&1 #################### demo_alt_getopt.sh runtest_header 'demo_alt_getopt2.sh #3' ../examples/demo_alt_getopt2.sh -o '/path/to/file with spaces.txt' 2>&1 #################### demo_alt_getopt.sh runtest_header 'demo_alt_getopt2.sh #4' ../examples/demo_alt_getopt2.sh -ofile.txt arg1 arg2 arg3 2>&1 #################### demo_alt_getopt.sh runtest_header 'demo_alt_getopt2.sh #5' ../examples/demo_alt_getopt2.sh -- -ofile.txt arg1 2>&1 #################### demo_alt_getopt.sh runtest_header 'demo_alt_getopt2.sh #6' ../examples/demo_alt_getopt2.sh -- -o file.txt arg1 2>&1 #################### demo_alt_getopt.sh runtest_header 'demo_alt_getopt2.sh #7' ../examples/demo_alt_getopt2.sh -o file.txt arg1 2>&1 #################### minmax runtest_header 'demo_minmax #1' ../examples/demo_minmax 1>&2 #################### ftrans runtest ../examples/demo_ftrans /dev/null runtest ../examples/demo_ftrans \ ../examples/demo_readfile.in runtest ../examples/demo_ftrans \ ../examples/demo_readfile.in ../examples/demo_shquote.in \ ../examples/demo_fieldwidths.in runtest ../examples/demo_ftrans <<'EOF' foo bar baz EOF #################### -F runtest_header '-F #1' $OBJDIR_runawk/runawk -F: -d -e '{print}' | unify_paths runtest_header '-F #2' $OBJDIR_runawk/runawk -d -F: -e '{print}' | unify_paths runtest_header '-F #3' echo '1:2:3:4' | $OBJDIR_runawk/runawk -F: -v a=1 -e '{print "a=" a, NF ":" $1, $2, $3, $4}' echo '1:2:3:4' | $OBJDIR_runawk/runawk -v b=2 -F: -e '{print "b=" b, NF ":" $1, $2, $3, $4}' #################### xargs + runawk runtest_header 'xargs + runawk #1' awk 'BEGIN {for (i=0; i < 100000; ++i){print (i % 1000)}}' | xargs $OBJDIR_runawk/runawk -e 'BEGIN {for (i=1; i < ARGC; ++i) print ARGV [i]}' | awk '{cnt += $1} END {print cnt}' #################### exitnow.awk runtest_header 'exitnow.awk #1' echo '' | $OBJDIR_runawk/runawk -f exitnow.awk \ -e 'BEGIN {exitnow(0)} END {print "Bad!"}' | unify_paths #################### exitnow.awk demo_io_input_data (){ cat << 'EOF' ../Makefile /nonexistent /dev/null . symlink.tmp fifo.tmp EOF } ln -s test.sh symlink.tmp mkfifo fifo.tmp demo_io_input_data | runtest ../examples/demo_io rm symlink.tmp fifo.tmp