diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 00000000..18473358
Binary files /dev/null and b/.DS_Store differ
diff --git a/.gitignore b/.gitignore
index 2c2a517e..ee8632c7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,6 +16,9 @@
.*.sw?
# Downloaded files:
+/build/
+/release/
+/smallRelease/
/Frameworks/
/curl/
/file_cmds/
@@ -24,6 +27,8 @@
/libutil/
/shell_cmds/
/text_cmds/
+/network_cmds-543/
+/ssh_keygen_110/
# Precompiled Headers
*.gch
diff --git a/TODO b/TODO
new file mode 100644
index 00000000..c25523b4
--- /dev/null
+++ b/TODO
@@ -0,0 +1,25 @@
+REVIEWS !
+
+- still crashing randomly. But less often.
+
+- write Lua script for TeX format creation from fmtutil.cnf
+- write Lua script for ls-lR generation (?)
+- write Lua script for tlmgr update ?
+
+- add file coordinator / file presenter stuff. Done
+- add dlopen / dlsym / dlclose stuff ?
+ Would open the way for local compilers.
+
+- e-mail Luigi Scarso
+
+- Python: numpy, matplotlib make more sense inside Pythonista, seriously
+- Stop trying to make it happen inside Blink, it won't, seriously. OK.
+
+- keep adding strerror(errno) to all commands in ios_system. Except warnx, errx.
+- swift programming?
+
+- move to Swift? Why?
+- git swift mapping? Hard.
+
+- Jupyter ?
+
diff --git a/TODO2 b/TODO2
new file mode 100644
index 00000000..d98ac5bc
--- /dev/null
+++ b/TODO2
@@ -0,0 +1,38 @@
+procfile("-")
+then grep_open(NULL)
+
+Now: grep is the first thread to reach phtread_start
+And it has been "joined"
+So the second thread never starts. Need to "not join".
+
+If I don't join, by the time grep starts, everything has been erased.
+
+So need to wait for the thread to be active, then release.
+
+
+- replace STDIN_FILENO with fileno(thread_stdin). Can't use #define
+- replace all isatty
+- TODO: also TeX/LaTeX. Keep compatible?
+- X move global variables to __thread for multi-calls.
+
+- todo: add ID of stream to close to params (in and out)
+- don't close streams equal to thread_stdout, someone else will.
+- don't close threads for system(), only for popen. Will be hard.
+- easy to close out-stream after popen, harder to close in-stream.
+
+X __thread for all commands in all groups
+! extern variables inside functions also
+X continue testing
+- create new patches for Python and Lua
+- test if python now works with system(python) (ballsy)
+X fileno(thread_stdout) does not exist.
+
+- TODO (now):
+X ssh + command (easy-ish).
+X mercurial calls subprocess.Popen(), it seems.
+X popen does not call posix_popen
+X dup2 inside execute_child. To state "p2cread == (new process) stdin"
+- can use that.
+- Need to think about what Popen does.
+
+X hg connects but doesn't read data / write ?
diff --git a/awk/.gitignore b/awk/.gitignore
new file mode 100644
index 00000000..95c43209
--- /dev/null
+++ b/awk/.gitignore
@@ -0,0 +1,5 @@
+.DS_Store
+/.build
+/Packages
+/*.xcodeproj
+xcuserdata/
diff --git a/awk/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/awk/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 00000000..706eedee
--- /dev/null
+++ b/awk/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/ios_system.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/awk/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
similarity index 100%
rename from ios_system.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
rename to awk/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
diff --git a/awk/Package.swift b/awk/Package.swift
new file mode 100644
index 00000000..303ae444
--- /dev/null
+++ b/awk/Package.swift
@@ -0,0 +1,35 @@
+// swift-tools-version:5.2
+// The swift-tools-version declares the minimum version of Swift required to build this package.
+
+import PackageDescription
+
+let package = Package(
+ name: "awk",
+ // thread-local variables are only available with iOS 11+. This setting is required for compilation.
+ platforms: [.iOS(.v11)],
+ products: [
+ // Products define the executables and libraries produced by a package, and make them visible to other packages.
+ .library(
+ name: "awk",
+ targets: ["awk"]),
+ ],
+ dependencies: [
+ // Dependencies declare other packages that this package depends on.
+ // .package(url: /* package url */, from: "1.0.0"),
+ // Depends on the local package, ios_system:
+ .package(path: "../ios_system")
+ ],
+ targets: [
+ // Targets are the basic building blocks of a package. A target can define a module or a test suite.
+ // Targets can depend on other targets in this package, and on products in packages which this package depends on.
+ .target(
+ name: "awk",
+ dependencies: ["ios_system"],
+ exclude: [],
+ cSettings: [.headerSearchPath("../"),
+ .headerSearchPath("./"),
+ ],
+ linkerSettings: [.linkedFramework("ios_system")]
+ ),
+ ]
+)
diff --git a/awk/README.md b/awk/README.md
new file mode 100644
index 00000000..687d7480
--- /dev/null
+++ b/awk/README.md
@@ -0,0 +1,3 @@
+# awk
+
+A description of this package.
diff --git a/awk/Sources/awk/awk.h b/awk/Sources/awk/awk.h
new file mode 100644
index 00000000..b991a4ed
--- /dev/null
+++ b/awk/Sources/awk/awk.h
@@ -0,0 +1,235 @@
+/****************************************************************
+Copyright (C) Lucent Technologies 1997
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name Lucent Technologies or any of
+its entities not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+****************************************************************/
+
+#include
+
+typedef double Awkfloat;
+
+/* unsigned char is more trouble than it's worth */
+
+typedef unsigned char uschar;
+
+#define xfree(a) { if ((a) != NULL) { free((void *) (a)); (a) = NULL; } }
+
+#define NN(p) ((p) ? (p) : "(null)") /* guaranteed non-null for dprintf
+*/
+#define DEBUG
+#ifdef DEBUG
+ /* uses have to be doubly parenthesized */
+# define dprintf(x) if (dbg) fprintf x
+#else
+# define dprintf(x)
+#endif
+
+extern __thread int compile_time; /* 1 if compiling, 0 if running */
+extern __thread int safe; /* 0 => unsafe, 1 => safe */
+extern __thread int Unix2003_compat;
+
+#define RECSIZE (8 * 1024) /* sets limit on records, fields, etc., etc. */
+extern __thread int recsize; /* size of current record, orig RECSIZE */
+
+extern __thread char **FS;
+extern __thread char **RS;
+extern __thread char **ORS;
+extern __thread char **OFS;
+extern __thread char **OFMT;
+extern __thread Awkfloat *NR;
+extern __thread Awkfloat *FNR;
+extern __thread Awkfloat *NF;
+extern __thread char **FILENAME;
+extern __thread char **SUBSEP;
+extern __thread Awkfloat *RSTART;
+extern __thread Awkfloat *RLENGTH;
+
+extern __thread char *record; /* points to $0 */
+extern __thread int lineno; /* line number in awk program */
+extern __thread int errorflag; /* 1 if error has occurred */
+extern __thread int donefld; /* 1 if record broken into fields */
+extern __thread int donerec; /* 1 if record is valid (no fld has changed */
+extern __thread char inputFS[]; /* FS at time of input, for field splitting */
+
+extern __thread int dbg;
+
+extern __thread char *patbeg; /* beginning of pattern matched */
+extern __thread int patlen; /* length of pattern matched. set in b.c */
+
+/* Cell: all information about a variable or constant */
+
+typedef struct Cell {
+ uschar ctype; /* OCELL, OBOOL, OJUMP, etc. */
+ uschar csub; /* CCON, CTEMP, CFLD, etc. */
+ char *nval; /* name, for variables only */
+ char *sval; /* string value */
+ Awkfloat fval; /* value as number */
+ int tval; /* type info: STR|NUM|ARR|FCN|FLD|CON|DONTFREE */
+ struct Cell *cnext; /* ptr to next if chained */
+} Cell;
+
+typedef struct Array { /* symbol table array */
+ int nelem; /* elements in table right now */
+ int size; /* size of tab */
+ Cell **tab; /* hash table pointers */
+} Array;
+
+#define NSYMTAB 50 /* initial size of a symbol table */
+extern __thread Array *symtab;
+
+extern __thread Cell *nrloc; /* NR */
+extern __thread Cell *fnrloc; /* FNR */
+extern __thread Cell *nfloc; /* NF */
+extern __thread Cell *rstartloc; /* RSTART */
+extern __thread Cell *rlengthloc; /* RLENGTH */
+
+/* Cell.tval values: */
+#define NUM 01 /* number value is valid */
+#define STR 02 /* string value is valid */
+#define DONTFREE 04 /* string space is not freeable */
+#define CON 010 /* this is a constant */
+#define ARR 020 /* this is an array */
+#define FCN 040 /* this is a function name */
+#define FLD 0100 /* this is a field $1, $2, ... */
+#define REC 0200 /* this is $0 */
+
+
+/* function types */
+#define FLENGTH 1
+#define FSQRT 2
+#define FEXP 3
+#define FLOG 4
+#define FINT 5
+#define FSYSTEM 6
+#define FRAND 7
+#define FSRAND 8
+#define FSIN 9
+#define FCOS 10
+#define FATAN 11
+#define FTOUPPER 12
+#define FTOLOWER 13
+#define FFLUSH 14
+
+/* Node: parse tree is made of nodes, with Cell's at bottom */
+
+typedef struct Node {
+ int ntype;
+ struct Node *nnext;
+ int lineno;
+ int nobj;
+ int nnarg;
+ struct Node *narg[1]; /* variable: actual size set by calling malloc */
+} Node;
+
+#define NIL ((Node *) 0)
+
+extern __thread Node *winner;
+extern __thread Node *nullstat;
+extern __thread Node *nullnode;
+
+/* ctypes */
+#define OCELL 1
+#define OBOOL 2
+#define OJUMP 3
+
+/* Cell subtypes: csub */
+#define CFREE 7
+#define CCOPY 6
+#define CCON 5
+#define CTEMP 4
+#define CNAME 3
+#define CVAR 2
+#define CFLD 1
+#define CUNK 0
+
+/* bool subtypes */
+#define BTRUE 11
+#define BFALSE 12
+
+/* jump subtypes */
+#define JEXIT 21
+#define JNEXT 22
+#define JBREAK 23
+#define JCONT 24
+#define JRET 25
+#define JNEXTFILE 26
+
+/* node types */
+#define NVALUE 1
+#define NSTAT 2
+#define NEXPR 3
+
+
+extern __thread int pairstack[], paircnt;
+
+#define notlegal(n) (n <= FIRSTTOKEN || n >= LASTTOKEN || proctab[n-FIRSTTOKEN] == nullproc)
+#define isvalue(n) ((n)->ntype == NVALUE)
+#define isexpr(n) ((n)->ntype == NEXPR)
+#define isjump(n) ((n)->ctype == OJUMP)
+#define isexit(n) ((n)->csub == JEXIT)
+#define isbreak(n) ((n)->csub == JBREAK)
+#define iscont(n) ((n)->csub == JCONT)
+#define isnext(n) ((n)->csub == JNEXT || (n)->csub == JNEXTFILE)
+#define isret(n) ((n)->csub == JRET)
+#define isrec(n) ((n)->tval & REC)
+#define isfld(n) ((n)->tval & FLD)
+#define isstr(n) ((n)->tval & STR)
+#define isnum(n) ((n)->tval & NUM)
+#define isarr(n) ((n)->tval & ARR)
+#define isfcn(n) ((n)->tval & FCN)
+#define istrue(n) ((n)->csub == BTRUE)
+#define istemp(n) ((n)->csub == CTEMP)
+#define isargument(n) ((n)->nobj == ARG)
+/* #define freeable(p) (!((p)->tval & DONTFREE)) */
+#define freeable(p) ( ((p)->tval & (STR|DONTFREE)) == STR )
+
+/* structures used by regular expression matching machinery, mostly b.c: */
+
+#define NCHARS (256+3) /* 256 handles 8-bit chars; 128 does 7-bit */
+ /* watch out in match(), etc. */
+#define NSTATES 32
+
+typedef struct rrow {
+ long ltype; /* long avoids pointer warnings on 64-bit */
+ union {
+ int i;
+ Node *np;
+ uschar *up;
+ } lval; /* because Al stores a pointer in it! */
+ int *lfollow;
+} rrow;
+
+typedef struct fa {
+ uschar gototab[NSTATES][NCHARS];
+ uschar out[NSTATES];
+ uschar *restr;
+ int *posns[NSTATES];
+ int anchor;
+ int use;
+ int initstat;
+ int curstat;
+ int accept;
+ int reset;
+ struct rrow re[1]; /* variable: actual size set by calling malloc */
+} fa;
+
+
+#include "proto.h"
diff --git a/awk/Sources/awk/awk_main.c b/awk/Sources/awk/awk_main.c
new file mode 100644
index 00000000..7e0f83cf
--- /dev/null
+++ b/awk/Sources/awk/awk_main.c
@@ -0,0 +1,250 @@
+/****************************************************************
+Copyright (C) Lucent Technologies 1997
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name Lucent Technologies or any of
+its entities not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+****************************************************************/
+
+const char *version = "version 20070501";
+
+#define DEBUG
+#include
+#include
+#include
+#include
+#include
+#include
+#include "awk.h"
+#include "ytab.h"
+
+// #ifdef __APPLE__
+// #include "get_compat.h"
+// #else
+#define COMPAT_MODE(func, mode) 1
+// #endif
+#include "ios_error.h"
+
+extern char **environ;
+extern __thread int nfields;
+
+__thread int dbg = 0; // Set to 1 for serious debugging
+__thread char *cmdname; /* gets argv[0] for error messages */
+extern __thread FILE *yyin; /* lex input file */
+__thread char *lexprog; /* points to program argument if it exists */
+extern __thread int errorflag; /* non-zero if any syntax errors; set by yyerror */
+__thread int compile_time = 2; /* for error printing: */
+ /* 2 = cmdline, 1 = compile, 0 = running */
+
+#define MAX_PFILE 20 /* max number of -f's */
+
+static __thread char *pfile[MAX_PFILE]; /* program filenames from -f's */
+static __thread int npfile = 0; /* number of filenames */
+static __thread int curpfile = 0; /* current filename */
+
+__thread int safe = 0; /* 1 => "safe" mode */
+__thread int Unix2003_compat;
+
+static void initializeVariables() {
+ // initialize all flags:
+ cmdname = NULL;
+ extern __thread int infunc;
+ infunc = 0; /* = 1 if in arglist or body of func */
+ extern __thread int inloop;
+ inloop = 0; /* = 1 if in while, for, do */
+
+ extern __thread int *setvec;
+ extern __thread int *tmpset;
+ if (setvec != 0) { /* first time through any RE */
+ free(setvec); setvec = 0;
+ free(tmpset); tmpset = 0;
+ }
+ yyin = 0;
+ nfields = 2; // MAXFLD
+ npfile = 0;
+ curpfile = 0;
+ compile_time = 2;
+ errorflag = 0;
+ lexprog = 0;
+ extern __thread int awk_firsttime;
+ awk_firsttime = 1;
+
+ extern __thread int lastfld;
+ lastfld = 0; /* last used field */
+ extern __thread int argno;
+ argno = 1; /* current input argument number */
+ if (symtab != NULL) {
+ free(symtab->tab);
+ free(symtab);
+ symtab = NULL;
+ }
+ // Variables from lib.c
+ if (record) { free(record); record = NULL;}
+ recsize = RECSIZE;
+ extern __thread char *fields;
+ if (fields) { free(fields); fields = NULL; }
+ extern __thread int fieldssize;
+ fieldssize = RECSIZE;
+ extern __thread Cell **fldtab; /* pointers to Cells */
+ if (fldtab) { free(fldtab); fldtab = NULL; }
+}
+
+
+int awk_main(int argc, char *argv[])
+{
+ const char *fs = NULL;
+ initializeVariables();
+
+ setlocale(LC_CTYPE, "");
+ setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */
+ cmdname = argv[0];
+ if (argc == 1) {
+ fprintf(thread_stderr,
+ "usage: %s [-F fs] [-v var=value] [-f progfile | 'prog'] [file ...]\n",
+ cmdname);
+ exit(1);
+ }
+ Unix2003_compat = COMPAT_MODE("bin/awk", "unix2003");
+ signal(SIGFPE, fpecatch);
+ yyin = NULL;
+ symtab = makesymtab(NSYMTAB/NSYMTAB);
+ while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
+ if (strcmp(argv[1],"-version") == 0 || strcmp(argv[1],"--version") == 0) {
+ fprintf(thread_stdout, "awk %s\n", version);
+ exit(0);
+ break;
+ }
+ if (strncmp(argv[1], "--", 2) == 0) { /* explicit end of args */
+ argc--;
+ argv++;
+ break;
+ }
+ switch (argv[1][1]) {
+ case 's':
+ if (strcmp(argv[1], "-safe") == 0)
+ safe = 1;
+ break;
+ case 'f': /* next argument is program filename */
+ argc--;
+ argv++;
+ if (argc <= 1)
+ FATAL("no program filename");
+ if (npfile >= MAX_PFILE - 1)
+ FATAL("too many -f options");
+ pfile[npfile++] = argv[1];
+ break;
+ case 'F': /* set field separator */
+ if (argv[1][2] != 0) { /* arg is -Fsomething */
+ if (argv[1][2] == 't' && argv[1][3] == 0) /* wart: t=>\t */
+ fs = "\t";
+ else if (argv[1][2] != 0)
+ fs = &argv[1][2];
+ } else { /* arg is -F something */
+ argc--; argv++;
+ if (argc > 1 && argv[1][0] == 't' && argv[1][1] == 0) /* wart: t=>\t */
+ fs = "\t";
+ else if (argc > 1 && argv[1][0] != 0)
+ fs = &argv[1][0];
+ }
+ if (fs == NULL || *fs == '\0')
+ WARNING("field separator FS is empty");
+ break;
+ case 'v': /* -v a=1 to be done NOW. one -v for each */
+ if (argv[1][2] == '\0' && --argc > 1 && isclvar((++argv)[1]))
+ setclvar(argv[1]);
+ else
+ FATAL("invalid -v option");
+ break;
+ case 'd':
+ dbg = atoi(&argv[1][2]);
+ if (dbg == 0)
+ dbg = 1;
+ fprintf(thread_stdout, "awk %s\n", version);
+ break;
+ default:
+ WARNING("unknown option %s ignored", argv[1]);
+ break;
+ }
+ argc--;
+ argv++;
+ }
+ /* argv[1] is now the first argument */
+ if (npfile == 0) { /* no -f; first argument is program */
+ if (argc <= 1) {
+ if (dbg)
+ exit(0);
+ FATAL("no program given");
+ }
+ dprintf( (thread_stdout, "program = |%s|\n", argv[1]) );
+ lexprog = argv[1];
+ argc--;
+ argv++;
+ }
+ recinit(recsize);
+ syminit();
+ compile_time = 1;
+ argv[0] = cmdname; /* put prog name at front of arglist */
+ dprintf( (thread_stdout, "argc=%d, argv[0]=%s\n", argc, argv[0]) );
+ arginit(argc, argv);
+ if (!safe)
+ envinit(environ);
+ yyparse();
+ setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */
+ if (fs)
+ *FS = qstring(fs, '\0');
+ dprintf( (thread_stdout, "errorflag=%d\n", errorflag) );
+ if (errorflag == 0) {
+ compile_time = 0;
+ run(winner);
+ winner = NULL;
+ } else
+ bracecheck();
+ return(errorflag);
+}
+
+int pgetc(void) /* get 1 character from awk program */
+{
+ int c;
+
+ for (;;) {
+ if (yyin == NULL) {
+ if (curpfile >= npfile)
+ return EOF;
+ if (strcmp(pfile[curpfile], "-") == 0)
+ yyin = thread_stdin;
+ else if ((yyin = fopen(pfile[curpfile], "r")) == NULL)
+ FATAL("can't open file %s", pfile[curpfile]);
+ lineno = 1;
+ }
+ if ((c = getc(yyin)) != EOF)
+ return c;
+ if (yyin != thread_stdin)
+ fclose(yyin);
+ yyin = NULL;
+ curpfile++;
+ }
+}
+
+char *cursource(void) /* current source file name */
+{
+ if (npfile > 0)
+ return pfile[curpfile];
+ else
+ return NULL;
+}
diff --git a/awk/Sources/awk/b.c b/awk/Sources/awk/b.c
new file mode 100644
index 00000000..36975542
--- /dev/null
+++ b/awk/Sources/awk/b.c
@@ -0,0 +1,1271 @@
+/****************************************************************
+Copyright (C) Lucent Technologies 1997
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name Lucent Technologies or any of
+its entities not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+****************************************************************/
+
+/* lasciate ogne speranza, voi ch'intrate. */
+
+#define DEBUG
+
+#include
+#include
+#include
+#include
+#include "awk.h"
+#include "ytab.h"
+#include
+#include "ios_error.h"
+
+#define HAT (NCHARS+2) /* matches ^ in regular expr */
+ /* NCHARS is 2**n */
+#define MAXLIN 22
+
+#define type(v) (v)->nobj /* badly overloaded here */
+#define info(v) (v)->ntype /* badly overloaded here */
+#define left(v) (v)->narg[0]
+#define right(v) (v)->narg[1]
+#define parent(v) (v)->nnext
+
+#define LEAF case CCL: case NCCL: case CHAR: case DOT: case FINAL: case ALL:
+#define ELEAF case EMPTYRE: /* empty string in regexp */
+#define UNARY case STAR: case PLUS: case QUEST:
+
+/* encoding in tree Nodes:
+ leaf (CCL, NCCL, CHAR, DOT, FINAL, ALL, EMPTYRE):
+ left is index, right contains value or pointer to value
+ unary (STAR, PLUS, QUEST): left is child, right is null
+ binary (CAT, OR): left and right are children
+ parent contains pointer to parent
+*/
+
+
+__thread int *setvec;
+__thread int *tmpset;
+static __thread int maxsetvec = 0;
+
+static __thread int rtok; /* next token in current re */
+static __thread int rlxval;
+static __thread uschar *rlxstr;
+static __thread uschar *prestr; /* current position in current re */
+static __thread uschar *lastre; /* origin of last re */
+static __thread uschar *lastatom; /* origin of last Atom */
+static __thread uschar *starttok;
+static __thread char *basestr; /* starts with original, replaced during
+ repetition processing */
+static __thread char *firstbasestr;
+
+static __thread FILE * replogfile = 0;
+
+static __thread int setcnt;
+static __thread int poscnt;
+
+__thread char *patbeg;
+__thread int patlen;
+
+#define NFA 20 /* cache this many dynamic fa's */
+static __thread fa *fatab[NFA];
+static __thread int nfatab = 0; /* entries in fatab */
+
+fa *makedfa(const char *s, int anchor) /* returns dfa for reg expr s */
+{
+ int i, use, nuse;
+ fa *pfa;
+ static __thread int now = 1;
+
+ if (setvec == 0) { /* first time through any RE */
+ maxsetvec = MAXLIN;
+ setvec = (int *) malloc(maxsetvec * sizeof(int));
+ tmpset = (int *) malloc(maxsetvec * sizeof(int));
+ if (setvec == 0 || tmpset == 0)
+ overflo("out of space initializing makedfa");
+ }
+
+ if (compile_time) /* a constant for sure */
+ return mkdfa(s, anchor);
+ for (i = 0; i < nfatab; i++) /* is it there already? */
+ if (fatab[i]->anchor == anchor
+ && strcmp((const char *) fatab[i]->restr, s) == 0) {
+ fatab[i]->use = now++;
+ return fatab[i];
+ }
+ pfa = mkdfa(s, anchor);
+ if (nfatab < NFA) { /* room for another */
+ fatab[nfatab] = pfa;
+ fatab[nfatab]->use = now++;
+ nfatab++;
+ return pfa;
+ }
+ use = fatab[0]->use; /* replace least-recently used */
+ nuse = 0;
+ for (i = 1; i < nfatab; i++)
+ if (fatab[i]->use < use) {
+ use = fatab[i]->use;
+ nuse = i;
+ }
+ freefa(fatab[nuse]);
+ fatab[nuse] = pfa;
+ pfa->use = now++;
+ return pfa;
+}
+
+fa *mkdfa(const char *s, int anchor) /* does the real work of making a dfa */
+ /* anchor = 1 for anchored matches, else 0 */
+{
+ Node *p, *p1;
+ fa *f;
+
+ firstbasestr = (char *)s;
+ basestr = firstbasestr;
+ if (replogfile==0) {
+ /* disabled
+ replogfile = fopen("/tmp/repeatlog", "a");
+ */
+ }
+ p = reparse(s);
+ p1 = op2(CAT, op2(STAR, op2(ALL, NIL, NIL), NIL), p);
+ /* put ALL STAR in front of reg. exp. */
+ p1 = op2(CAT, p1, op2(FINAL, NIL, NIL));
+ /* put FINAL after reg. exp. */
+
+ poscnt = 0;
+ penter(p1); /* enter parent pointers and leaf indices */
+ if ((f = (fa *) calloc(1, sizeof(fa) + poscnt*sizeof(rrow))) == NULL)
+ overflo("out of space for fa");
+ f->accept = poscnt-1; /* penter has computed number of positions in re */
+ cfoll(f, p1); /* set up follow sets */
+ freetr(p1);
+ if ((f->posns[0] = (int *) calloc(1, *(f->re[0].lfollow)*sizeof(int))) == NULL)
+ overflo("out of space in makedfa");
+ if ((f->posns[1] = (int *) calloc(1, sizeof(int))) == NULL)
+ overflo("out of space in makedfa");
+ *f->posns[1] = 0;
+ f->initstat = makeinit(f, anchor);
+ f->anchor = anchor;
+ f->restr = (uschar *) tostring(s);
+ if (replogfile) {
+ fflush(replogfile);
+ fclose(replogfile);
+ replogfile=0;
+ }
+ if (firstbasestr != basestr) {
+ if (basestr) free(basestr);
+ }
+ return f;
+}
+
+int makeinit(fa *f, int anchor)
+{
+ int i, k;
+
+ f->curstat = 2;
+ f->out[2] = 0;
+ f->reset = 0;
+ k = *(f->re[0].lfollow);
+ xfree(f->posns[2]);
+ if ((f->posns[2] = (int *) calloc(1, (k+1)*sizeof(int))) == NULL)
+ overflo("out of space in makeinit");
+ for (i=0; i <= k; i++) {
+ (f->posns[2])[i] = (f->re[0].lfollow)[i];
+ }
+ if ((f->posns[2])[1] == f->accept)
+ f->out[2] = 1;
+ for (i=0; i < NCHARS; i++)
+ f->gototab[2][i] = 0;
+ f->curstat = cgoto(f, 2, HAT);
+ if (anchor) {
+ *f->posns[2] = k-1; /* leave out position 0 */
+ for (i=0; i < k; i++) {
+ (f->posns[0])[i] = (f->posns[2])[i];
+ }
+
+ f->out[0] = f->out[2];
+ if (f->curstat != 2)
+ --(*f->posns[f->curstat]);
+ }
+ return f->curstat;
+}
+
+void penter(Node *p) /* set up parent pointers and leaf indices */
+{
+ switch (type(p)) {
+ ELEAF
+ LEAF
+ info(p) = poscnt;
+ poscnt++;
+ break;
+ UNARY
+ penter(left(p));
+ parent(left(p)) = p;
+ break;
+ case CAT:
+ case OR:
+ penter(left(p));
+ penter(right(p));
+ parent(left(p)) = p;
+ parent(right(p)) = p;
+ break;
+ default: /* can't happen */
+ FATAL("can't happen: unknown type %d in penter", type(p));
+ break;
+ }
+}
+
+void freetr(Node *p) /* free parse tree */
+{
+ switch (type(p)) {
+ ELEAF
+ LEAF
+ // fprintf(stderr, "Freeing leaf %x\n", p); fflush(stderr);
+ xfree(p);
+ break;
+ UNARY
+ freetr(left(p));
+ // fprintf(stderr, "Freeing unary %x\n", p); fflush(stderr);
+ xfree(p);
+ break;
+ case CAT:
+ case OR:
+ freetr(left(p));
+ freetr(right(p));
+ // fprintf(stderr, "Freeing tree %x\n", p); fflush(stderr);
+ xfree(p);
+ break;
+ default: /* can't happen */
+ FATAL("can't happen: unknown type %d in freetr", type(p));
+ break;
+ }
+}
+
+/* in the parsing of regular expressions, metacharacters like . have */
+/* to be seen literally; \056 is not a metacharacter. */
+
+int hexstr(char **pp) /* find and eval hex string at pp, return new p */
+{ /* only pick up one 8-bit byte (2 chars) */
+ uschar *p;
+ int n = 0;
+ int i;
+
+ for (i = 0, p = (uschar *) *pp; i < 2 && isxdigit(*p); i++, p++) {
+ if (isdigit(*p))
+ n = 16 * n + *p - '0';
+ else if (*p >= 'a' && *p <= 'f')
+ n = 16 * n + *p - 'a' + 10;
+ else if (*p >= 'A' && *p <= 'F')
+ n = 16 * n + *p - 'A' + 10;
+ }
+ *pp = (char *) p;
+ return n;
+}
+
+#define isoctdigit(c) ((c) >= '0' && (c) <= '7') /* multiple use of arg */
+
+int quoted(char **pp) /* pick up next thing after a \\ */
+ /* and increment *pp */
+{
+ char *p = *pp;
+ int c;
+
+ if ((c = *p++) == 't')
+ c = '\t';
+ else if (c == 'n')
+ c = '\n';
+ else if (c == 'f')
+ c = '\f';
+ else if (c == 'r')
+ c = '\r';
+ else if (c == 'b')
+ c = '\b';
+ else if (c == '\\')
+ c = '\\';
+ else if (c == 'x') { /* hexadecimal goo follows */
+ c = hexstr(&p); /* this adds a null if number is invalid */
+ } else if (isoctdigit(c)) { /* \d \dd \ddd */
+ int n = c - '0';
+ if (isoctdigit(*p)) {
+ n = 8 * n + *p++ - '0';
+ if (isoctdigit(*p))
+ n = 8 * n + *p++ - '0';
+ }
+ c = n;
+ } /* else */
+ /* c = c; */
+ *pp = p;
+ return c;
+}
+
+char *cclenter(const char *argp) /* add a character class */
+{
+ int i, c, c2;
+ uschar *p = (uschar *) argp;
+ uschar *op, *bp;
+ static __thread uschar *buf = 0;
+ static __thread int bufsz = 100;
+
+ op = p;
+ if (buf == 0 && (buf = (uschar *) malloc(bufsz)) == NULL)
+ FATAL("out of space for character class [%.10s...] 1", p);
+ bp = buf;
+ for (i = 0; (c = *p++) != 0; ) {
+ if (c == '\\') {
+ c = quoted((char **) &p);
+ } else if (c == '-' && i > 0 && bp[-1] != 0) {
+ if (*p != 0) {
+ c = bp[-1];
+ c2 = *p++;
+ if (c2 == '\\')
+ c2 = quoted((char **) &p);
+ if (c > c2) { /* empty; ignore */
+ bp--;
+ i--;
+ continue;
+ }
+ while (c < c2) {
+ if (!adjbuf((char **) &buf, &bufsz, bp-buf+2, 100, (char **) &bp, "cclenter1"))
+ FATAL("out of space for character class [%.10s...] 2", p);
+ *bp++ = ++c;
+ i++;
+ }
+ continue;
+ }
+ }
+ if (!adjbuf((char **) &buf, &bufsz, bp-buf+2, 100, (char **) &bp, "cclenter2"))
+ FATAL("out of space for character class [%.10s...] 3", p);
+ *bp++ = c;
+ i++;
+ }
+ *bp = 0;
+ dprintf( (thread_stdout, "cclenter: in = |%s|, out = |%s|\n", op, buf) );
+ xfree(op);
+ return (char *) tostring((char *) buf);
+}
+
+void overflo(const char *s)
+{
+ FATAL("regular expression too big: %.30s...", s);
+}
+
+void cfoll(fa *f, Node *v) /* enter follow set of each leaf of vertex v into lfollow[leaf] */
+{
+ int i;
+ int *p;
+
+ switch (type(v)) {
+ ELEAF
+ LEAF
+ f->re[info(v)].ltype = type(v);
+ f->re[info(v)].lval.np = right(v);
+ while (f->accept >= maxsetvec) { /* guessing here! */
+ maxsetvec *= 4;
+ setvec = (int *) realloc(setvec, maxsetvec * sizeof(int));
+ tmpset = (int *) realloc(tmpset, maxsetvec * sizeof(int));
+ if (setvec == 0 || tmpset == 0)
+ overflo("out of space in cfoll()");
+ }
+ for (i = 0; i <= f->accept; i++)
+ setvec[i] = 0;
+ setcnt = 0;
+ follow(v); /* computes setvec and setcnt */
+ if ((p = (int *) calloc(1, (setcnt+1)*sizeof(int))) == NULL)
+ overflo("out of space building follow set");
+ f->re[info(v)].lfollow = p;
+ *p = setcnt;
+ for (i = f->accept; i >= 0; i--)
+ if (setvec[i] == 1)
+ *++p = i;
+ break;
+ UNARY
+ cfoll(f,left(v));
+ break;
+ case CAT:
+ case OR:
+ cfoll(f,left(v));
+ cfoll(f,right(v));
+ break;
+ default: /* can't happen */
+ FATAL("can't happen: unknown type %d in cfoll", type(v));
+ }
+}
+
+static int first(Node *p) /* collects initially active leaves of p into setvec */
+ /* returns 0 if p matches empty string */
+{
+ int b, lp;
+
+ switch (type(p)) {
+ ELEAF
+ LEAF
+ lp = info(p); /* look for high-water mark of subscripts */
+ while (setcnt >= maxsetvec || lp >= maxsetvec) { /* guessing here! */
+ maxsetvec *= 4;
+ setvec = (int *) realloc(setvec, maxsetvec * sizeof(int));
+ tmpset = (int *) realloc(tmpset, maxsetvec * sizeof(int));
+ if (setvec == 0 || tmpset == 0)
+ overflo("out of space in first()");
+ }
+ if (type(p) == EMPTYRE) {
+ setvec[lp] = 0;
+ return(0);
+ }
+ if (setvec[lp] != 1) {
+ setvec[lp] = 1;
+ setcnt++;
+ }
+ if (type(p) == CCL && (*(char *) right(p)) == '\0')
+ return(0); /* empty CCL */
+ else return(1);
+ case PLUS:
+ if (first(left(p)) == 0) return(0);
+ return(1);
+ case STAR:
+ case QUEST:
+ first(left(p));
+ return(0);
+ case CAT:
+ if (first(left(p)) == 0 && first(right(p)) == 0) return(0);
+ return(1);
+ case OR:
+ b = first(right(p));
+ if (first(left(p)) == 0 || b == 0) return(0);
+ return(1);
+ }
+ FATAL("can't happen: unknown type %d in first", type(p)); /* can't happen */
+ return(-1);
+}
+
+void follow(Node *v) /* collects leaves that can follow v into setvec */
+{
+ Node *p;
+
+ if (type(v) == FINAL)
+ return;
+ p = parent(v);
+ switch (type(p)) {
+ case STAR:
+ case PLUS:
+ first(v);
+ follow(p);
+ return;
+
+ case OR:
+ case QUEST:
+ follow(p);
+ return;
+
+ case CAT:
+ if (v == left(p)) { /* v is left child of p */
+ if (first(right(p)) == 0) {
+ follow(p);
+ return;
+ }
+ } else /* v is right child */
+ follow(p);
+ return;
+ }
+}
+
+int member(int c, const char *sarg) /* is c in s? */
+{
+ uschar *s = (uschar *) sarg;
+
+ while (*s)
+ if (c == *s++)
+ return(1);
+ return(0);
+}
+
+int smatch(fa *f, const char *p0) /* shortest match ? */
+{
+ int s, ns;
+ uschar *p = (uschar *) p0;
+
+ s = f->reset ? makeinit(f,0) : f->initstat;
+ if (f->out[s])
+ return(1);
+ do {
+ /* assert(*p < NCHARS); */
+ if ((ns = f->gototab[s][*p]) != 0)
+ s = ns;
+ else
+ s = cgoto(f, s, *p);
+ if (f->out[s])
+ return(1);
+ } while (*p++ != 0);
+ return(0);
+}
+
+int pmatch(fa *f, const char *p0) /* longest match, for sub */
+{
+ int s, ns;
+ uschar *p = (uschar *) p0;
+ uschar *q;
+ int i, k;
+
+ /* s = f->reset ? makeinit(f,1) : f->initstat; */
+ if (f->reset) {
+ f->initstat = s = makeinit(f,1);
+ } else {
+ s = f->initstat;
+ }
+ patbeg = (char *) p;
+ patlen = -1;
+ do {
+ q = p;
+ do {
+ if (f->out[s]) /* final state */
+ patlen = q-p;
+ /* assert(*q < NCHARS); */
+ if ((ns = f->gototab[s][*q]) != 0)
+ s = ns;
+ else
+ s = cgoto(f, s, *q);
+ if (s == 1) { /* no transition */
+ if (patlen >= 0) {
+ patbeg = (char *) p;
+ return(1);
+ }
+ else
+ goto nextin; /* no match */
+ }
+ } while (*q++ != 0);
+ if (f->out[s])
+ patlen = q-p-1; /* don't count $ */
+ if (patlen >= 0) {
+ patbeg = (char *) p;
+ return(1);
+ }
+ nextin:
+ s = 2;
+ if (f->reset) {
+ for (i = 2; i <= f->curstat; i++)
+ xfree(f->posns[i]);
+ k = *f->posns[0];
+ if ((f->posns[2] = (int *) calloc(1, (k+1)*sizeof(int))) == NULL)
+ overflo("out of space in pmatch");
+ for (i = 0; i <= k; i++)
+ (f->posns[2])[i] = (f->posns[0])[i];
+ f->initstat = f->curstat = 2;
+ f->out[2] = f->out[0];
+ for (i = 0; i < NCHARS; i++)
+ f->gototab[2][i] = 0;
+ }
+ } while (*p++ != 0);
+ return (0);
+}
+
+int nematch(fa *f, const char *p0) /* non-empty match, for sub */
+{
+ int s, ns;
+ uschar *p = (uschar *) p0;
+ uschar *q;
+ int i, k;
+
+ /* s = f->reset ? makeinit(f,1) : f->initstat; */
+ if (f->reset) {
+ f->initstat = s = makeinit(f,1);
+ } else {
+ s = f->initstat;
+ }
+ patlen = -1;
+ while (*p) {
+ q = p;
+ do {
+ if (f->out[s]) /* final state */
+ patlen = q-p;
+ /* assert(*q < NCHARS); */
+ if ((ns = f->gototab[s][*q]) != 0)
+ s = ns;
+ else
+ s = cgoto(f, s, *q);
+ if (s == 1) { /* no transition */
+ if (patlen > 0) {
+ patbeg = (char *) p;
+ return(1);
+ } else
+ goto nnextin; /* no nonempty match */
+ }
+ } while (*q++ != 0);
+ if (f->out[s])
+ patlen = q-p-1; /* don't count $ */
+ if (patlen > 0 ) {
+ patbeg = (char *) p;
+ return(1);
+ }
+ nnextin:
+ s = 2;
+ if (f->reset) {
+ for (i = 2; i <= f->curstat; i++)
+ xfree(f->posns[i]);
+ k = *f->posns[0];
+ if ((f->posns[2] = (int *) calloc(1, (k+1)*sizeof(int))) == NULL)
+ overflo("out of state space");
+ for (i = 0; i <= k; i++)
+ (f->posns[2])[i] = (f->posns[0])[i];
+ f->initstat = f->curstat = 2;
+ f->out[2] = f->out[0];
+ for (i = 0; i < NCHARS; i++)
+ f->gototab[2][i] = 0;
+ }
+ p++;
+ }
+ return (0);
+}
+
+Node *reparse(const char *p) /* parses regular expression pointed to by p */
+{ /* uses relex() to scan regular expression */
+ Node *np;
+
+ dprintf( (thread_stdout, "reparse <%s>\n", p) );
+ lastre = prestr = (uschar *) p; /* prestr points to string to be parsed */
+ rtok = relex();
+ /* GNU compatibility: an empty regexp matches anything */
+ if (rtok == '\0') {
+ /* FATAL("empty regular expression"); previous */
+ return(op2(EMPTYRE, NIL, NIL));
+ }
+ np = regexp();
+ if (rtok != '\0')
+ FATAL("syntax error in regular expression %s at %s", lastre, prestr);
+ return(np);
+}
+
+Node *regexp(void) /* top-level parse of reg expr */
+{
+ return (alt(concat(primary())));
+}
+
+Node *primary(void)
+{
+ Node *np;
+ int savelastatom;
+
+ switch (rtok) {
+ case CHAR:
+ lastatom = starttok;
+ np = op2(CHAR, NIL, itonp(rlxval));
+ rtok = relex();
+ return (unary(np));
+ case ALL:
+ rtok = relex();
+ return (unary(op2(ALL, NIL, NIL)));
+ case EMPTYRE:
+ if (replogfile) {
+ fprintf(replogfile,
+ "returned EMPTYRE from primary\n");
+ fflush(replogfile);
+ }
+ rtok = relex();
+
+ return (unary(op2(EMPTYRE, NIL, NIL)));
+ case DOT:
+ lastatom = starttok;
+ rtok = relex();
+ return (unary(op2(DOT, NIL, NIL)));
+ case CCL:
+ lastatom = starttok;
+ np = op2(CCL, NIL, (Node*) cclenter((char *) rlxstr));
+ rtok = relex();
+ return (unary(np));
+ case NCCL:
+ lastatom = starttok;
+ np = op2(NCCL, NIL, (Node *) cclenter((char *) rlxstr));
+ rtok = relex();
+ return (unary(np));
+ case '^':
+ rtok = relex();
+ return (unary(op2(CHAR, NIL, itonp(HAT))));
+ case '$':
+ rtok = relex();
+ return (unary(op2(CHAR, NIL, NIL)));
+ case '(':
+ lastatom = starttok;
+ savelastatom = (char *)starttok-basestr; /* Retain over recursion */
+ rtok = relex();
+ if (rtok == ')') { /* special pleading for () */
+ rtok = relex();
+ return unary(op2(CCL, NIL, (Node *) tostring("")));
+ }
+ np = regexp();
+ if (rtok == ')') {
+ lastatom = basestr+savelastatom; /* Restore */
+ rtok = relex();
+ return (unary(np));
+ }
+ else
+ FATAL("syntax error in regular expression %s at %s", lastre, prestr);
+ default:
+ FATAL("illegal primary in regular expression %s at %s", lastre, prestr);
+ }
+ return 0; /*NOTREACHED*/
+}
+
+Node *concat(Node *np)
+{
+ switch (rtok) {
+ case CHAR: case DOT: case ALL: case CCL: case NCCL: case '$': case '(':
+ return (concat(op2(CAT, np, primary())));
+ case EMPTYRE:
+ if (replogfile) {
+ fprintf(replogfile,
+ "returned EMPTYRE to concat\n");
+ fflush(replogfile);
+ }
+ rtok = relex();
+ return (concat(op2(CAT, op2(CCL, NIL, (Node *) tostring("")),
+ primary())));
+ }
+ return (np);
+}
+
+Node *alt(Node *np)
+{
+ if (rtok == OR) {
+ rtok = relex();
+ return (alt(op2(OR, np, concat(primary()))));
+ }
+ return (np);
+}
+
+Node *unary(Node *np)
+{
+ switch (rtok) {
+ case STAR:
+ rtok = relex();
+ return (unary(op2(STAR, np, NIL)));
+ case PLUS:
+ rtok = relex();
+ return (unary(op2(PLUS, np, NIL)));
+ case QUEST:
+ rtok = relex();
+ return (unary(op2(QUEST, np, NIL)));
+ default:
+ return (np);
+ }
+}
+
+/*
+ * Character class definitions conformant to the POSIX locale as
+ * defined in IEEE P1003.1 draft 7 of June 2001, assuming the source
+ * and operating character sets are both ASCII (ISO646) or supersets
+ * thereof.
+ *
+ * Note that to avoid overflowing the temporary buffer used in
+ * relex(), the expanded character class (prior to range expansion)
+ * must be less than twice the size of their full name.
+ */
+
+/* Because isblank doesn't show up in any of the header files on any
+ * system i use, it's defined here. if some other locale has a richer
+ * definition of "blank", define HAS_ISBLANK and provide your own
+ * version.
+ * the parentheses here are an attempt to find a path through the maze
+ * of macro definition and/or function and/or version provided. thanks
+ * to nelson beebe for the suggestion; let's see if it works everywhere.
+ */
+
+#if defined(__APPLE__)
+#define HAS_ISBLANK
+#endif
+#ifndef HAS_ISBLANK
+
+int (isblank)(int c)
+{
+ return c==' ' || c=='\t';
+}
+
+#endif
+
+struct charclass {
+ const char *cc_name;
+ int cc_namelen;
+ int (*cc_func)(int);
+} charclasses[] = {
+ { "alnum", 5, isalnum },
+ { "alpha", 5, isalpha },
+ { "blank", 5, isblank },
+ { "cntrl", 5, iscntrl },
+ { "digit", 5, isdigit },
+ { "graph", 5, isgraph },
+ { "lower", 5, islower },
+ { "print", 5, isprint },
+ { "punct", 5, ispunct },
+ { "space", 5, isspace },
+ { "upper", 5, isupper },
+ { "xdigit", 6, isxdigit },
+ { NULL, 0, NULL },
+};
+
+#define REPEAT_SIMPLE 0
+#define REPEAT_PLUS_APPENDED 1
+#define REPEAT_WITH_Q 2
+#define REPEAT_ZERO 3
+
+int replace_repeat(uschar * reptok, int reptoklen, uschar * atom, int atomlen,
+ int firstnum, int secondnum, int special_case)
+{
+ int i, j;
+ uschar *buf = 0;
+ int ret = 1;
+ int init_q = (firstnum==0); /* first added char will be ? */
+ int n_q_reps = secondnum-firstnum; /* m>n, so reduce until {1,m-n} left */
+ int prefix_length = (char *) reptok-basestr; /* prefix includes first rep */
+ int suffix_length = strlen(reptok) - reptoklen; /* string after rep specifier */
+ int size = prefix_length + suffix_length;
+
+ if (firstnum > 1) { /* add room for reps 2 through firstnum */
+ size += atomlen*(firstnum-1);
+ }
+
+ /* Adjust size of buffer for special cases */
+ if (special_case == REPEAT_PLUS_APPENDED) {
+ size++; /* for the final + */
+ } else if (special_case == REPEAT_WITH_Q) {
+ size += init_q + (atomlen+1)* n_q_reps;
+ } else if (special_case == REPEAT_ZERO) {
+ size += 2; /* just a null ERE: () */
+ }
+ if ((buf = (uschar *) malloc(size+1)) == NULL)
+ FATAL("out of space in reg expr %.10s..", lastre);
+ if (replogfile) {
+ fprintf(replogfile, "re before: len=%d,%s\n"
+ " : init_q=%d,n_q_reps=%d\n",
+ strlen(basestr),basestr,
+ init_q,n_q_reps);
+ fprintf(replogfile, "re prefix_length=%d,atomlen=%d\n",
+ prefix_length,atomlen);
+/*
+ fprintf(replogfile, " new buf size: %d, atom=%s, atomlen=%d\n",
+ size, atom, atomlen);
+*/
+ fflush(replogfile);
+ }
+ memcpy(buf, basestr, prefix_length); /* copy prefix */
+ j = prefix_length;
+ if (special_case == REPEAT_ZERO) {
+ j -= atomlen;
+ buf[j++] = '(';
+ buf[j++] = ')';
+ }
+ for (i=1; i < firstnum; i++) { /* copy x reps */
+ memcpy(&buf[j], atom, atomlen);
+ j += atomlen;
+ }
+ if (special_case == REPEAT_PLUS_APPENDED) {
+ buf[j++] = '+';
+ } else if (special_case == REPEAT_WITH_Q) {
+ if (init_q) buf[j++] = '?';
+ for (i=0; i < n_q_reps; i++) { /* copy x? reps */
+ memcpy(&buf[j], atom, atomlen);
+ j += atomlen;
+ buf[j++] = '?';
+ }
+ }
+ memcpy(&buf[j], reptok+reptoklen, suffix_length);
+ if (special_case == REPEAT_ZERO) {
+ buf[j+suffix_length] = '\0';
+ } else {
+ buf[size] = '\0';
+ }
+ if (replogfile) {
+ fprintf(replogfile, "re after : len=%d,%s\n",strlen(buf),buf);
+ fflush(replogfile);
+ }
+ /* free old basestr */
+ if (firstbasestr != basestr) {
+ if (basestr) free(basestr);
+ }
+ basestr = (char *)buf;
+ prestr = buf + prefix_length;
+ if (special_case == REPEAT_ZERO) {
+ prestr -= atomlen;
+ ret++;
+ }
+ return ret;
+}
+
+int repeat(uschar * reptok, int reptoklen, uschar * atom, int atomlen,
+ int firstnum, int secondnum)
+{
+ /*
+ In general, the repetition specifier or "bound" is replaced here
+ by an equivalent ERE string, repeating the immediately previous atom
+ and appending ? and + as needed. Note that the first copy of the
+ atom is left in place, except in the special_case of a zero-repeat
+ (i.e., {0}).
+ */
+ int i, j;
+ if (secondnum < 0) { /* means {n,} -> repeat n-1 times followed by PLUS */
+ if (firstnum < 2) {
+ /* 0 or 1: should be handled before you get here */
+ if (replogfile) {
+ fprintf(replogfile,
+ "{%d, %d}, shouldn't be here\n",
+ firstnum, secondnum);
+ fflush(replogfile);
+ }
+ } else {
+ return replace_repeat(reptok, reptoklen, atom, atomlen,
+ firstnum, secondnum, REPEAT_PLUS_APPENDED);
+ }
+ } else if (firstnum == secondnum) { /* {n} or {n,n} -> simply repeat n-1 times */
+ if (firstnum == 0) { /* {0} or {0,0} */
+ /* This case is unusual because the resulting
+ replacement string might actually be SMALLER than
+ the original ERE */
+ return replace_repeat(reptok, reptoklen, atom, atomlen,
+ firstnum, secondnum, REPEAT_ZERO);
+ } else { /* (firstnum >= 1) */
+ return replace_repeat(reptok, reptoklen, atom, atomlen,
+ firstnum, secondnum, REPEAT_SIMPLE);
+ }
+ } else if (firstnum < secondnum) { /* {n,m} -> repeat n-1 times then alternate */
+ /* x{n,m} => xx...x{1, m-n+1} => xx...x?x?x?..x? */
+ return replace_repeat(reptok, reptoklen, atom, atomlen,
+ firstnum, secondnum, REPEAT_WITH_Q);
+ } else { /* Error - shouldn't be here (n>m) */
+ if (replogfile) {
+ fprintf(replogfile,
+ "illegal ERE {%d,%d} shouldn't be here!\n",
+ firstnum,secondnum);
+ fflush(replogfile);
+ }
+ }
+ return 0;
+}
+
+int relex(void) /* lexical analyzer for reparse */
+{
+ int c, n;
+ int cflag;
+ static __thread uschar *buf = 0;
+ static __thread int bufsz = 100;
+ uschar *bp;
+ struct charclass *cc;
+ int i;
+ int num, m, commafound, digitfound;
+ uschar *startreptok;
+
+rescan:
+ starttok = prestr;
+
+ switch (c = *prestr++) {
+ case '|': return OR;
+ case '*': return STAR;
+ case '+': return PLUS;
+ case '?': return QUEST;
+ case '.': return DOT;
+ case '\0': prestr--; return '\0';
+ case '^':
+ case '$':
+ case '(':
+ case ')':
+ return c;
+ case '\\':
+ rlxval = quoted((char **) &prestr);
+ return CHAR;
+ default:
+ rlxval = c;
+ return CHAR;
+ case '[':
+ if (buf == 0 && (buf = (uschar *) malloc(bufsz)) == NULL)
+ FATAL("out of space in reg expr %.10s..", lastre);
+ bp = buf;
+ if (*prestr == '^') {
+ cflag = 1;
+ prestr++;
+ }
+ else
+ cflag = 0;
+ n = 2 * strlen((const char *) prestr)+1;
+ if (!adjbuf((char **) &buf, &bufsz, n, n, (char **) &bp, "relex1"))
+ FATAL("out of space for reg expr %.10s...", lastre);
+ for (; ; ) {
+ if ((c = *prestr++) == '\\') {
+ *bp++ = '\\';
+ if ((c = *prestr++) == '\0')
+ FATAL("nonterminated character class %.20s...", lastre);
+ *bp++ = c;
+ /* } else if (c == '\n') { */
+ /* FATAL("newline in character class %.20s...", lastre); */
+ } else if (c == '[' && *prestr == ':') {
+ /* POSIX char class names, Dag-Erling Smorgrav, des@ofug.org */
+ for (cc = charclasses; cc->cc_name; cc++)
+ if (strncmp((const char *) prestr + 1, (const char *) cc->cc_name, cc->cc_namelen) == 0)
+ break;
+ if (cc->cc_name != NULL && prestr[1 + cc->cc_namelen] == ':' &&
+ prestr[2 + cc->cc_namelen] == ']') {
+ prestr += cc->cc_namelen + 3;
+ for (i = 0; i < NCHARS; i++) {
+ if (!adjbuf((char **) &buf, &bufsz, bp-buf+1, 100, (char **) &bp, "relex2"))
+ FATAL("out of space for reg expr %.10s...", lastre);
+ if (cc->cc_func(i)) {
+ *bp++ = i;
+ n++;
+ }
+ }
+ } else
+ *bp++ = c;
+ } else if (Unix2003_compat && c == '['
+ && *prestr == '.') {
+ char collate_char;
+ prestr++;
+ collate_char = *prestr++;
+ if (*prestr == '.' && prestr[1] == ']') {
+ prestr += 2;
+ /* Found it: map via locale TBD: for
+ now, simply return this char. This
+ is sufficient to pass conformance
+ test awk.ex 156
+ */
+ if (*prestr == ']') {
+ prestr++;
+ rlxval = collate_char;
+ if (replogfile) {
+ fprintf(replogfile,
+ "[..] collate char=%c\n",
+ collate_char);
+ fflush(replogfile);
+ }
+ return CHAR;
+ }
+ }
+ } else if (Unix2003_compat && c == '['
+ && *prestr == '=') {
+ char equiv_char;
+ prestr++;
+ equiv_char = *prestr++;
+ if (*prestr == '=' && prestr[1] == ']') {
+ prestr += 2;
+ /* Found it: map via locale TBD: for now
+ simply return this char. This is
+ sufficient to pass conformance test
+ awk.ex 156
+ */
+ if (*prestr == ']') {
+ prestr++;
+ rlxval = equiv_char;
+ if (replogfile) {
+ fprintf(replogfile,
+ "[==] equiv char=%c\n",
+ equiv_char);
+ fflush(replogfile);
+ }
+ return CHAR;
+ }
+ }
+ } else if (c == '\0') {
+ FATAL("nonterminated character class %.20s", lastre);
+ } else if (bp == buf) { /* 1st char is special */
+ *bp++ = c;
+ } else if (c == ']') {
+ *bp++ = 0;
+ rlxstr = (uschar *) tostring((char *) buf);
+ if (replogfile) {
+ fprintf(replogfile,
+ "detecting []: cflag=%d, len=%d,%s\n",
+ cflag,strlen(rlxstr),rlxstr);
+ fflush(replogfile);
+ }
+ if (cflag == 0)
+ return CCL;
+ else
+ return NCCL;
+ } else
+ *bp++ = c;
+ }
+ break;
+ case '{':
+ if (Unix2003_compat && isdigit(*(prestr))) {
+ num = 0; /* Process as a repetition */
+ n = -1; m = -1;
+ commafound = 0;
+ digitfound = 0;
+ startreptok = prestr-1;
+ /* Remember start of previous atom here ? */
+ } else { /* just a { char, not a repetition */
+ rlxval = c;
+ return CHAR;
+ }
+ for (; ; ) {
+ if ((c = *prestr++) == '}') {
+ if (commafound) {
+ if (digitfound) { /* {n,m} */
+ m = num;
+ if (m 0) {
+ if ((n==0) && (m==0)) {
+ return EMPTYRE;
+ }
+ /* must rescan input for next token */
+ goto rescan;
+ }
+ /* Failed to replace: eat up {...} characters
+ and treat like just PLUS */
+ return PLUS;
+ } else if (c == '\0') {
+ FATAL("nonterminated character class %.20s",
+ lastre);
+ } else if (isdigit(c)) {
+ num = 10 * num + c - '0';
+ digitfound = 1;
+ } else if (c == ',') {
+ if (commafound)
+ FATAL("illegal repetition expression: class %.20s",
+ lastre);
+ /* looking for {n,} or {n,m} */
+ commafound = 1;
+ n = num;
+ digitfound = 0; /* reset */
+ num = 0;
+ } else {
+ FATAL("illegal repetition expression: class %.20s",
+ lastre);
+ }
+ }
+ break;
+ }
+}
+
+int cgoto(fa *f, int s, int c)
+{
+ int i, j, k;
+ int *p, *q;
+
+ assert(c == HAT || c < NCHARS);
+ while (f->accept >= maxsetvec) { /* guessing here! */
+ maxsetvec *= 4;
+ setvec = (int *) realloc(setvec, maxsetvec * sizeof(int));
+ tmpset = (int *) realloc(tmpset, maxsetvec * sizeof(int));
+ if (setvec == 0 || tmpset == 0)
+ overflo("out of space in cgoto()");
+ }
+ for (i = 0; i <= f->accept; i++)
+ setvec[i] = 0;
+ setcnt = 0;
+ /* compute positions of gototab[s,c] into setvec */
+ p = f->posns[s];
+ for (i = 1; i <= *p; i++) {
+ if ((k = f->re[p[i]].ltype) != FINAL) {
+ if ((k == CHAR && c == ptoi(f->re[p[i]].lval.np))
+ || (k == DOT && c != 0 && c != HAT)
+ || (k == ALL && c != 0)
+ || (k == EMPTYRE && c != 0)
+ || (k == CCL && member(c, (char *) f->re[p[i]].lval.up))
+ || (k == NCCL && !member(c, (char *) f->re[p[i]].lval.up) && c != 0 && c != HAT)) {
+ q = f->re[p[i]].lfollow;
+ for (j = 1; j <= *q; j++) {
+ if (q[j] >= maxsetvec) {
+ maxsetvec *= 4;
+ setvec = (int *) realloc(setvec, maxsetvec * sizeof(int));
+ tmpset = (int *) realloc(setvec, maxsetvec * sizeof(int));
+ if (setvec == 0 || tmpset == 0)
+ overflo("cgoto overflow");
+ }
+ if (setvec[q[j]] == 0) {
+ setcnt++;
+ setvec[q[j]] = 1;
+ }
+ }
+ }
+ }
+ }
+ /* determine if setvec is a previous state */
+ tmpset[0] = setcnt;
+ j = 1;
+ for (i = f->accept; i >= 0; i--)
+ if (setvec[i]) {
+ tmpset[j++] = i;
+ }
+ /* tmpset == previous state? */
+ for (i = 1; i <= f->curstat; i++) {
+ p = f->posns[i];
+ if ((k = tmpset[0]) != p[0])
+ goto different;
+ for (j = 1; j <= k; j++)
+ if (tmpset[j] != p[j])
+ goto different;
+ /* setvec is state i */
+ f->gototab[s][c] = i;
+ return i;
+ different:;
+ }
+
+ /* add tmpset to current set of states */
+ if (f->curstat >= NSTATES-1) {
+ f->curstat = 2;
+ f->reset = 1;
+ for (i = 2; i < NSTATES; i++)
+ xfree(f->posns[i]);
+ } else
+ ++(f->curstat);
+ for (i = 0; i < NCHARS; i++)
+ f->gototab[f->curstat][i] = 0;
+ xfree(f->posns[f->curstat]);
+ if ((p = (int *) calloc(1, (setcnt+1)*sizeof(int))) == NULL)
+ overflo("out of space in cgoto");
+
+ f->posns[f->curstat] = p;
+ f->gototab[s][c] = f->curstat;
+ for (i = 0; i <= setcnt; i++)
+ p[i] = tmpset[i];
+ if (setvec[f->accept])
+ f->out[f->curstat] = 1;
+ else
+ f->out[f->curstat] = 0;
+ return f->curstat;
+}
+
+
+void freefa(fa *f) /* free a finite automaton */
+{
+ int i;
+
+ if (f == NULL)
+ return;
+ for (i = 0; i <= f->curstat; i++)
+ xfree(f->posns[i]);
+ for (i = 0; i <= f->accept; i++) {
+ xfree(f->re[i].lfollow);
+ if (f->re[i].ltype == CCL || f->re[i].ltype == NCCL)
+ xfree((f->re[i].lval.np));
+ }
+ xfree(f->restr);
+ xfree(f);
+}
diff --git a/awk/Sources/awk/lex.c b/awk/Sources/awk/lex.c
new file mode 100644
index 00000000..9fe0e650
--- /dev/null
+++ b/awk/Sources/awk/lex.c
@@ -0,0 +1,586 @@
+/****************************************************************
+Copyright (C) Lucent Technologies 1997
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name Lucent Technologies or any of
+its entities not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+****************************************************************/
+
+#include
+#include
+#include
+#include
+#include "awk.h"
+#include "ytab.h"
+#include "ios_error.h"
+
+
+extern __thread YYSTYPE yylval;
+extern __thread int infunc;
+
+__thread int lineno = 1;
+__thread int bracecnt = 0;
+__thread int brackcnt = 0;
+__thread int parencnt = 0;
+
+typedef struct Keyword {
+ const char *word;
+ int sub;
+ int type;
+} Keyword;
+
+Keyword keywords[] ={ /* keep sorted: binary searched */
+ { "BEGIN", XBEGIN, XBEGIN },
+ { "END", XEND, XEND },
+ { "NF", VARNF, VARNF },
+ { "atan2", FATAN, BLTIN },
+ { "break", BREAK, BREAK },
+ { "close", CLOSE, CLOSE },
+ { "continue", CONTINUE, CONTINUE },
+ { "cos", FCOS, BLTIN },
+ { "delete", DELETE, DELETE },
+ { "do", DO, DO },
+ { "else", ELSE, ELSE },
+ { "exit", EXIT, EXIT },
+ { "exp", FEXP, BLTIN },
+ { "fflush", FFLUSH, BLTIN },
+ { "for", FOR, FOR },
+ { "func", FUNC, FUNC },
+ { "function", FUNC, FUNC },
+ { "getline", GETLINE, GETLINE },
+ { "gsub", GSUB, GSUB },
+ { "if", IF, IF },
+ { "in", IN, IN },
+ { "index", INDEX, INDEX },
+ { "int", FINT, BLTIN },
+ { "length", FLENGTH, BLTIN },
+ { "log", FLOG, BLTIN },
+ { "match", MATCHFCN, MATCHFCN },
+ { "next", NEXT, NEXT },
+ { "nextfile", NEXTFILE, NEXTFILE },
+ { "print", PRINT, PRINT },
+ { "printf", PRINTF, PRINTF },
+ { "rand", FRAND, BLTIN },
+ { "return", RETURN, RETURN },
+ { "sin", FSIN, BLTIN },
+ { "split", SPLIT, SPLIT },
+ { "sprintf", SPRINTF, SPRINTF },
+ { "sqrt", FSQRT, BLTIN },
+ { "srand", FSRAND, BLTIN },
+ { "sub", SUB, SUB },
+ { "substr", SUBSTR, SUBSTR },
+ { "system", FSYSTEM, BLTIN },
+ { "tolower", FTOLOWER, BLTIN },
+ { "toupper", FTOUPPER, BLTIN },
+ { "while", WHILE, WHILE },
+};
+
+#define RET(x) { if(dbg)fprintf(thread_stdout, "lex %s\n", tokname(x)); return(x); }
+
+int peek(void)
+{
+ int c = input();
+ unput(c);
+ return c;
+}
+
+int gettok(char **pbuf, int *psz) /* get next input token */
+{
+ int c, retc;
+ char *buf = *pbuf;
+ int sz = *psz;
+ char *bp = buf;
+
+ c = input();
+ if (c == 0)
+ return 0;
+ buf[0] = c;
+ buf[1] = 0;
+ if (!isalnum(c) && c != '.' && c != '_')
+ return c;
+
+ *bp++ = c;
+ if (isalpha(c) || c == '_') { /* it's a varname */
+ for ( ; (c = input()) != 0; ) {
+ if (bp-buf >= sz)
+ if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, "gettok"))
+ FATAL( "out of space for name %.10s...", buf );
+ if (isalnum(c) || c == '_')
+ *bp++ = c;
+ else {
+ *bp = 0;
+ unput(c);
+ break;
+ }
+ }
+ *bp = 0;
+ retc = 'a'; /* alphanumeric */
+ } else { /* maybe it's a number, but could be . */
+ char *rem;
+ /* read input until can't be a number */
+ for ( ; (c = input()) != 0; ) {
+ if (bp-buf >= sz)
+ if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, "gettok"))
+ FATAL( "out of space for number %.10s...", buf );
+ if (isdigit(c) || c == 'e' || c == 'E'
+ || c == '.' || c == '+' || c == '-')
+ *bp++ = c;
+ else {
+ unput(c);
+ break;
+ }
+ }
+ *bp = 0;
+ strtod(buf, &rem); /* parse the number */
+ if (rem == buf) { /* it wasn't a valid number at all */
+ buf[1] = 0; /* return one character as token */
+ retc = buf[0]; /* character is its own type */
+ unputstr(rem+1); /* put rest back for later */
+ } else { /* some prefix was a number */
+ unputstr(rem); /* put rest back for later */
+ rem[0] = 0; /* truncate buf after number part */
+ retc = '0'; /* type is number */
+ }
+ }
+ *pbuf = buf;
+ *psz = sz;
+ return retc;
+}
+
+int word(char *);
+int string(void);
+int regexpr(void);
+int sc = 0; /* 1 => return a } right now */
+int reg = 0; /* 1 => return a REGEXPR now */
+
+int yylex(void)
+{
+ int c;
+ static __thread char *buf = 0;
+ static __thread int bufsize = 5; /* BUG: setting this small causes core dump! */
+
+ if (buf == 0 && (buf = (char *) malloc(bufsize)) == NULL)
+ FATAL( "out of space in yylex" );
+ if (sc) {
+ sc = 0;
+ RET('}');
+ }
+ if (reg) {
+ reg = 0;
+ return regexpr();
+ }
+ for (;;) {
+ c = gettok(&buf, &bufsize);
+ if (c == 0)
+ return 0;
+ if (isalpha(c) || c == '_')
+ return word(buf);
+ if (isdigit(c)) {
+ yylval.cp = setsymtab(buf, tostring(buf), atof(buf), CON|NUM, symtab);
+ /* should this also have STR set? */
+ RET(NUMBER);
+ }
+
+ yylval.i = c;
+ switch (c) {
+ case '\n': /* {EOL} */
+ RET(NL);
+ case '\r': /* assume \n is coming */
+ case ' ': /* {WS}+ */
+ case '\t':
+ break;
+ case '#': /* #.* strip comments */
+ while ((c = input()) != '\n' && c != 0)
+ ;
+ unput(c);
+ break;
+ case ';':
+ RET(';');
+ case '\\':
+ if (peek() == '\n') {
+ input();
+ } else if (peek() == '\r') {
+ input(); input(); /* \n */
+ lineno++;
+ } else {
+ RET(c);
+ }
+ break;
+ case '&':
+ if (peek() == '&') {
+ input(); RET(AND);
+ } else
+ RET('&');
+ case '|':
+ if (peek() == '|') {
+ input(); RET(BOR);
+ } else
+ RET('|');
+ case '!':
+ if (peek() == '=') {
+ input(); yylval.i = NE; RET(NE);
+ } else if (peek() == '~') {
+ input(); yylval.i = NOTMATCH; RET(MATCHOP);
+ } else
+ RET(NOT);
+ case '~':
+ yylval.i = MATCH;
+ RET(MATCHOP);
+ case '<':
+ if (peek() == '=') {
+ input(); yylval.i = LE; RET(LE);
+ } else {
+ yylval.i = LT; RET(LT);
+ }
+ case '=':
+ if (peek() == '=') {
+ input(); yylval.i = EQ; RET(EQ);
+ } else {
+ yylval.i = ASSIGN; RET(ASGNOP);
+ }
+ case '>':
+ if (peek() == '=') {
+ input(); yylval.i = GE; RET(GE);
+ } else if (peek() == '>') {
+ input(); yylval.i = APPEND; RET(APPEND);
+ } else {
+ yylval.i = GT; RET(GT);
+ }
+ case '+':
+ if (peek() == '+') {
+ input(); yylval.i = INCR; RET(INCR);
+ } else if (peek() == '=') {
+ input(); yylval.i = ADDEQ; RET(ASGNOP);
+ } else
+ RET('+');
+ case '-':
+ if (peek() == '-') {
+ input(); yylval.i = DECR; RET(DECR);
+ } else if (peek() == '=') {
+ input(); yylval.i = SUBEQ; RET(ASGNOP);
+ } else
+ RET('-');
+ case '*':
+ if (peek() == '=') { /* *= */
+ input(); yylval.i = MULTEQ; RET(ASGNOP);
+ } else if (peek() == '*') { /* ** or **= */
+ input(); /* eat 2nd * */
+ if (peek() == '=') {
+ input(); yylval.i = POWEQ; RET(ASGNOP);
+ } else {
+ RET(POWER);
+ }
+ } else
+ RET('*');
+ case '/':
+ RET('/');
+ case '%':
+ if (peek() == '=') {
+ input(); yylval.i = MODEQ; RET(ASGNOP);
+ } else
+ RET('%');
+ case '^':
+ if (peek() == '=') {
+ input(); yylval.i = POWEQ; RET(ASGNOP);
+ } else
+ RET(POWER);
+
+ case '$':
+ /* BUG: awkward, if not wrong */
+ c = gettok(&buf, &bufsize);
+ if (isalpha(c)) {
+ if (strcmp(buf, "NF") == 0) { /* very special */
+ unputstr("(NF)");
+ RET(INDIRECT);
+ }
+ c = peek();
+ if (c == '(' || c == '[' || (infunc && isarg(buf) >= 0)) {
+ unputstr(buf);
+ RET(INDIRECT);
+ }
+ yylval.cp = setsymtab(buf, "", 0.0, STR|NUM, symtab);
+ RET(IVAR);
+ } else if (c == 0) { /* */
+ SYNTAX( "unexpected end of input after $" );
+ RET(';');
+ } else {
+ unputstr(buf);
+ RET(INDIRECT);
+ }
+
+ case '}':
+ if (--bracecnt < 0)
+ SYNTAX( "extra }" );
+ sc = 1;
+ RET(';');
+ case ']':
+ if (--brackcnt < 0)
+ SYNTAX( "extra ]" );
+ RET(']');
+ case ')':
+ if (--parencnt < 0)
+ SYNTAX( "extra )" );
+ RET(')');
+ case '{':
+ bracecnt++;
+ RET('{');
+ case '[':
+ brackcnt++;
+ RET('[');
+ case '(':
+ parencnt++;
+ RET('(');
+
+ case '"':
+ return string(); /* BUG: should be like tran.c ? */
+
+ default:
+ RET(c);
+ }
+ }
+}
+
+int string(void)
+{
+ int c, n;
+ char *s, *bp;
+ static __thread char *buf = 0;
+ static __thread int bufsz = 500;
+
+ if (buf == 0 && (buf = (char *) malloc(bufsz)) == NULL)
+ FATAL("out of space for strings");
+ for (bp = buf; (c = input()) != '"'; ) {
+ if (!adjbuf(&buf, &bufsz, bp-buf+2, 500, &bp, "string"))
+ FATAL("out of space for string %.10s...", buf);
+ switch (c) {
+ case '\n':
+ case '\r':
+ case 0:
+ SYNTAX( "non-terminated string %.10s...", buf );
+ lineno++;
+ if (c == 0) /* hopeless */
+ FATAL( "giving up" );
+ break;
+ case '\\':
+ c = input();
+ switch (c) {
+ case '"': *bp++ = '"'; break;
+ case 'n': *bp++ = '\n'; break;
+ case 't': *bp++ = '\t'; break;
+ case 'f': *bp++ = '\f'; break;
+ case 'r': *bp++ = '\r'; break;
+ case 'b': *bp++ = '\b'; break;
+ case 'v': *bp++ = '\v'; break;
+ case 'a': *bp++ = '\007'; break;
+ case '\\': *bp++ = '\\'; break;
+
+ case '0': case '1': case '2': /* octal: \d \dd \ddd */
+ case '3': case '4': case '5': case '6': case '7':
+ n = c - '0';
+ if ((c = peek()) >= '0' && c < '8') {
+ n = 8 * n + input() - '0';
+ if ((c = peek()) >= '0' && c < '8')
+ n = 8 * n + input() - '0';
+ }
+ *bp++ = n;
+ break;
+
+ case 'x': /* hex \x0-9a-fA-F + */
+ { char xbuf[100], *px;
+ for (px = xbuf; (c = input()) != 0 && px-xbuf < 100-2; ) {
+ if (isdigit(c)
+ || (c >= 'a' && c <= 'f')
+ || (c >= 'A' && c <= 'F'))
+ *px++ = c;
+ else
+ break;
+ }
+ *px = 0;
+ unput(c);
+ sscanf(xbuf, "%x", &n);
+ *bp++ = n;
+ break;
+ }
+
+ default:
+ *bp++ = c;
+ break;
+ }
+ break;
+ default:
+ *bp++ = c;
+ break;
+ }
+ }
+ *bp = 0;
+ s = tostring(buf);
+ *bp++ = ' '; *bp++ = 0;
+ yylval.cp = setsymtab(buf, s, 0.0, CON|STR|DONTFREE, symtab);
+ RET(STRING);
+}
+
+
+int binsearch(char *w, Keyword *kp, int n)
+{
+ int cond, low, mid, high;
+
+ low = 0;
+ high = n - 1;
+ while (low <= high) {
+ mid = (low + high) / 2;
+ if ((cond = strcmp(w, kp[mid].word)) < 0)
+ high = mid - 1;
+ else if (cond > 0)
+ low = mid + 1;
+ else
+ return mid;
+ }
+ return -1;
+}
+
+int word(char *w)
+{
+ Keyword *kp = NULL;
+ int c, n;
+
+ n = binsearch(w, keywords, sizeof(keywords)/sizeof(keywords[0]));
+/* BUG: this ought to be inside the if; in theory could fault (daniel barrett) */
+ // kp = keywords + n;
+ // Indeed, it did fail with LLVM + Clang. I moved it inside the if. NH.
+ if (n != -1) { /* found in table */
+ kp = keywords + n;
+ yylval.i = kp->sub;
+ switch (kp->type) { /* special handling */
+ case BLTIN:
+ if (kp->sub == FSYSTEM && safe)
+ SYNTAX( "system is unsafe" );
+ RET(kp->type);
+ case FUNC:
+ if (infunc)
+ SYNTAX( "illegal nested function" );
+ RET(kp->type);
+ case RETURN:
+ if (!infunc)
+ SYNTAX( "return not in function" );
+ RET(kp->type);
+ case VARNF:
+ yylval.cp = setsymtab("NF", "", 0.0, NUM, symtab);
+ RET(VARNF);
+ default:
+ RET(kp->type);
+ }
+ }
+ c = peek(); /* look for '(' */
+ if (c != '(' && infunc && (n=isarg(w)) >= 0) {
+ yylval.i = n;
+ RET(ARG);
+ } else {
+ yylval.cp = setsymtab(w, "", 0.0, STR|NUM|DONTFREE, symtab);
+ if (c == '(') {
+ RET(CALL);
+ } else {
+ RET(VAR);
+ }
+ }
+}
+
+void startreg(void) /* next call to yylex will return a regular expression */
+{
+ reg = 1;
+}
+
+int regexpr(void)
+{
+ int c;
+ static __thread char *buf = 0;
+ static __thread int bufsz = 500;
+ char *bp;
+
+ if (buf == 0 && (buf = (char *) malloc(bufsz)) == NULL)
+ FATAL("out of space for rex expr");
+ bp = buf;
+ for ( ; (c = input()) != '/' && c != 0; ) {
+ if (!adjbuf(&buf, &bufsz, bp-buf+3, 500, &bp, "regexpr"))
+ FATAL("out of space for reg expr %.10s...", buf);
+ if (c == '\n') {
+ SYNTAX( "newline in regular expression %.10s...", buf );
+ unput('\n');
+ break;
+ } else if (c == '\\') {
+ *bp++ = '\\';
+ *bp++ = input();
+ } else {
+ *bp++ = c;
+ }
+ }
+ *bp = 0;
+ if (c == 0)
+ SYNTAX("non-terminated regular expression %.10s...", buf);
+ yylval.s = tostring(buf);
+ unput('/');
+ RET(REGEXPR);
+}
+
+/* low-level lexical stuff, sort of inherited from lex */
+
+char ebuf[300];
+char *ep = ebuf;
+static char yysbuf[100]; /* pushback buffer */
+static char *yysptr = yysbuf;
+__thread FILE *yyin = 0;
+
+int input(void) /* get next lexical input character */
+{
+ int c;
+ extern __thread char *lexprog;
+
+ if (yysptr > yysbuf)
+ c = (uschar)*--yysptr;
+ else if (lexprog != NULL) { /* awk '...' */
+ if ((c = (uschar)*lexprog) != 0)
+ lexprog++;
+ } else /* awk -f ... */
+ c = pgetc();
+ if (c == '\n')
+ lineno++;
+ else if (c == EOF)
+ c = 0;
+ if (ep >= ebuf + sizeof ebuf)
+ ep = ebuf;
+ return *ep++ = c;
+}
+
+void unput(int c) /* put lexical character back on input */
+{
+ if (c == '\n')
+ lineno--;
+ if (yysptr >= yysbuf + sizeof(yysbuf))
+ FATAL("pushed back too much: %.20s...", yysbuf);
+ *yysptr++ = c;
+ if (--ep < ebuf)
+ ep = ebuf + sizeof(ebuf) - 1;
+}
+
+void unputstr(const char *s) /* put a string back on input */
+{
+ int i;
+
+ for (i = strlen(s)-1; i >= 0; i--)
+ unput(s[i]);
+}
diff --git a/awk/Sources/awk/lib.c b/awk/Sources/awk/lib.c
new file mode 100644
index 00000000..0e10e404
--- /dev/null
+++ b/awk/Sources/awk/lib.c
@@ -0,0 +1,705 @@
+/****************************************************************
+Copyright (C) Lucent Technologies 1997
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name Lucent Technologies or any of
+its entities not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+****************************************************************/
+
+#define DEBUG
+#include
+#include
+#include
+#include
+#include
+#include
+#include "awk.h"
+#include "ytab.h"
+#include "ios_error.h"
+
+static __thread FILE *infile = NULL;
+static __thread char *file = "";
+__thread char *record;
+__thread int recsize = RECSIZE;
+__thread char *fields;
+__thread int fieldssize = RECSIZE;
+
+__thread Cell **fldtab; /* pointers to Cells */
+__thread char inputFS[100] = " ";
+
+#define MAXFLD 2
+__thread int nfields = MAXFLD; /* last allocated slot for $i */
+
+__thread int donefld; /* 1 = implies rec broken into fields */
+__thread int donerec; /* 1 = record is valid (no flds have changed) */
+
+__thread int lastfld = 0; /* last used field */
+__thread int argno = 1; /* current input argument number */
+extern __thread Awkfloat *ARGC;
+
+static __thread Cell dollar0 = { OCELL, CFLD, NULL, "", 0.0, REC|STR|DONTFREE };
+static __thread Cell dollar1 = { OCELL, CFLD, NULL, "", 0.0, FLD|STR|DONTFREE };
+
+void recinit(unsigned int n)
+{
+ if ( (record = (char*)calloc(n, sizeof(char*))) == NULL
+ || (fields = (char*)calloc(n+1, sizeof(char *))) == NULL
+ || (fldtab = (Cell **)calloc(nfields+1, sizeof(Cell*))) == NULL
+ || (fldtab[0] = (Cell *) calloc(1, sizeof(Cell))) == NULL )
+ FATAL("out of space for $0 and fields");
+/* if ( (record = (char *) malloc(n)) == NULL
+ || (fields = (char *) malloc(n+1)) == NULL
+ || (fldtab = (Cell **) malloc((nfields+1) * sizeof(Cell *))) == NULL
+ || (fldtab[0] = (Cell *) malloc(sizeof(Cell))) == NULL )
+ FATAL("out of space for $0 and fields"); */
+ *fldtab[0] = dollar0;
+ fldtab[0]->sval = record;
+ fldtab[0]->nval = tostring("0");
+ makefields(1, nfields);
+}
+
+void makefields(int n1, int n2) /* create $n1..$n2 inclusive */
+{
+ char temp[50];
+ int i;
+
+ for (i = n1; i <= n2; i++) {
+ fldtab[i] = (Cell *) malloc(sizeof (struct Cell));
+ if (fldtab[i] == NULL)
+ FATAL("out of space in makefields %d", i);
+ *fldtab[i] = dollar1;
+ sprintf(temp, "%d", i);
+ fldtab[i]->nval = tostring(temp);
+ }
+}
+
+void initgetrec(void)
+{
+ int i;
+ char *p;
+
+ for (i = 1; i < *ARGC; i++) {
+ if (!isclvar(p = getargv(i))) { /* find 1st real filename */
+ setsval(lookup("FILENAME", symtab), getargv(i));
+ return;
+ }
+ setclvar(p); /* a commandline assignment before filename */
+ argno++;
+ }
+ infile = thread_stdin; /* no filenames, so use stdin */
+}
+
+__thread int awk_firsttime = 1;
+
+int getrec(char **pbuf, int *pbufsize, int isrecord) /* get next input record */
+{ /* note: cares whether buf == record */
+ int c;
+ char *buf = *pbuf;
+ uschar saveb0;
+ int bufsize = *pbufsize, savebufsize = bufsize;
+
+ if (awk_firsttime) {
+ awk_firsttime = 0;
+ initgetrec();
+ }
+ dprintf( (thread_stdout, "RS=<%s>, FS=<%s>, ARGC=%g, FILENAME=%s\n",
+ *RS, *FS, *ARGC, *FILENAME) );
+ if (isrecord) {
+ donefld = 0;
+ donerec = 1;
+ }
+ saveb0 = buf[0];
+ buf[0] = 0;
+ while (argno < *ARGC || infile == thread_stdin) {
+ dprintf( (thread_stdout, "argno=%d, file=|%s|\n", argno, file) );
+ if (infile == NULL) { /* have to open a new file */
+ file = getargv(argno);
+ if (*file == '\0') { /* it's been zapped */
+ argno++;
+ continue;
+ }
+ if (isclvar(file)) { /* a var=value arg */
+ setclvar(file);
+ argno++;
+ continue;
+ }
+ *FILENAME = file;
+ dprintf( (thread_stdout, "opening file %s\n", file) );
+ if (*file == '-' && *(file+1) == '\0')
+ infile = thread_stdin;
+ else if ((infile = fopen(file, "r")) == NULL)
+ FATAL("can't open file %s", file);
+ setfval(fnrloc, 0.0);
+ }
+ c = readrec(&buf, &bufsize, infile);
+ if (c != 0 || buf[0] != '\0') { /* normal record */
+ if (isrecord) {
+ if (freeable(fldtab[0]))
+ xfree(fldtab[0]->sval);
+ fldtab[0]->sval = buf; /* buf == record */
+ fldtab[0]->tval = REC | STR | DONTFREE;
+ if (is_number(fldtab[0]->sval)) {
+ fldtab[0]->fval = atof(fldtab[0]->sval);
+ fldtab[0]->tval |= NUM;
+ }
+ }
+ setfval(nrloc, nrloc->fval+1);
+ setfval(fnrloc, fnrloc->fval+1);
+ if (donefld == 0)
+ fldbld();
+ *pbuf = buf;
+ *pbufsize = bufsize;
+ return 1;
+ }
+ /* EOF arrived on this file; set up next */
+ if (infile != thread_stdin)
+ fclose(infile);
+ else getc(infile); // OpenTerm issue: EOF is followed by \n, we need to clear the queue.
+ infile = NULL;
+ argno++;
+ }
+ buf[0] = saveb0;
+ *pbuf = buf;
+ *pbufsize = savebufsize;
+ return 0; /* true end of file */
+}
+
+void nextfile(void)
+{
+ if (infile != NULL && infile != thread_stdin)
+ fclose(infile);
+ infile = NULL;
+ argno++;
+}
+
+int readrec(char **pbuf, int *pbufsize, FILE *inf) /* read one record into buf */
+{
+ int sep, c;
+ char *rr, *buf = *pbuf;
+ int bufsize = *pbufsize;
+
+ if (strlen(*FS) >= sizeof(inputFS))
+ FATAL("field separator %.10s... is too long", *FS);
+ strcpy(inputFS, *FS); /* for subsequent field splitting */
+ if ((sep = **RS) == 0) {
+ sep = '\n';
+ while ((c=getc(inf)) == '\n' && c != EOF) /* skip leading \n's */
+ ;
+ if (c != EOF)
+ ungetc(c, inf);
+ }
+ for (rr = buf; ; ) {
+ for (; (c=getc(inf)) != sep && c != EOF; ) {
+ if (rr-buf+1 > bufsize)
+ if (!adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec 1"))
+ FATAL("input record `%.30s...' too long", buf);
+ *rr++ = c;
+ }
+ if (**RS == sep || c == EOF)
+ break;
+ if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */
+ break;
+ if (!adjbuf(&buf, &bufsize, 2+rr-buf, recsize, &rr, "readrec 2"))
+ FATAL("input record `%.30s...' too long", buf);
+ *rr++ = '\n';
+ *rr++ = c;
+ }
+ if (!adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec 3"))
+ FATAL("input record `%.30s...' too long", buf);
+ *rr = 0;
+ dprintf( (thread_stdout, "readrec saw <%s>, returns %d\n", buf, c == EOF && rr == buf ? 0 : 1) );
+ *pbuf = buf;
+ *pbufsize = bufsize;
+ return c == EOF && rr == buf ? 0 : 1;
+}
+
+char *getargv(int n) /* get ARGV[n] */
+{
+ Cell *x;
+ char *s, temp[50];
+ extern __thread Array *ARGVtab;
+
+ sprintf(temp, "%d", n);
+ x = setsymtab(temp, "", 0.0, STR, ARGVtab);
+ s = getsval(x);
+ dprintf( (thread_stdout, "getargv(%d) returns |%s|\n", n, s) );
+ return s;
+}
+
+void setclvar(char *s) /* set var=value from s */
+{
+ char *p;
+ Cell *q;
+
+ for (p=s; *p != '='; p++)
+ ;
+ *p++ = 0;
+ p = qstring(p, '\0');
+ q = setsymtab(s, p, 0.0, STR, symtab);
+ setsval(q, p);
+ if (is_number(q->sval)) {
+ q->fval = atof(q->sval);
+ q->tval |= NUM;
+ }
+ dprintf( (thread_stdout, "command line set %s to |%s|\n", s, p) );
+}
+
+
+void fldbld(void) /* create fields from current record */
+{
+ /* this relies on having fields[] the same length as $0 */
+ /* the fields are all stored in this one array with \0's */
+ char *r, *fr, sep;
+ Cell *p;
+ int i, j, n;
+
+ if (donefld)
+ return;
+ if (!isstr(fldtab[0]))
+ getsval(fldtab[0]);
+ r = fldtab[0]->sval;
+ n = strlen(r);
+ if (n > fieldssize) {
+ xfree(fields);
+ if ((fields = (char *) malloc(n+1)) == NULL)
+ FATAL("out of space for fields in fldbld %d", n);
+ fieldssize = n;
+ }
+ fr = fields;
+ i = 0; /* number of fields accumulated here */
+ if (strlen(inputFS) > 1) { /* it's a regular expression */
+ i = refldbld(r, inputFS);
+ } else if ((sep = *inputFS) == ' ') { /* default whitespace */
+ for (i = 0; ; ) {
+ while (*r == ' ' || *r == '\t' || *r == '\n')
+ r++;
+ if (*r == 0)
+ break;
+ i++;
+ if (i > nfields)
+ growfldtab(i);
+ if (freeable(fldtab[i]))
+ xfree(fldtab[i]->sval);
+ fldtab[i]->sval = fr;
+ fldtab[i]->tval = FLD | STR | DONTFREE;
+ do
+ *fr++ = *r++;
+ while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0');
+ *fr++ = 0;
+ }
+ *fr = 0;
+ } else if ((sep = *inputFS) == 0) { /* new: FS="" => 1 char/field */
+ for (i = 0; *r != 0; r++) {
+ char buf[2];
+ i++;
+ if (i > nfields)
+ growfldtab(i);
+ if (freeable(fldtab[i]))
+ xfree(fldtab[i]->sval);
+ buf[0] = *r;
+ buf[1] = 0;
+ fldtab[i]->sval = tostring(buf);
+ fldtab[i]->tval = FLD | STR;
+ }
+ *fr = 0;
+ } else if (*r != 0) { /* if 0, it's a null field */
+ /* subtlecase : if length(FS) == 1 && length(RS > 0)
+ * \n is NOT a field separator (cf awk book 61,84).
+ * this variable is tested in the inner while loop.
+ */
+ int rtest = '\n'; /* normal case */
+ if (strlen(*RS) > 0)
+ rtest = '\0';
+ for (;;) {
+ i++;
+ if (i > nfields)
+ growfldtab(i);
+ if (freeable(fldtab[i]))
+ xfree(fldtab[i]->sval);
+ fldtab[i]->sval = fr;
+ fldtab[i]->tval = FLD | STR | DONTFREE;
+ while (*r != sep && *r != rtest && *r != '\0') /* \n is always a separator */
+ *fr++ = *r++;
+ *fr++ = 0;
+ if (*r++ == 0)
+ break;
+ }
+ *fr = 0;
+ }
+ if (i > nfields)
+ FATAL("record `%.30s...' has too many fields; can't happen", r);
+ cleanfld(i+1, lastfld); /* clean out junk from previous record */
+ lastfld = i;
+ donefld = 1;
+ for (j = 1; j <= lastfld; j++) {
+ p = fldtab[j];
+ if(is_number(p->sval)) {
+ p->fval = atof(p->sval);
+ p->tval |= NUM;
+ }
+ }
+ setfval(nfloc, (Awkfloat) lastfld);
+ if (dbg) {
+ for (j = 0; j <= lastfld; j++) {
+ p = fldtab[j];
+ fprintf(thread_stdout, "field %d (%s): |%s|\n", j, p->nval, p->sval);
+ }
+ }
+}
+
+void cleanfld(int n1, int n2) /* clean out fields n1 .. n2 inclusive */
+{ /* nvals remain intact */
+ Cell *p;
+ int i;
+
+ for (i = n1; i <= n2; i++) {
+ p = fldtab[i];
+ if (freeable(p))
+ xfree(p->sval);
+ p->sval = "";
+ p->tval = FLD | STR | DONTFREE;
+ }
+}
+
+void newfld(int n) /* add field n after end of existing lastfld */
+{
+ if (n > nfields)
+ growfldtab(n);
+ cleanfld(lastfld+1, n);
+ lastfld = n;
+ setfval(nfloc, (Awkfloat) n);
+}
+
+Cell *fieldadr(int n) /* get nth field */
+{
+ if (n < 0)
+ FATAL("trying to access out of range field %d", n);
+ if (n > nfields) /* fields after NF are empty */
+ growfldtab(n); /* but does not increase NF */
+ return(fldtab[n]);
+}
+
+void growfldtab(int n) /* make new fields up to at least $n */
+{
+ int nf = 2 * nfields;
+ size_t s;
+
+ if (n > nf)
+ nf = n;
+ s = (nf+1) * (sizeof (struct Cell *)); /* freebsd: how much do we need? */
+ if (s / sizeof(struct Cell *) - 1 == nf) /* didn't overflow */
+ fldtab = (Cell **) realloc(fldtab, s);
+ else /* overflow sizeof int */
+ xfree(fldtab); /* make it null */
+ if (fldtab == NULL)
+ FATAL("out of space creating %d fields", nf);
+ makefields(nfields+1, nf);
+ nfields = nf;
+}
+
+int refldbld(const char *rec, const char *fs) /* build fields from reg expr in FS */
+{
+ /* this relies on having fields[] the same length as $0 */
+ /* the fields are all stored in this one array with \0's */
+ char *fr;
+ int i, tempstat, n;
+ fa *pfa;
+
+ n = strlen(rec);
+ if (n > fieldssize) {
+ xfree(fields);
+ if ((fields = (char *) malloc(n+1)) == NULL)
+ FATAL("out of space for fields in refldbld %d", n);
+ fieldssize = n;
+ }
+ fr = fields;
+ *fr = '\0';
+ if (*rec == '\0')
+ return 0;
+ pfa = makedfa(fs, 1);
+ dprintf( (thread_stdout, "into refldbld, rec = <%s>, pat = <%s>\n", rec, fs) );
+ tempstat = pfa->initstat;
+ for (i = 1; ; i++) {
+ if (i > nfields)
+ growfldtab(i);
+ if (freeable(fldtab[i]))
+ xfree(fldtab[i]->sval);
+ fldtab[i]->tval = FLD | STR | DONTFREE;
+ fldtab[i]->sval = fr;
+ dprintf( (thread_stdout, "refldbld: i=%d\n", i) );
+ if (nematch(pfa, rec)) {
+ pfa->initstat = 2; /* horrible coupling to b.c */
+ dprintf( (thread_stdout, "match %s (%d chars)\n", patbeg, patlen) );
+ strncpy(fr, rec, patbeg-rec);
+ fr += patbeg - rec + 1;
+ *(fr-1) = '\0';
+ rec = patbeg + patlen;
+ } else {
+ dprintf( (thread_stdout, "no match %s\n", rec) );
+ strcpy(fr, rec);
+ pfa->initstat = tempstat;
+ break;
+ }
+ }
+ return i;
+}
+
+void recbld(void) /* create $0 from $1..$NF if necessary */
+{
+ int i;
+ char *r, *p;
+
+ if (donerec == 1)
+ return;
+ r = record;
+ for (i = 1; i <= *NF; i++) {
+ p = getsval(fldtab[i]);
+ if (!adjbuf(&record, &recsize, 1+strlen(p)+r-record, recsize, &r, "recbld 1"))
+ FATAL("created $0 `%.30s...' too long", record);
+ while ((*r = *p++) != 0)
+ r++;
+ if (i < *NF) {
+ if (!adjbuf(&record, &recsize, 2+strlen(*OFS)+r-record, recsize, &r, "recbld 2"))
+ FATAL("created $0 `%.30s...' too long", record);
+ for (p = *OFS; (*r = *p++) != 0; )
+ r++;
+ }
+ }
+ if (!adjbuf(&record, &recsize, 2+r-record, recsize, &r, "recbld 3"))
+ FATAL("built giant record `%.30s...'", record);
+ *r = '\0';
+ dprintf( (thread_stdout, "in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, fldtab[0]) );
+
+ if (freeable(fldtab[0]))
+ xfree(fldtab[0]->sval);
+ fldtab[0]->tval = REC | STR | DONTFREE;
+ fldtab[0]->sval = record;
+
+ dprintf( (thread_stdout, "in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, fldtab[0]) );
+ dprintf( (thread_stdout, "recbld = |%s|\n", record) );
+ donerec = 1;
+}
+
+__thread int errorflag = 0;
+
+void yyerror(const char *s)
+{
+ SYNTAX("%s", s);
+}
+
+void SYNTAX(const char *fmt, ...)
+{
+ extern __thread char *cmdname, *curfname;
+ static __thread int been_here = 0;
+ va_list varg;
+
+ if (been_here++ > 2)
+ return;
+ fprintf(thread_stderr, "%s: ", cmdname);
+ va_start(varg, fmt);
+ vfprintf(thread_stderr, fmt, varg);
+ va_end(varg);
+ fprintf(thread_stderr, " at source line %d", lineno);
+ if (curfname != NULL)
+ fprintf(thread_stderr, " in function %s", curfname);
+ if (compile_time == 1 && cursource() != NULL)
+ fprintf(thread_stderr, " source file %s", cursource());
+ fprintf(thread_stderr, "\n");
+ errorflag = 2;
+ eprint();
+}
+
+void fpecatch(int n)
+{
+ FATAL("floating point exception %d", n);
+}
+
+extern __thread int bracecnt, brackcnt, parencnt;
+
+void bracecheck(void)
+{
+ int c;
+ static __thread int beenhere = 0;
+
+ if (beenhere++)
+ return;
+ while ((c = input()) != EOF && c != '\0')
+ bclass(c);
+ bcheck2(bracecnt, '{', '}');
+ bcheck2(brackcnt, '[', ']');
+ bcheck2(parencnt, '(', ')');
+}
+
+void bcheck2(int n, int c1, int c2)
+{
+ if (n == 1)
+ fprintf(thread_stderr, "\tmissing %c\n", c2);
+ else if (n > 1)
+ fprintf(thread_stderr, "\t%d missing %c's\n", n, c2);
+ else if (n == -1)
+ fprintf(thread_stderr, "\textra %c\n", c2);
+ else if (n < -1)
+ fprintf(thread_stderr, "\t%d extra %c's\n", -n, c2);
+}
+
+void FATAL(const char *fmt, ...)
+{
+ extern __thread char *cmdname;
+ va_list varg;
+
+ fflush(thread_stdout);
+ fprintf(thread_stderr, "%s: ", cmdname);
+ va_start(varg, fmt);
+ vfprintf(thread_stderr, fmt, varg);
+ va_end(varg);
+ error();
+ // if (dbg > 1) /* core dump if serious debugging on */
+ // abort();
+ exit(2);
+}
+
+void WARNING(const char *fmt, ...)
+{
+ extern __thread char *cmdname;
+ va_list varg;
+
+ fflush(thread_stdout);
+ fprintf(thread_stderr, "%s: ", cmdname);
+ va_start(varg, fmt);
+ vfprintf(thread_stderr, fmt, varg);
+ va_end(varg);
+ error();
+}
+
+void error()
+{
+ extern __thread Node *curnode;
+
+ fprintf(thread_stderr, "\n");
+ if (compile_time != 2 && NR && *NR > 0) {
+ fprintf(thread_stderr, " input record number %d", (int) (*FNR));
+ if (strcmp(*FILENAME, "-") != 0)
+ fprintf(thread_stderr, ", file %s", *FILENAME);
+ fprintf(thread_stderr, "\n");
+ }
+ if (compile_time != 2 && curnode)
+ fprintf(thread_stderr, " source line number %d", curnode->lineno);
+ else if (compile_time != 2 && lineno)
+ fprintf(thread_stderr, " source line number %d", lineno);
+ if (compile_time == 1 && cursource() != NULL)
+ fprintf(thread_stderr, " source file %s", cursource());
+ fprintf(thread_stderr, "\n");
+ eprint();
+}
+
+void eprint(void) /* try to print context around error */
+{
+ char *p, *q;
+ int c;
+ static __thread int been_here = 0;
+ extern char ebuf[], *ep;
+
+ if (compile_time == 2 || compile_time == 0 || been_here++ > 0)
+ return;
+ p = ep - 1;
+ if (p > ebuf && *p == '\n')
+ p--;
+ for ( ; p > ebuf && *p != '\n' && *p != '\0'; p--)
+ ;
+ while (*p == '\n')
+ p++;
+ fprintf(thread_stderr, " context is\n\t");
+ for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--)
+ ;
+ for ( ; p < q; p++)
+ if (*p)
+ putc(*p, thread_stderr);
+ fprintf(thread_stderr, " >>> ");
+ for ( ; p < ep; p++)
+ if (*p)
+ putc(*p, thread_stderr);
+ fprintf(thread_stderr, " <<< ");
+ if (*ep)
+ while ((c = input()) != '\n' && c != '\0' && c != EOF) {
+ putc(c, thread_stderr);
+ bclass(c);
+ }
+ putc('\n', thread_stderr);
+ ep = ebuf;
+}
+
+void bclass(int c)
+{
+ switch (c) {
+ case '{': bracecnt++; break;
+ case '}': bracecnt--; break;
+ case '[': brackcnt++; break;
+ case ']': brackcnt--; break;
+ case '(': parencnt++; break;
+ case ')': parencnt--; break;
+ }
+}
+
+double errcheck(double x, const char *s)
+{
+
+ if (errno == EDOM) {
+ errno = 0;
+ WARNING("%s argument out of domain", s);
+ x = 1;
+ } else if (errno == ERANGE) {
+ errno = 0;
+ WARNING("%s result out of range", s);
+ x = 1;
+ }
+ return x;
+}
+
+int isclvar(const char *s) /* is s of form var=something ? */
+{
+ const char *os = s;
+
+ if (!isalpha((uschar) *s) && *s != '_')
+ return 0;
+ for ( ; *s; s++)
+ if (!(isalnum((uschar) *s) || *s == '_'))
+ break;
+ return *s == '=' && s > os;
+}
+
+/* strtod is supposed to be a proper test of what's a valid number */
+/* appears to be broken in gcc on linux: thinks 0x123 is a valid FP number */
+/* wrong: violates 4.10.1.4 of ansi C standard */
+
+#include
+int is_number(const char *s)
+{
+ double r;
+ char *ep;
+ errno = 0;
+ r = strtod(s, &ep);
+ if (ep == s || r == HUGE_VAL || errno == ERANGE)
+ return 0;
+ while (*ep == ' ' || *ep == '\t' || *ep == '\n')
+ ep++;
+ if (*ep == '\0')
+ return 1;
+ else
+ return 0;
+}
diff --git a/awk/Sources/awk/parse.c b/awk/Sources/awk/parse.c
new file mode 100644
index 00000000..e42b17b6
--- /dev/null
+++ b/awk/Sources/awk/parse.c
@@ -0,0 +1,279 @@
+/****************************************************************
+Copyright (C) Lucent Technologies 1997
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name Lucent Technologies or any of
+its entities not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+****************************************************************/
+
+#define DEBUG
+#include
+#include
+#include
+#include "awk.h"
+#include "ytab.h"
+#include "ios_error.h"
+
+Node *nodealloc(int n)
+{
+ Node *x;
+
+ x = (Node *) malloc(sizeof(Node) + (n-1)*sizeof(Node *));
+ if (x == NULL)
+ FATAL("out of space in nodealloc");
+ memset(x, 0, sizeof(Node) + (n-1)*sizeof(Node *));
+ x->nnarg = n;
+ x->nnext = NULL;
+ x->lineno = lineno;
+ return(x);
+}
+
+Node *exptostat(Node *a)
+{
+ a->ntype = NSTAT;
+ return(a);
+}
+
+Node *node1(int a, Node *b)
+{
+ Node *x;
+
+ x = nodealloc(1);
+ x->nobj = a;
+ x->narg[0]=b;
+ return(x);
+}
+
+Node *node2(int a, Node *b, Node *c)
+{
+ Node *x;
+
+ x = nodealloc(2);
+ x->nobj = a;
+ x->narg[0] = b;
+ x->narg[1] = c;
+ return(x);
+}
+
+Node *node3(int a, Node *b, Node *c, Node *d)
+{
+ Node *x;
+
+ x = nodealloc(3);
+ x->nobj = a;
+ x->narg[0] = b;
+ x->narg[1] = c;
+ x->narg[2] = d;
+ return(x);
+}
+
+Node *node4(int a, Node *b, Node *c, Node *d, Node *e)
+{
+ Node *x;
+
+ x = nodealloc(4);
+ x->nobj = a;
+ x->narg[0] = b;
+ x->narg[1] = c;
+ x->narg[2] = d;
+ x->narg[3] = e;
+ return(x);
+}
+
+Node *stat1(int a, Node *b)
+{
+ Node *x;
+
+ x = node1(a,b);
+ x->ntype = NSTAT;
+ return(x);
+}
+
+Node *stat2(int a, Node *b, Node *c)
+{
+ Node *x;
+
+ x = node2(a,b,c);
+ x->ntype = NSTAT;
+ return(x);
+}
+
+Node *stat3(int a, Node *b, Node *c, Node *d)
+{
+ Node *x;
+
+ x = node3(a,b,c,d);
+ x->ntype = NSTAT;
+ return(x);
+}
+
+Node *stat4(int a, Node *b, Node *c, Node *d, Node *e)
+{
+ Node *x;
+
+ x = node4(a,b,c,d,e);
+ x->ntype = NSTAT;
+ return(x);
+}
+
+Node *op1(int a, Node *b)
+{
+ Node *x;
+
+ x = node1(a,b);
+ x->ntype = NEXPR;
+ return(x);
+}
+
+Node *op2(int a, Node *b, Node *c)
+{
+ Node *x;
+
+ x = node2(a,b,c);
+ x->ntype = NEXPR;
+ return(x);
+}
+
+Node *op3(int a, Node *b, Node *c, Node *d)
+{
+ Node *x;
+
+ x = node3(a,b,c,d);
+ x->ntype = NEXPR;
+ return(x);
+}
+
+Node *op4(int a, Node *b, Node *c, Node *d, Node *e)
+{
+ Node *x;
+
+ x = node4(a,b,c,d,e);
+ x->ntype = NEXPR;
+ return(x);
+}
+
+Node *celltonode(Cell *a, int b)
+{
+ Node *x;
+
+ a->ctype = OCELL;
+ a->csub = b;
+ x = node1(0, (Node *) a);
+ x->ntype = NVALUE;
+ return(x);
+}
+
+Node *rectonode(void) /* make $0 into a Node */
+{
+ extern __thread Cell *literal0;
+ return op1(INDIRECT, celltonode(literal0, CUNK));
+}
+
+Node *makearr(Node *p)
+{
+ Cell *cp;
+
+ if (isvalue(p)) {
+ cp = (Cell *) (p->narg[0]);
+ if (isfcn(cp))
+ SYNTAX( "%s is a function, not an array", cp->nval );
+ else if (!isarr(cp)) {
+ xfree(cp->sval);
+ cp->sval = (char *) makesymtab(NSYMTAB);
+ cp->tval = ARR;
+ }
+ }
+ return p;
+}
+
+#define PA2NUM 50 /* max number of pat,pat patterns allowed */
+__thread int paircnt; /* number of them in use */
+__thread int pairstack[PA2NUM]; /* state of each pat,pat */
+
+Node *pa2stat(Node *a, Node *b, Node *c) /* pat, pat {...} */
+{
+ Node *x;
+
+ x = node4(PASTAT2, a, b, c, itonp(paircnt));
+ if (paircnt++ >= PA2NUM)
+ SYNTAX( "limited to %d pat,pat statements", PA2NUM );
+ x->ntype = NSTAT;
+ return(x);
+}
+
+Node *linkum(Node *a, Node *b)
+{
+ Node *c;
+
+ if (errorflag) /* don't link things that are wrong */
+ return a;
+ if (a == NULL)
+ return(b);
+ else if (b == NULL)
+ return(a);
+ for (c = a; c->nnext != NULL; c = c->nnext)
+ ;
+ c->nnext = b;
+ return(a);
+}
+
+void defn(Cell *v, Node *vl, Node *st) /* turn on FCN bit in definition, */
+{ /* body of function, arglist */
+ Node *p;
+ int n;
+
+ if (isarr(v)) {
+ SYNTAX( "`%s' is an array name and a function name", v->nval );
+ return;
+ }
+ if (isarg(v->nval) != -1) {
+ SYNTAX( "`%s' is both function name and argument name", v->nval );
+ return;
+ }
+
+ v->tval = FCN;
+ v->sval = (char *) st;
+ n = 0; /* count arguments */
+ for (p = vl; p; p = p->nnext)
+ n++;
+ v->fval = n;
+ dprintf( (thread_stdout, "defining func %s (%d args)\n", v->nval, n) );
+}
+
+int isarg(const char *s) /* is s in argument list for current function? */
+{ /* return -1 if not, otherwise arg # */
+ extern __thread Node *arglist;
+ Node *p = arglist;
+ int n;
+
+ for (n = 0; p != 0; p = p->nnext, n++)
+ if (strcmp(((Cell *)(p->narg[0]))->nval, s) == 0)
+ return n;
+ return -1;
+}
+
+int ptoi(void *p) /* convert pointer to integer */
+{
+ return (int) (long) p; /* swearing that p fits, of course */
+}
+
+Node *itonp(int i) /* and vice versa */
+{
+ return (Node *) (long) i;
+}
diff --git a/awk/Sources/awk/proctab.c b/awk/Sources/awk/proctab.c
new file mode 100644
index 00000000..d409cc08
--- /dev/null
+++ b/awk/Sources/awk/proctab.c
@@ -0,0 +1,212 @@
+#include
+#include "awk.h"
+#include "ytab.h"
+#include "ios_error.h"
+
+static char *printname[95] = {
+ (char *) "FIRSTTOKEN", /* 258 */
+ (char *) "PROGRAM", /* 259 */
+ (char *) "PASTAT", /* 260 */
+ (char *) "PASTAT2", /* 261 */
+ (char *) "XBEGIN", /* 262 */
+ (char *) "XEND", /* 263 */
+ (char *) "NL", /* 264 */
+ (char *) "ARRAY", /* 265 */
+ (char *) "MATCH", /* 266 */
+ (char *) "NOTMATCH", /* 267 */
+ (char *) "MATCHOP", /* 268 */
+ (char *) "FINAL", /* 269 */
+ (char *) "DOT", /* 270 */
+ (char *) "ALL", /* 271 */
+ (char *) "CCL", /* 272 */
+ (char *) "NCCL", /* 273 */
+ (char *) "CHAR", /* 274 */
+ (char *) "OR", /* 275 */
+ (char *) "STAR", /* 276 */
+ (char *) "QUEST", /* 277 */
+ (char *) "PLUS", /* 278 */
+ (char *) "EMPTYRE", /* 279 */
+ (char *) "IGNORE_PRIOR_ATOM", /* 280 */
+ (char *) "AND", /* 281 */
+ (char *) "BOR", /* 282 */
+ (char *) "APPEND", /* 283 */
+ (char *) "EQ", /* 284 */
+ (char *) "GE", /* 285 */
+ (char *) "GT", /* 286 */
+ (char *) "LE", /* 287 */
+ (char *) "LT", /* 288 */
+ (char *) "NE", /* 289 */
+ (char *) "IN", /* 290 */
+ (char *) "ARG", /* 291 */
+ (char *) "BLTIN", /* 292 */
+ (char *) "BREAK", /* 293 */
+ (char *) "CLOSE", /* 294 */
+ (char *) "CONTINUE", /* 295 */
+ (char *) "DELETE", /* 296 */
+ (char *) "DO", /* 297 */
+ (char *) "EXIT", /* 298 */
+ (char *) "FOR", /* 299 */
+ (char *) "FUNC", /* 300 */
+ (char *) "SUB", /* 301 */
+ (char *) "GSUB", /* 302 */
+ (char *) "IF", /* 303 */
+ (char *) "INDEX", /* 304 */
+ (char *) "LSUBSTR", /* 305 */
+ (char *) "MATCHFCN", /* 306 */
+ (char *) "NEXT", /* 307 */
+ (char *) "NEXTFILE", /* 308 */
+ (char *) "ADD", /* 309 */
+ (char *) "MINUS", /* 310 */
+ (char *) "MULT", /* 311 */
+ (char *) "DIVIDE", /* 312 */
+ (char *) "MOD", /* 313 */
+ (char *) "ASSIGN", /* 314 */
+ (char *) "ASGNOP", /* 315 */
+ (char *) "ADDEQ", /* 316 */
+ (char *) "SUBEQ", /* 317 */
+ (char *) "MULTEQ", /* 318 */
+ (char *) "DIVEQ", /* 319 */
+ (char *) "MODEQ", /* 320 */
+ (char *) "POWEQ", /* 321 */
+ (char *) "PRINT", /* 322 */
+ (char *) "PRINTF", /* 323 */
+ (char *) "SPRINTF", /* 324 */
+ (char *) "ELSE", /* 325 */
+ (char *) "INTEST", /* 326 */
+ (char *) "CONDEXPR", /* 327 */
+ (char *) "POSTINCR", /* 328 */
+ (char *) "PREINCR", /* 329 */
+ (char *) "POSTDECR", /* 330 */
+ (char *) "PREDECR", /* 331 */
+ (char *) "VAR", /* 332 */
+ (char *) "IVAR", /* 333 */
+ (char *) "VARNF", /* 334 */
+ (char *) "CALL", /* 335 */
+ (char *) "NUMBER", /* 336 */
+ (char *) "STRING", /* 337 */
+ (char *) "REGEXPR", /* 338 */
+ (char *) "GETLINE", /* 339 */
+ (char *) "SUBSTR", /* 340 */
+ (char *) "SPLIT", /* 341 */
+ (char *) "RETURN", /* 342 */
+ (char *) "WHILE", /* 343 */
+ (char *) "CAT", /* 344 */
+ (char *) "UPLUS", /* 345 */
+ (char *) "UMINUS", /* 346 */
+ (char *) "NOT", /* 347 */
+ (char *) "POWER", /* 348 */
+ (char *) "INCR", /* 349 */
+ (char *) "DECR", /* 350 */
+ (char *) "INDIRECT", /* 351 */
+ (char *) "LASTTOKEN", /* 352 */
+};
+
+
+Cell *(*proctab[95])(Node **, int) = {
+ nullproc, /* FIRSTTOKEN */
+ program, /* PROGRAM */
+ pastat, /* PASTAT */
+ dopa2, /* PASTAT2 */
+ nullproc, /* XBEGIN */
+ nullproc, /* XEND */
+ nullproc, /* NL */
+ array, /* ARRAY */
+ matchop, /* MATCH */
+ matchop, /* NOTMATCH */
+ nullproc, /* MATCHOP */
+ nullproc, /* FINAL */
+ nullproc, /* DOT */
+ nullproc, /* ALL */
+ nullproc, /* CCL */
+ nullproc, /* NCCL */
+ nullproc, /* CHAR */
+ nullproc, /* OR */
+ nullproc, /* STAR */
+ nullproc, /* QUEST */
+ nullproc, /* PLUS */
+ nullproc, /* EMPTYRE */
+ nullproc, /* IGNORE_PRIOR_ATOM */
+ boolop, /* AND */
+ boolop, /* BOR */
+ nullproc, /* APPEND */
+ relop, /* EQ */
+ relop, /* GE */
+ relop, /* GT */
+ relop, /* LE */
+ relop, /* LT */
+ relop, /* NE */
+ instat, /* IN */
+ arg, /* ARG */
+ bltin, /* BLTIN */
+ jump, /* BREAK */
+ closefile, /* CLOSE */
+ jump, /* CONTINUE */
+ awkdelete, /* DELETE */
+ dostat, /* DO */
+ jump, /* EXIT */
+ forstat, /* FOR */
+ nullproc, /* FUNC */
+ sub, /* SUB */
+ gsub, /* GSUB */
+ ifstat, /* IF */
+ sindex, /* INDEX */
+ nullproc, /* LSUBSTR */
+ matchop, /* MATCHFCN */
+ jump, /* NEXT */
+ jump, /* NEXTFILE */
+ arith, /* ADD */
+ arith, /* MINUS */
+ arith, /* MULT */
+ arith, /* DIVIDE */
+ arith, /* MOD */
+ assign, /* ASSIGN */
+ nullproc, /* ASGNOP */
+ assign, /* ADDEQ */
+ assign, /* SUBEQ */
+ assign, /* MULTEQ */
+ assign, /* DIVEQ */
+ assign, /* MODEQ */
+ assign, /* POWEQ */
+ printstat, /* PRINT */
+ awkprintf, /* PRINTF */
+ awksprintf, /* SPRINTF */
+ nullproc, /* ELSE */
+ intest, /* INTEST */
+ condexpr, /* CONDEXPR */
+ incrdecr, /* POSTINCR */
+ incrdecr, /* PREINCR */
+ incrdecr, /* POSTDECR */
+ incrdecr, /* PREDECR */
+ nullproc, /* VAR */
+ nullproc, /* IVAR */
+ getnf, /* VARNF */
+ call, /* CALL */
+ nullproc, /* NUMBER */
+ nullproc, /* STRING */
+ nullproc, /* REGEXPR */
+ awk_getline, /* GETLINE */
+ substr, /* SUBSTR */
+ split, /* SPLIT */
+ jump, /* RETURN */
+ whilestat, /* WHILE */
+ cat, /* CAT */
+ arith, /* UPLUS */
+ arith, /* UMINUS */
+ boolop, /* NOT */
+ arith, /* POWER */
+ nullproc, /* INCR */
+ nullproc, /* DECR */
+ indirect, /* INDIRECT */
+ nullproc, /* LASTTOKEN */
+};
+
+char *tokname(int n)
+{
+ static __thread char buf[100];
+
+ if (n < FIRSTTOKEN || n > LASTTOKEN) {
+ sprintf(buf, "token %d", n);
+ return buf;
+ }
+ return printname[n-FIRSTTOKEN];
+}
diff --git a/awk/Sources/awk/proto.h b/awk/Sources/awk/proto.h
new file mode 100644
index 00000000..c7705645
--- /dev/null
+++ b/awk/Sources/awk/proto.h
@@ -0,0 +1,196 @@
+/****************************************************************
+Copyright (C) Lucent Technologies 1997
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name Lucent Technologies or any of
+its entities not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+****************************************************************/
+
+extern int yywrap(void);
+extern void setfname(Cell *);
+extern int constnode(Node *);
+extern char *strnode(Node *);
+extern Node *notnull(Node *);
+extern int yyparse(void);
+
+extern int yylex(void);
+extern void startreg(void);
+extern int input(void);
+extern void unput(int);
+extern void unputstr(const char *);
+extern int yylook(void);
+extern int yyback(int *, int);
+extern int yyinput(void);
+
+extern fa *makedfa(const char *, int);
+extern fa *mkdfa(const char *, int);
+extern int makeinit(fa *, int);
+extern void penter(Node *);
+extern void freetr(Node *);
+extern int hexstr(char **);
+extern int quoted(char **);
+extern char *cclenter(const char *);
+extern void overflo(const char *);
+extern void cfoll(fa *, Node *);
+// extern int first(Node *);
+extern void follow(Node *);
+extern int member(int, const char *);
+extern int smatch(fa *, const char *); // was match
+extern int pmatch(fa *, const char *);
+extern int nematch(fa *, const char *);
+extern Node *reparse(const char *);
+extern Node *regexp(void);
+extern Node *primary(void);
+extern Node *concat(Node *);
+extern Node *alt(Node *);
+extern Node *unary(Node *);
+extern int relex(void);
+extern int cgoto(fa *, int, int);
+extern void freefa(fa *);
+
+extern int pgetc(void);
+extern char *cursource(void);
+
+extern Node *nodealloc(int);
+extern Node *exptostat(Node *);
+extern Node *node1(int, Node *);
+extern Node *node2(int, Node *, Node *);
+extern Node *node3(int, Node *, Node *, Node *);
+extern Node *node4(int, Node *, Node *, Node *, Node *);
+extern Node *stat3(int, Node *, Node *, Node *);
+extern Node *op2(int, Node *, Node *);
+extern Node *op1(int, Node *);
+extern Node *stat1(int, Node *);
+extern Node *op3(int, Node *, Node *, Node *);
+extern Node *op4(int, Node *, Node *, Node *, Node *);
+extern Node *stat2(int, Node *, Node *);
+extern Node *stat4(int, Node *, Node *, Node *, Node *);
+extern Node *celltonode(Cell *, int);
+extern Node *rectonode(void);
+extern Node *makearr(Node *);
+extern Node *pa2stat(Node *, Node *, Node *);
+extern Node *linkum(Node *, Node *);
+extern void defn(Cell *, Node *, Node *);
+extern int isarg(const char *);
+extern char *tokname(int);
+extern Cell *(*proctab[])(Node **, int);
+extern int ptoi(void *);
+extern Node *itonp(int);
+
+extern void syminit(void);
+extern void arginit(int, char **);
+extern void envinit(char **);
+extern Array *makesymtab(int);
+extern void freesymtab(Cell *);
+extern void freeelem(Cell *, const char *);
+extern Cell *setsymtab(const char *, const char *, double, unsigned int, Array *);
+extern int hash(const char *, int);
+extern void rehash(Array *);
+extern Cell *lookup(const char *, Array *);
+extern double setfval(Cell *, double);
+extern void funnyvar(Cell *, const char *);
+extern char *setsval(Cell *, const char *);
+extern double getfval(Cell *);
+extern char *getsval(Cell *);
+extern char *getpssval(Cell *); /* for print */
+extern char *tostring(const char *);
+extern char *qstring(const char *, int);
+
+extern void recinit(unsigned int);
+extern void initgetrec(void);
+extern void makefields(int, int);
+extern void growfldtab(int n);
+extern int getrec(char **, int *, int);
+extern void nextfile(void);
+extern int readrec(char **buf, int *bufsize, FILE *inf);
+extern char *getargv(int);
+extern void setclvar(char *);
+extern void fldbld(void);
+extern void cleanfld(int, int);
+extern void newfld(int);
+extern int refldbld(const char *, const char *);
+extern void recbld(void);
+extern Cell *fieldadr(int);
+extern void yyerror(const char *);
+extern void fpecatch(int);
+extern void bracecheck(void);
+extern void bcheck2(int, int, int);
+extern void SYNTAX(const char *, ...);
+extern void FATAL(const char *, ...);
+extern void WARNING(const char *, ...);
+extern void error(void);
+extern void eprint(void);
+extern void bclass(int);
+extern double errcheck(double, const char *);
+extern int isclvar(const char *);
+extern int is_number(const char *);
+
+extern int adjbuf(char **pb, int *sz, int min, int q, char **pbp, const char *what);
+extern void run(Node *);
+extern void freeTree(Node *, int eraseSelf);
+extern Cell *execute(Node *);
+extern Cell *program(Node **, int);
+extern Cell *call(Node **, int);
+extern Cell *copycell(Cell *);
+extern Cell *arg(Node **, int);
+extern Cell *jump(Node **, int);
+extern Cell *awk_getline(Node **, int);
+extern Cell *getnf(Node **, int);
+extern Cell *array(Node **, int);
+extern Cell *awkdelete(Node **, int);
+extern Cell *intest(Node **, int);
+extern Cell *matchop(Node **, int);
+extern Cell *boolop(Node **, int);
+extern Cell *relop(Node **, int);
+extern void tfree(Cell *);
+extern Cell *gettemp(void);
+extern Cell *field(Node **, int);
+extern Cell *indirect(Node **, int);
+extern Cell *substr(Node **, int);
+extern Cell *sindex(Node **, int);
+extern int format(char **, int *, const char *, Node *);
+extern Cell *awksprintf(Node **, int);
+extern Cell *awkprintf(Node **, int);
+extern Cell *arith(Node **, int);
+extern double ipow(double, int);
+extern Cell *incrdecr(Node **, int);
+extern Cell *assign(Node **, int);
+extern Cell *cat(Node **, int);
+extern Cell *pastat(Node **, int);
+extern Cell *dopa2(Node **, int);
+extern Cell *split(Node **, int);
+extern Cell *condexpr(Node **, int);
+extern Cell *ifstat(Node **, int);
+extern Cell *whilestat(Node **, int);
+extern Cell *dostat(Node **, int);
+extern Cell *forstat(Node **, int);
+extern Cell *instat(Node **, int);
+extern Cell *bltin(Node **, int);
+extern Cell *printstat(Node **, int);
+extern Cell *nullproc(Node **, int);
+extern FILE *redirect(int, Node *);
+extern FILE *openfile(int, const char *);
+// extern const char *filename(FILE *);
+extern Cell *closefile(Node **, int);
+extern void closeall(void);
+extern Cell *sub(Node **, int);
+extern Cell *gsub(Node **, int);
+
+extern FILE *popen(const char *, const char *);
+extern int pclose(FILE *);
diff --git a/awk/Sources/awk/run.c b/awk/Sources/awk/run.c
new file mode 100644
index 00000000..b8570b04
--- /dev/null
+++ b/awk/Sources/awk/run.c
@@ -0,0 +1,1999 @@
+/****************************************************************
+Copyright (C) Lucent Technologies 1997
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name Lucent Technologies or any of
+its entities not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+****************************************************************/
+
+#define DEBUG
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "awk.h"
+#include "ytab.h"
+
+#include "ios_error.h"
+
+#define tempfree(x) if (istemp(x)) tfree(x); /* else */
+
+/*
+#undef tempfree
+
+void tempfree(Cell *p) {
+ if (p->ctype == OCELL && (p->csub < CUNK || p->csub > CFREE)) {
+ WARNING("bad csub %d in Cell %d %s",
+ p->csub, p->ctype, p->sval);
+ }
+ if (istemp(p))
+ tfree(p);
+}
+*/
+
+/* do we really need these? */
+/* #ifdef _NFILE */
+/* #ifndef FOPEN_MAX */
+/* #define FOPEN_MAX _NFILE */
+/* #endif */
+/* #endif */
+/* */
+/* #ifndef FOPEN_MAX */
+/* #define FOPEN_MAX 40 */ /* max number of open files */
+/* #endif */
+/* */
+/* #ifndef RAND_MAX */
+/* #define RAND_MAX 32767 */ /* all that ansi guarantees */
+/* #endif */
+
+static __thread jmp_buf env;
+extern __thread int pairstack[];
+
+__thread Node *winner = NULL; /* root of parse tree */
+Cell *tmps; /* free temporary cells for execution */
+
+static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM };
+Cell *True = &truecell;
+static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM };
+Cell *False = &falsecell;
+static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM };
+Cell *jbreak = &breakcell;
+static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM };
+Cell *jcont = &contcell;
+static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM };
+Cell *jnext = &nextcell;
+static Cell nextfilecell ={ OJUMP, JNEXTFILE, 0, 0, 0.0, NUM };
+Cell *jnextfile = &nextfilecell;
+static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM };
+Cell *jexit = &exitcell;
+static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM };
+Cell *jret = &retcell;
+static Cell tempcell ={ OCELL, CTEMP, 0, "", 0.0, NUM|STR|DONTFREE };
+
+__thread Node *curnode = NULL; /* the node being executed, for debugging */
+
+static __thread Awkfloat prev_srand, tmp_srand;
+
+/* buffer memory management */
+int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr,
+ const char *whatrtn)
+/* pbuf: address of pointer to buffer being managed
+ * psiz: address of buffer size variable
+ * minlen: minimum length of buffer needed
+ * quantum: buffer size quantum
+ * pbptr: address of movable pointer into buffer, or 0 if none
+ * whatrtn: name of the calling routine if failure should cause fatal error
+ *
+ * return 0 for realloc failure, !=0 for success
+ */
+{
+ if (minlen > *psiz) {
+ char *tbuf;
+ int rminlen = quantum ? minlen % quantum : 0;
+ int boff = pbptr ? *pbptr - *pbuf : 0;
+ /* round up to next multiple of quantum */
+ if (rminlen)
+ minlen += quantum - rminlen;
+ tbuf = (char *) realloc(*pbuf, minlen);
+ dprintf( (thread_stdout, "adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn, *psiz, minlen, *pbuf, tbuf) );
+ if (tbuf == NULL) {
+ if (whatrtn)
+ FATAL("out of memory in %s", whatrtn);
+ return 0;
+ }
+ *pbuf = tbuf;
+ *psiz = minlen;
+ if (pbptr)
+ *pbptr = tbuf + boff;
+ }
+ return 1;
+}
+
+void run(Node *a) /* execution of parse tree starts here */
+{
+ extern void stdinit(void);
+
+ stdinit();
+ execute(a);
+ closeall();
+ freeTree(a, 1);
+ // Reset main variables at exit:
+ curnode = NULL;
+ winner = NULL;
+ // These are defined in ytab.c
+ extern __thread Node *beginloc;
+ extern __thread Node *endloc;
+ beginloc = 0;
+ endloc = 0;
+}
+
+void freeTree(Node *u, int eraseSelf) /* scan the entire tree, and frees the allocated memory */
+{
+ Node *a;
+ Node *anext;
+
+ if (u == NULL) return;
+ if ((int)u == 0x1) return; // safeguard
+
+ // If it's a tree, freetr will do the job:
+ if ((u->nobj == CCL) || (u->nobj == NCCL) || (u->nobj == CHAR) || (u->nobj == DOT) || (u->nobj == FINAL)
+ || (u->nobj == ALL) || (u->nobj == EMPTYRE) || (u->nobj == STAR) || (u->nobj == PLUS) || (u->nobj == QUEST)
+ || (u->nobj == CAT) || (u->nobj == OR)) {
+ freetr(u);
+ return;
+ }
+ for (a = u; a; a = anext) {
+ if ((a->ntype == NSTAT) || (a->ntype == NEXPR)) {
+ for (int i = 0; i < a->nnarg; i++) {
+ freeTree(a->narg[i], 0); // never free narg, it was allocated as part of the node
+ a->narg[i] = NULL;
+ }
+ }
+ // Erase all values, all pointers.
+ anext = a->nnext;
+ if ((int)anext % 8 != 0) anext = NULL; // Enforce 8-bit alignment
+ a->ntype = 0;
+ a->nnext = NULL;
+ a->lineno = 0;
+ a->nobj = 0;
+ a->nnarg = 0;
+ a->narg[0] = NULL;
+ if (eraseSelf) {
+ free(a);
+ }
+ eraseSelf = 1; // but free node->next
+ a = NULL;
+ }
+}
+
+
+Cell *execute(Node *u) /* execute a node of the parse tree */
+{
+ Cell *(*proc)(Node **, int);
+ Cell *x;
+ Node *a;
+
+ if (u == NULL)
+ return(True);
+ for (a = u; ; a = a->nnext) {
+ curnode = a;
+ if (isvalue(a)) {
+ x = (Cell *) (a->narg[0]);
+ if (isfld(x) && !donefld)
+ fldbld();
+ else if (isrec(x) && !donerec)
+ recbld();
+ return(x);
+ }
+ if (notlegal(a->nobj)) /* probably a Cell* but too risky to print */
+ FATAL("illegal statement");
+ proc = proctab[a->nobj-FIRSTTOKEN];
+ x = (*proc)(a->narg, a->nobj);
+ if (isfld(x) && !donefld)
+ fldbld();
+ else if (isrec(x) && !donerec)
+ recbld();
+ if (isexpr(a))
+ return(x);
+ if (isjump(x))
+ return(x);
+ if (a->nnext == NULL)
+ return(x);
+ tempfree(x);
+ }
+}
+
+
+Cell *program(Node **a, int n) /* execute an awk program */
+{ /* a[0] = BEGIN, a[1] = body, a[2] = END */
+ Cell *x;
+
+ if (setjmp(env) != 0)
+ goto ex;
+ if (a[0]) { /* BEGIN */
+ x = execute(a[0]);
+ if (isexit(x))
+ return(True);
+ if (isjump(x))
+ FATAL("illegal break, continue, next or nextfile from BEGIN");
+ tempfree(x);
+ }
+ if (a[1] || a[2])
+ while (getrec(&record, &recsize, 1) > 0) {
+ x = execute(a[1]);
+ if (isexit(x))
+ break;
+ tempfree(x);
+ }
+ ex:
+ if (setjmp(env) != 0) /* handles exit within END */
+ goto ex1;
+ if (a[2]) { /* END */
+ donefld = 1; /* avoid updating NF */
+ x = execute(a[2]);
+ if (isbreak(x) || isnext(x) || iscont(x))
+ FATAL("illegal break, continue, next or nextfile from END");
+ tempfree(x);
+ }
+ ex1:
+ return(True);
+}
+
+struct Frame { /* stack frame for awk function calls */
+ int nargs; /* number of arguments in this call */
+ Cell *fcncell; /* pointer to Cell for function */
+ Cell **args; /* pointer to array of arguments after execute */
+ Cell *retval; /* return value */
+};
+
+#define NARGS 50 /* max args in a call */
+
+struct Frame *frame = NULL; /* base of stack frames; dynamically allocated */
+int nframe = 0; /* number of frames allocated */
+struct Frame *fp = NULL; /* frame pointer. bottom level unused */
+
+Cell *call(Node **a, int n) /* function call. very kludgy and fragile */
+{
+ static __thread Cell newcopycell = { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE };
+ int i, ncall, ndef;
+ int freed = 0; /* handles potential double freeing when fcn & param share a tempcell */
+ Node *x;
+ Cell *args[NARGS], *oargs[NARGS]; /* BUG: fixed size arrays */
+ Cell *y, *z, *fcn;
+ char *s;
+
+ fcn = execute(a[0]); /* the function itself */
+ s = fcn->nval;
+ if (!isfcn(fcn))
+ FATAL("calling undefined function %s", s);
+ if (frame == NULL) {
+ fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame));
+ if (frame == NULL)
+ FATAL("out of space for stack frames calling %s", s);
+ }
+ for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */
+ ncall++;
+ ndef = (int) fcn->fval; /* args in defn */
+ dprintf( (thread_stdout, "calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, (int) (fp-frame)) );
+ if (ncall > ndef)
+ WARNING("function %s called with %d args, uses only %d",
+ s, ncall, ndef);
+ if (ncall + ndef > NARGS)
+ FATAL("function %s has %d arguments, limit %d", s, ncall+ndef, NARGS);
+ for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) { /* get call args */
+ dprintf( (thread_stdout, "evaluate args[%d], fp=%d:\n", i, (int) (fp-frame)) );
+ y = execute(x);
+ oargs[i] = y;
+ dprintf( (thread_stdout, "args[%d]: %s %f <%s>, t=%o\n",
+ i, NN(y->nval), y->fval, isarr(y) ? "(array)" : NN(y->sval), y->tval) );
+ if (isfcn(y))
+ FATAL("can't use function %s as argument in %s", y->nval, s);
+ if (isarr(y))
+ args[i] = y; /* arrays by ref */
+ else
+ args[i] = copycell(y);
+ tempfree(y);
+ }
+ for ( ; i < ndef; i++) { /* add null args for ones not provided */
+ args[i] = gettemp();
+ *args[i] = newcopycell;
+ }
+ fp++; /* now ok to up frame */
+ if (fp >= frame + nframe) {
+ int dfp = fp - frame; /* old index */
+ frame = (struct Frame *)
+ realloc((char *) frame, (nframe += 100) * sizeof(struct Frame));
+ if (frame == NULL)
+ FATAL("out of space for stack frames in %s", s);
+ fp = frame + dfp;
+ }
+ fp->fcncell = fcn;
+ fp->args = args;
+ fp->nargs = ndef; /* number defined with (excess are locals) */
+ fp->retval = gettemp();
+
+ dprintf( (thread_stdout, "start exec of %s, fp=%d\n", s, (int) (fp-frame)) );
+ y = execute((Node *)(fcn->sval)); /* execute body */
+ dprintf( (thread_stdout, "finished exec of %s, fp=%d\n", s, (int) (fp-frame)) );
+
+ for (i = 0; i < ndef; i++) {
+ Cell *t = fp->args[i];
+ if (isarr(t)) {
+ if (t->csub == CCOPY) {
+ if (i >= ncall) {
+ freesymtab(t);
+ t->csub = CTEMP;
+ tempfree(t);
+ } else {
+ oargs[i]->tval = t->tval;
+ oargs[i]->tval &= ~(STR|NUM|DONTFREE);
+ oargs[i]->sval = t->sval;
+ tempfree(t);
+ }
+ }
+ } else if (t != y) { /* kludge to prevent freeing twice */
+ t->csub = CTEMP;
+ tempfree(t);
+ } else if (t == y && t->csub == CCOPY) {
+ t->csub = CTEMP;
+ tempfree(t);
+ freed = 1;
+ }
+ }
+ tempfree(fcn);
+ if (isexit(y) || isnext(y))
+ return y;
+ if (freed == 0) {
+ tempfree(y); /* don't free twice! */
+ }
+ z = fp->retval; /* return value */
+ dprintf( (thread_stdout, "%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) );
+ fp--;
+ return(z);
+}
+
+Cell *copycell(Cell *x) /* make a copy of a cell in a temp */
+{
+ Cell *y;
+
+ y = gettemp();
+ y->csub = CCOPY; /* prevents freeing until call is over */
+ y->nval = x->nval; /* BUG? */
+ if (isstr(x))
+ y->sval = tostring(x->sval);
+ y->fval = x->fval;
+ y->tval = x->tval & ~(CON|FLD|REC|DONTFREE); /* copy is not constant or field */
+ /* is DONTFREE right? */
+ return y;
+}
+
+Cell *arg(Node **a, int n) /* nth argument of a function */
+{
+
+ n = ptoi(a[0]); /* argument number, counting from 0 */
+ dprintf( (thread_stdout, "arg(%d), fp->nargs=%d\n", n, fp->nargs) );
+ if (n+1 > fp->nargs)
+ FATAL("argument #%d of function %s was not supplied",
+ n+1, fp->fcncell->nval);
+ return fp->args[n];
+}
+
+Cell *jump(Node **a, int n) /* break, continue, next, nextfile, return */
+{
+ Cell *y;
+
+ switch (n) {
+ case EXIT:
+ if (a[0] != NULL) {
+ y = execute(a[0]);
+ errorflag = (int) getfval(y);
+ tempfree(y);
+ }
+ longjmp(env, 1);
+ case RETURN:
+ if (a[0] != NULL) {
+ y = execute(a[0]);
+ if ((y->tval & (STR|NUM)) == (STR|NUM)) {
+ setsval(fp->retval, getsval(y));
+ fp->retval->fval = getfval(y);
+ fp->retval->tval |= NUM;
+ }
+ else if (y->tval & STR)
+ setsval(fp->retval, getsval(y));
+ else if (y->tval & NUM)
+ setfval(fp->retval, getfval(y));
+ else /* can't happen */
+ FATAL("bad type variable %d", y->tval);
+ tempfree(y);
+ }
+ return(jret);
+ case NEXT:
+ return(jnext);
+ case NEXTFILE:
+ nextfile();
+ return(jnextfile);
+ case BREAK:
+ return(jbreak);
+ case CONTINUE:
+ return(jcont);
+ default: /* can't happen */
+ FATAL("illegal jump type %d", n);
+ }
+ return 0; /* not reached */
+}
+
+Cell *awk_getline(Node **a, int n) /* get next line from specific input */
+{ /* a[0] is variable, a[1] is operator, a[2] is filename */
+ Cell *r, *x;
+ extern __thread Cell **fldtab;
+ FILE *fp;
+ char *buf;
+ int bufsize = recsize;
+ int mode;
+
+ if ((buf = (char *) malloc(bufsize)) == NULL)
+ FATAL("out of memory in getline");
+
+ fflush(thread_stdout); /* in case someone is waiting for a prompt */
+ r = gettemp();
+ if (a[1] != NULL) { /* getline < file */
+ x = execute(a[2]); /* filename */
+ mode = ptoi(a[1]);
+ if (mode == '|') /* input pipe */
+ mode = LE; /* arbitrary flag */
+ fp = openfile(mode, getsval(x));
+ tempfree(x);
+ if (fp == NULL)
+ n = -1;
+ else
+ n = readrec(&buf, &bufsize, fp);
+ if (n <= 0) {
+ ;
+ } else if (a[0] != NULL) { /* getline var sval)) {
+ fldtab[0]->fval = atof(fldtab[0]->sval);
+ fldtab[0]->tval |= NUM;
+ }
+ }
+ } else { /* bare getline; use current input */
+ if (a[0] == NULL) /* getline */
+ n = getrec(&record, &recsize, 1);
+ else { /* getline var */
+ n = getrec(&buf, &bufsize, 0);
+ x = execute(a[0]);
+ setsval(x, buf);
+ tempfree(x);
+ }
+ }
+ setfval(r, (Awkfloat) n);
+ free(buf);
+ return r;
+}
+
+Cell *getnf(Node **a, int n) /* get NF */
+{
+ if (donefld == 0)
+ fldbld();
+ return (Cell *) a[0];
+}
+
+Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
+{
+ Cell *x, *y, *z;
+ char *s;
+ Node *np;
+ char *buf;
+ int bufsz = recsize;
+ int nsub = strlen(*SUBSEP);
+
+ if ((buf = (char *) malloc(bufsz)) == NULL)
+ FATAL("out of memory in array");
+
+ x = execute(a[0]); /* Cell* for symbol table */
+ buf[0] = 0;
+ for (np = a[1]; np; np = np->nnext) {
+ y = execute(np); /* subscript */
+ s = getsval(y);
+ if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "array"))
+ FATAL("out of memory for %s[%s...]", x->nval, buf);
+ strcat(buf, s);
+ if (np->nnext)
+ strcat(buf, *SUBSEP);
+ tempfree(y);
+ }
+ if (!isarr(x)) {
+ dprintf( (thread_stdout, "making %s into an array\n", NN(x->nval)) );
+ if (freeable(x))
+ xfree(x->sval);
+ x->tval &= ~(STR|NUM|DONTFREE);
+ x->tval |= ARR;
+ x->sval = (char *) makesymtab(NSYMTAB);
+ }
+ z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);
+ z->ctype = OCELL;
+ z->csub = CVAR;
+ tempfree(x);
+ free(buf);
+ return(z);
+}
+
+Cell *awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
+{
+ Cell *x, *y;
+ Node *np;
+ char *s;
+ int nsub = strlen(*SUBSEP);
+
+ x = execute(a[0]); /* Cell* for symbol table */
+ if (!isarr(x))
+ return True;
+ if (a[1] == 0) { /* delete the elements, not the table */
+ freesymtab(x);
+ x->tval &= ~STR;
+ x->tval |= ARR;
+ x->sval = (char *) makesymtab(NSYMTAB);
+ } else {
+ int bufsz = recsize;
+ char *buf;
+ if ((buf = (char *) malloc(bufsz)) == NULL)
+ FATAL("out of memory in adelete");
+ buf[0] = 0;
+ for (np = a[1]; np; np = np->nnext) {
+ y = execute(np); /* subscript */
+ s = getsval(y);
+ if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "awkdelete"))
+ FATAL("out of memory deleting %s[%s...]", x->nval, buf);
+ strcat(buf, s);
+ if (np->nnext)
+ strcat(buf, *SUBSEP);
+ tempfree(y);
+ }
+ freeelem(x, buf);
+ free(buf);
+ }
+ tempfree(x);
+ return True;
+}
+
+Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */
+{
+ Cell *x, *ap, *k;
+ Node *p;
+ char *buf;
+ char *s;
+ int bufsz = recsize;
+ int nsub = strlen(*SUBSEP);
+
+ ap = execute(a[1]); /* array name */
+ if (!isarr(ap)) {
+ dprintf( (thread_stdout, "making %s into an array\n", ap->nval) );
+ if (freeable(ap))
+ xfree(ap->sval);
+ ap->tval &= ~(STR|NUM|DONTFREE);
+ ap->tval |= ARR;
+ ap->sval = (char *) makesymtab(NSYMTAB);
+ }
+ if ((buf = (char *) malloc(bufsz)) == NULL) {
+ FATAL("out of memory in intest");
+ }
+ buf[0] = 0;
+ for (p = a[0]; p; p = p->nnext) {
+ x = execute(p); /* expr */
+ s = getsval(x);
+ if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "intest"))
+ FATAL("out of memory deleting %s[%s...]", x->nval, buf);
+ strcat(buf, s);
+ tempfree(x);
+ if (p->nnext)
+ strcat(buf, *SUBSEP);
+ }
+ k = lookup(buf, (Array *) ap->sval);
+ tempfree(ap);
+ free(buf);
+ if (k == NULL)
+ return(False);
+ else
+ return(True);
+}
+
+
+Cell *matchop(Node **a, int n) /* ~ and match() */
+{
+ Cell *x, *y;
+ char *s, *t;
+ int i;
+ fa *pfa;
+ int (*mf)(fa *, const char *) = smatch, mode = 0;
+
+ if (n == MATCHFCN) {
+ mf = pmatch;
+ mode = 1;
+ }
+ x = execute(a[1]); /* a[1] = target text */
+ s = getsval(x);
+ if (a[0] == 0) /* a[1] == 0: already-compiled reg expr */
+ i = (*mf)((fa *) a[2], s);
+ else {
+ y = execute(a[2]); /* a[2] = regular expr */
+ t = getsval(y);
+ pfa = makedfa(t, mode);
+ i = (*mf)(pfa, s);
+ tempfree(y);
+ }
+ tempfree(x);
+ if (n == MATCHFCN) {
+ int start = patbeg - s + 1;
+ if (patlen < 0)
+ start = 0;
+ setfval(rstartloc, (Awkfloat) start);
+ setfval(rlengthloc, (Awkfloat) patlen);
+ x = gettemp();
+ x->tval = NUM;
+ x->fval = start;
+ return x;
+ } else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0))
+ return(True);
+ else
+ return(False);
+}
+
+
+Cell *boolop(Node **a, int n) /* a[0] || a[1], a[0] && a[1], !a[0] */
+{
+ Cell *x, *y;
+ int i;
+
+ x = execute(a[0]);
+ i = istrue(x);
+ tempfree(x);
+ switch (n) {
+ case BOR:
+ if (i) return(True);
+ y = execute(a[1]);
+ i = istrue(y);
+ tempfree(y);
+ if (i) return(True);
+ else return(False);
+ case AND:
+ if ( !i ) return(False);
+ y = execute(a[1]);
+ i = istrue(y);
+ tempfree(y);
+ if (i) return(True);
+ else return(False);
+ case NOT:
+ if (i) return(False);
+ else return(True);
+ default: /* can't happen */
+ FATAL("unknown boolean operator %d", n);
+ }
+ return 0; /*NOTREACHED*/
+}
+
+Cell *relop(Node **a, int n) /* a[0 < a[1], etc. */
+{
+ int i;
+ Cell *x, *y;
+ Awkfloat j;
+
+ x = execute(a[0]);
+ y = execute(a[1]);
+ if (x->tval&NUM && y->tval&NUM) {
+ j = x->fval - y->fval;
+ i = j<0? -1: (j>0? 1: 0);
+ } else {
+ i = strcmp(getsval(x), getsval(y));
+ }
+ tempfree(x);
+ tempfree(y);
+ switch (n) {
+ case LT: if (i<0) return(True);
+ else return(False);
+ case LE: if (i<=0) return(True);
+ else return(False);
+ case NE: if (i!=0) return(True);
+ else return(False);
+ case EQ: if (i == 0) return(True);
+ else return(False);
+ case GE: if (i>=0) return(True);
+ else return(False);
+ case GT: if (i>0) return(True);
+ else return(False);
+ default: /* can't happen */
+ FATAL("unknown relational operator %d", n);
+ }
+ return 0; /*NOTREACHED*/
+}
+
+void tfree(Cell *a) /* free a tempcell */
+{
+ if (freeable(a)) {
+ dprintf( (thread_stdout, "freeing %s %s %o\n", NN(a->nval), NN(a->sval), a->tval) );
+ xfree(a->sval);
+ }
+ if (a == tmps)
+ FATAL("tempcell list is curdled");
+ a->cnext = tmps;
+ tmps = a;
+}
+
+Cell *gettemp(void) /* get a tempcell */
+{ int i;
+ Cell *x;
+
+ if (!tmps) {
+ tmps = (Cell *) calloc(100, sizeof(Cell));
+ if (!tmps)
+ FATAL("out of space for temporaries");
+ for(i = 1; i < 100; i++)
+ tmps[i-1].cnext = &tmps[i];
+ tmps[i-1].cnext = 0;
+ }
+ x = tmps;
+ tmps = x->cnext;
+ *x = tempcell;
+ return(x);
+}
+
+Cell *indirect(Node **a, int n) /* $( a[0] ) */
+{
+ Awkfloat val;
+ Cell *x;
+ int m;
+ char *s;
+
+ x = execute(a[0]);
+ val = getfval(x); /* freebsd: defend against super large field numbers */
+ if ((Awkfloat)INT_MAX < val)
+ FATAL("trying to access out of range field %s", x->nval);
+ m = (int) val;
+ if (m == 0 && !is_number(s = getsval(x))) /* suspicion! */
+ FATAL("illegal field $(%s), name \"%s\"", s, x->nval);
+ /* BUG: can x->nval ever be null??? */
+ tempfree(x);
+ x = fieldadr(m);
+ x->ctype = OCELL; /* BUG? why are these needed? */
+ x->csub = CFLD;
+ return(x);
+}
+
+Cell *substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */
+{
+ int k, m, n;
+ char *s;
+ int temp;
+ Cell *x, *y, *z = 0;
+
+ x = execute(a[0]);
+ y = execute(a[1]);
+ if (a[2] != 0)
+ z = execute(a[2]);
+ s = getsval(x);
+ k = strlen(s) + 1;
+ if (k <= 1) {
+ tempfree(x);
+ tempfree(y);
+ if (a[2] != 0) {
+ tempfree(z);
+ }
+ x = gettemp();
+ setsval(x, "");
+ return(x);
+ }
+ m = (int) getfval(y);
+ if (m <= 0)
+ m = 1;
+ else if (m > k)
+ m = k;
+ tempfree(y);
+ if (a[2] != 0) {
+ n = (int) getfval(z);
+ tempfree(z);
+ } else
+ n = k - 1;
+ if (n < 0)
+ n = 0;
+ else if (n > k - m)
+ n = k - m;
+ dprintf( (thread_stdout, "substr: m=%d, n=%d, s=%s\n", m, n, s) );
+ y = gettemp();
+ temp = s[n+m-1]; /* with thanks to John Linderman */
+ s[n+m-1] = '\0';
+ setsval(y, s + m - 1);
+ s[n+m-1] = temp;
+ tempfree(x);
+ return(y);
+}
+
+Cell *sindex(Node **a, int nnn) /* index(a[0], a[1]) */
+{
+ Cell *x, *y, *z;
+ char *s1, *s2, *p1, *p2, *q;
+ Awkfloat v = 0.0;
+
+ x = execute(a[0]);
+ s1 = getsval(x);
+ y = execute(a[1]);
+ s2 = getsval(y);
+
+ z = gettemp();
+ for (p1 = s1; *p1 != '\0'; p1++) {
+ for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++)
+ ;
+ if (*p2 == '\0') {
+ v = (Awkfloat) (p1 - s1 + 1); /* origin 1 */
+ break;
+ }
+ }
+ tempfree(x);
+ tempfree(y);
+ setfval(z, v);
+ return(z);
+}
+
+#define MAXNUMSIZE 50
+
+int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like conversions */
+{
+ char *fmt;
+ char *p, *t;
+ const char *os;
+ Cell *x;
+ int flag = 0, n;
+ int fmtwd; /* format width */
+ int fmtsz = recsize;
+ char *buf = *pbuf;
+ int bufsize = *pbufsize;
+
+ os = s;
+ p = buf;
+ if ((fmt = (char *) malloc(fmtsz)) == NULL)
+ FATAL("out of memory in format()");
+ while (*s) {
+ adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format1");
+ if (*s != '%') {
+ *p++ = *s++;
+ continue;
+ }
+ if (*(s+1) == '%') {
+ *p++ = '%';
+ s += 2;
+ continue;
+ }
+ /* have to be real careful in case this is a huge number, eg, %100000d */
+ fmtwd = atoi(s+1);
+ if (fmtwd < 0)
+ fmtwd = -fmtwd;
+ adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format2");
+ for (t = fmt; (*t++ = *s) != '\0'; s++) {
+ if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, "format3"))
+ FATAL("format item %.30s... ran format() out of memory", os);
+ if (isalpha((uschar)*s) && *s != 'l' && *s != 'h' && *s != 'L')
+ break; /* the ansi panoply */
+ if (*s == '*') {
+ x = execute(a);
+ a = a->nnext;
+ sprintf(t-1, "%d", fmtwd=(int) getfval(x));
+ if (fmtwd < 0)
+ fmtwd = -fmtwd;
+ adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
+ t = fmt + strlen(fmt);
+ tempfree(x);
+ }
+ }
+ *t = '\0';
+ if (fmtwd < 0)
+ fmtwd = -fmtwd;
+ adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format4");
+
+ switch (*s) {
+ case 'f': case 'e': case 'g': case 'E': case 'G':
+ flag = 'f';
+ break;
+ case 'd': case 'i':
+ flag = 'd';
+ if(*(s-1) == 'l') break;
+ *(t-1) = 'l';
+ *t = 'd';
+ *++t = '\0';
+ break;
+ case 'o': case 'x': case 'X': case 'u':
+ flag = *(s-1) == 'l' ? 'd' : 'u';
+ break;
+ case 's':
+ flag = 's';
+ break;
+ case 'c':
+ flag = 'c';
+ break;
+ default:
+ WARNING("weird printf conversion %s", fmt);
+ flag = '?';
+ break;
+ }
+ if (a == NULL)
+ FATAL("not enough args in printf(%s)", os);
+ x = execute(a);
+ a = a->nnext;
+ n = MAXNUMSIZE;
+ if (fmtwd > n)
+ n = fmtwd;
+ adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format5");
+ switch (flag) {
+ case '?': sprintf(p, "%s", fmt); /* unknown, so dump it too */
+ t = getsval(x);
+ n = strlen(t);
+ if (fmtwd > n)
+ n = fmtwd;
+ adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format6");
+ p += strlen(p);
+ sprintf(p, "%s", t);
+ break;
+ case 'f': sprintf(p, fmt, getfval(x)); break;
+ case 'd': sprintf(p, fmt, (long) getfval(x)); break;
+ case 'u': sprintf(p, fmt, (unsigned int) getfval(x)); break;
+ case 's':
+ t = getsval(x);
+ n = strlen(t);
+ if (fmtwd > n)
+ n = fmtwd;
+ if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format7"))
+ FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t);
+ sprintf(p, fmt, t);
+ break;
+ case 'c':
+ if (isnum(x)) {
+ if (getfval(x))
+ sprintf(p, fmt, (int) getfval(x));
+ else {
+ *p++ = '\0'; /* explicit null byte */
+ *p = '\0'; /* next output will start here */
+ }
+ } else
+ sprintf(p, fmt, getsval(x)[0]);
+ break;
+ default:
+ FATAL("can't happen: bad conversion %c in format()", flag);
+ }
+ tempfree(x);
+ p += strlen(p);
+ s++;
+ }
+ *p = '\0';
+ free(fmt);
+ for ( ; a; a = a->nnext) /* evaluate any remaining args */
+ execute(a);
+ *pbuf = buf;
+ *pbufsize = bufsize;
+ return p - buf;
+}
+
+// Moved function so it is static:
+struct files {
+ FILE *fp;
+ const char *fname;
+ int mode; /* '|', 'a', 'w' => LE/LT, GT */
+} files[FOPEN_MAX] ={
+ { NULL, "/dev/stdin", LT }, /* watch out: don't free this! */
+ { NULL, "/dev/stdout", GT },
+ { NULL, "/dev/stderr", GT }
+};
+
+void stdinit(void) /* in case stdin, etc., are not constants */
+{
+ files[0].fp = thread_stdin;
+ files[1].fp = thread_stdout;
+ files[2].fp = thread_stderr;
+}
+
+static const char *filename(FILE *fp)
+{
+ int i;
+
+ for (i = 0; i < FOPEN_MAX; i++)
+ if (fp == files[i].fp)
+ return files[i].fname;
+ return "???";
+}
+
+Cell *awksprintf(Node **a, int n) /* sprintf(a[0]) */
+{
+ Cell *x;
+ Node *y;
+ char *buf;
+ int bufsz=3*recsize;
+
+ if ((buf = (char *) malloc(bufsz)) == NULL)
+ FATAL("out of memory in awksprintf");
+ y = a[0]->nnext;
+ x = execute(a[0]);
+ if (format(&buf, &bufsz, getsval(x), y) == -1)
+ FATAL("sprintf string %.30s... too long. can't happen.", buf);
+ tempfree(x);
+ x = gettemp();
+ x->sval = buf;
+ x->tval = STR;
+ return(x);
+}
+
+Cell *awkprintf(Node **a, int n) /* printf */
+{ /* a[0] is list of args, starting with format string */
+ /* a[1] is redirection operator, a[2] is redirection file */
+ FILE *fp;
+ Cell *x;
+ Node *y;
+ char *buf;
+ int len;
+ int bufsz=3*recsize;
+
+ if ((buf = (char *) malloc(bufsz)) == NULL)
+ FATAL("out of memory in awkprintf");
+ y = a[0]->nnext;
+ x = execute(a[0]);
+ if ((len = format(&buf, &bufsz, getsval(x), y)) == -1)
+ FATAL("printf string %.30s... too long. can't happen.", buf);
+ tempfree(x);
+ if (a[1] == NULL) {
+ /* fputs(buf, stdout); */
+ fwrite(buf, len, 1, thread_stdout);
+ if (ferror(thread_stdout))
+ FATAL("write error on stdout");
+ } else {
+ fp = redirect(ptoi(a[1]), a[2]);
+ /* fputs(buf, fp); */
+ fwrite(buf, len, 1, fp);
+ fflush(fp);
+ if (ferror(fp))
+ FATAL("write error on %s", filename(fp));
+ }
+ free(buf);
+ return(True);
+}
+
+Cell *arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */
+{
+ Awkfloat i, j = 0;
+ double v;
+ Cell *x, *y, *z;
+
+ x = execute(a[0]);
+ i = getfval(x);
+ tempfree(x);
+ if (n != UMINUS && n != UPLUS) {
+ y = execute(a[1]);
+ j = getfval(y);
+ tempfree(y);
+ }
+ z = gettemp();
+ switch (n) {
+ case ADD:
+ i += j;
+ break;
+ case MINUS:
+ i -= j;
+ break;
+ case MULT:
+ i *= j;
+ break;
+ case DIVIDE:
+ if (j == 0)
+ FATAL("division by zero");
+ i /= j;
+ break;
+ case MOD:
+ if (j == 0)
+ FATAL("division by zero in mod");
+ modf(i/j, &v);
+ i = i - j * v;
+ break;
+ case UMINUS:
+ i = -i;
+ break;
+ case UPLUS:
+ i = i;
+ break;
+ case POWER:
+ if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */
+ i = ipow(i, (int) j);
+ else
+ i = errcheck(pow(i, j), "pow");
+ break;
+ default: /* can't happen */
+ FATAL("illegal arithmetic operator %d", n);
+ }
+ setfval(z, i);
+ return(z);
+}
+
+double ipow(double x, int n) /* x**n. ought to be done by pow, but isn't always */
+{
+ double v;
+
+ if (n <= 0)
+ return 1;
+ v = ipow(x, n/2);
+ if (n % 2 == 0)
+ return v * v;
+ else
+ return x * v * v;
+}
+
+Cell *incrdecr(Node **a, int n) /* a[0]++, etc. */
+{
+ Cell *x, *z;
+ int k;
+ Awkfloat xf;
+
+ x = execute(a[0]);
+ xf = getfval(x);
+ k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
+ if (n == PREINCR || n == PREDECR) {
+ setfval(x, xf + k);
+ return(x);
+ }
+ z = gettemp();
+ setfval(z, xf);
+ setfval(x, xf + k);
+ tempfree(x);
+ return(z);
+}
+
+Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */
+{ /* this is subtle; don't muck with it. */
+ Cell *x, *y;
+ Awkfloat xf, yf;
+ double v;
+
+ y = execute(a[1]);
+ x = execute(a[0]);
+ if (n == ASSIGN) { /* ordinary assignment */
+ if (x == y && !(x->tval & (FLD|REC))) /* self-assignment: */
+ ; /* leave alone unless it's a field */
+ else if ((y->tval & (STR|NUM)) == (STR|NUM)) {
+ setsval(x, getsval(y));
+ x->fval = getfval(y);
+ x->tval |= NUM;
+ }
+ else if (isstr(y))
+ setsval(x, getsval(y));
+ else if (isnum(y))
+ setfval(x, getfval(y));
+ else
+ funnyvar(y, "read value of");
+ tempfree(y);
+ return(x);
+ }
+ xf = getfval(x);
+ yf = getfval(y);
+ switch (n) {
+ case ADDEQ:
+ xf += yf;
+ break;
+ case SUBEQ:
+ xf -= yf;
+ break;
+ case MULTEQ:
+ xf *= yf;
+ break;
+ case DIVEQ:
+ if (yf == 0)
+ FATAL("division by zero in /=");
+ xf /= yf;
+ break;
+ case MODEQ:
+ if (yf == 0)
+ FATAL("division by zero in %%=");
+ modf(xf/yf, &v);
+ xf = xf - yf * v;
+ break;
+ case POWEQ:
+ if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */
+ xf = ipow(xf, (int) yf);
+ else
+ xf = errcheck(pow(xf, yf), "pow");
+ break;
+ default:
+ FATAL("illegal assignment operator %d", n);
+ break;
+ }
+ tempfree(y);
+ setfval(x, xf);
+ return(x);
+}
+
+Cell *cat(Node **a, int q) /* a[0] cat a[1] */
+{
+ Cell *x, *y, *z;
+ int n1, n2;
+ char *s;
+
+ x = execute(a[0]);
+ y = execute(a[1]);
+ getsval(x);
+ getsval(y);
+ n1 = strlen(x->sval);
+ n2 = strlen(y->sval);
+ s = (char *) malloc(n1 + n2 + 1);
+ if (s == NULL)
+ FATAL("out of space concatenating %.15s... and %.15s...",
+ x->sval, y->sval);
+ strcpy(s, x->sval);
+ strcpy(s+n1, y->sval);
+ tempfree(y);
+ z = gettemp();
+ z->sval = s;
+ z->tval = STR;
+ tempfree(x);
+ return(z);
+}
+
+Cell *pastat(Node **a, int n) /* a[0] { a[1] } */
+{
+ Cell *x;
+
+ if (a[0] == 0)
+ x = execute(a[1]);
+ else {
+ x = execute(a[0]);
+ if (istrue(x)) {
+ tempfree(x);
+ x = execute(a[1]);
+ }
+ }
+ return x;
+}
+
+Cell *dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */
+{
+ Cell *x;
+ int pair;
+
+ pair = ptoi(a[3]);
+ if (pairstack[pair] == 0) {
+ x = execute(a[0]);
+ if (istrue(x))
+ pairstack[pair] = 1;
+ tempfree(x);
+ }
+ if (pairstack[pair] == 1) {
+ x = execute(a[1]);
+ if (istrue(x))
+ pairstack[pair] = 0;
+ tempfree(x);
+ x = execute(a[2]);
+ return(x);
+ }
+ return(False);
+}
+
+Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
+{
+ Cell *x = 0, *y, *ap;
+ char *s;
+ int sep;
+ char *t, temp, num[50], *fs = 0;
+ int n, tempstat, arg3type;
+
+ y = execute(a[0]); /* source string */
+ s = getsval(y);
+ arg3type = ptoi(a[3]);
+ if (a[2] == 0) /* fs string */
+ fs = *FS;
+ else if (arg3type == STRING) { /* split(str,arr,"string") */
+ x = execute(a[2]);
+ fs = getsval(x);
+ } else if (arg3type == REGEXPR)
+ fs = "(regexpr)"; /* split(str,arr,/regexpr/) */
+ else
+ FATAL("illegal type of split");
+ sep = *fs;
+ ap = execute(a[1]); /* array name */
+ freesymtab(ap);
+ dprintf( (thread_stdout, "split: s=|%s|, a=%s, sep=|%s|\n", s, NN(ap->nval), fs) );
+ ap->tval &= ~STR;
+ ap->tval |= ARR;
+ ap->sval = (char *) makesymtab(NSYMTAB);
+
+ n = 0;
+ if (*s != '\0' && (strlen(fs) > 1 || arg3type == REGEXPR)) { /* reg expr */
+ fa *pfa;
+ if (arg3type == REGEXPR) { /* it's ready already */
+ pfa = (fa *) a[2];
+ } else {
+ pfa = makedfa(fs, 1);
+ }
+ if (nematch(pfa,s)) {
+ tempstat = pfa->initstat;
+ pfa->initstat = 2;
+ do {
+ n++;
+ sprintf(num, "%d", n);
+ temp = *patbeg;
+ *patbeg = '\0';
+ if (is_number(s))
+ setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
+ else
+ setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
+ *patbeg = temp;
+ s = patbeg + patlen;
+ if (*(patbeg+patlen-1) == 0 || *s == 0) {
+ n++;
+ sprintf(num, "%d", n);
+ setsymtab(num, "", 0.0, STR, (Array *) ap->sval);
+ pfa->initstat = tempstat;
+ goto spdone;
+ }
+ } while (nematch(pfa,s));
+ pfa->initstat = tempstat; /* bwk: has to be here to reset */
+ /* cf gsub and refldbld */
+ }
+ n++;
+ sprintf(num, "%d", n);
+ if (is_number(s))
+ setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
+ else
+ setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
+ spdone:
+ pfa = NULL;
+ } else if (sep == ' ') {
+ for (n = 0; ; ) {
+ while (*s == ' ' || *s == '\t' || *s == '\n')
+ s++;
+ if (*s == 0)
+ break;
+ n++;
+ t = s;
+ do
+ s++;
+ while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0');
+ temp = *s;
+ *s = '\0';
+ sprintf(num, "%d", n);
+ if (is_number(t))
+ setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
+ else
+ setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
+ *s = temp;
+ if (*s != 0)
+ s++;
+ }
+ } else if (sep == 0) { /* new: split(s, a, "") => 1 char/elem */
+ for (n = 0; *s != 0; s++) {
+ char buf[2];
+ n++;
+ sprintf(num, "%d", n);
+ buf[0] = *s;
+ buf[1] = 0;
+ if (isdigit((uschar)buf[0]))
+ setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval);
+ else
+ setsymtab(num, buf, 0.0, STR, (Array *) ap->sval);
+ }
+ } else if (*s != 0) {
+ for (;;) {
+ n++;
+ t = s;
+ while (*s != sep && *s != '\n' && *s != '\0')
+ s++;
+ temp = *s;
+ *s = '\0';
+ sprintf(num, "%d", n);
+ if (is_number(t))
+ setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
+ else
+ setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
+ *s = temp;
+ if (*s++ == 0)
+ break;
+ }
+ }
+ tempfree(ap);
+ tempfree(y);
+ if (a[2] != 0 && arg3type == STRING) {
+ tempfree(x);
+ }
+ x = gettemp();
+ x->tval = NUM;
+ x->fval = n;
+ return(x);
+}
+
+Cell *condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */
+{
+ Cell *x;
+
+ x = execute(a[0]);
+ if (istrue(x)) {
+ tempfree(x);
+ x = execute(a[1]);
+ } else {
+ tempfree(x);
+ x = execute(a[2]);
+ }
+ return(x);
+}
+
+Cell *ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */
+{
+ Cell *x;
+
+ x = execute(a[0]);
+ if (istrue(x)) {
+ tempfree(x);
+ x = execute(a[1]);
+ } else if (a[2] != 0) {
+ tempfree(x);
+ x = execute(a[2]);
+ }
+ return(x);
+}
+
+Cell *whilestat(Node **a, int n) /* while (a[0]) a[1] */
+{
+ Cell *x;
+
+ for (;;) {
+ x = execute(a[0]);
+ if (!istrue(x))
+ return(x);
+ tempfree(x);
+ x = execute(a[1]);
+ if (isbreak(x)) {
+ x = True;
+ return(x);
+ }
+ if (isnext(x) || isexit(x) || isret(x))
+ return(x);
+ tempfree(x);
+ }
+}
+
+Cell *dostat(Node **a, int n) /* do a[0]; while(a[1]) */
+{
+ Cell *x;
+
+ for (;;) {
+ x = execute(a[0]);
+ if (isbreak(x))
+ return True;
+ if (isnext(x) || isexit(x) || isret(x))
+ return(x);
+ tempfree(x);
+ x = execute(a[1]);
+ if (!istrue(x))
+ return(x);
+ tempfree(x);
+ }
+}
+
+Cell *forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */
+{
+ Cell *x;
+
+ x = execute(a[0]);
+ tempfree(x);
+ for (;;) {
+ if (a[1]!=0) {
+ x = execute(a[1]);
+ if (!istrue(x)) return(x);
+ else tempfree(x);
+ }
+ x = execute(a[3]);
+ if (isbreak(x)) /* turn off break */
+ return True;
+ if (isnext(x) || isexit(x) || isret(x))
+ return(x);
+ tempfree(x);
+ x = execute(a[2]);
+ tempfree(x);
+ }
+}
+
+Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */
+{
+ Cell *x, *vp, *arrayp, *cp, *ncp;
+ Array *tp;
+ int i;
+
+ vp = execute(a[0]);
+ arrayp = execute(a[1]);
+ if (!isarr(arrayp)) {
+ return True;
+ }
+ tp = (Array *) arrayp->sval;
+ tempfree(arrayp);
+ for (i = 0; i < tp->size; i++) { /* this routine knows too much */
+ for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
+ setsval(vp, cp->nval);
+ ncp = cp->cnext;
+ x = execute(a[2]);
+ if (isbreak(x)) {
+ tempfree(vp);
+ return True;
+ }
+ if (isnext(x) || isexit(x) || isret(x)) {
+ tempfree(vp);
+ return(x);
+ }
+ tempfree(x);
+ }
+ }
+ return True;
+}
+
+Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */
+{
+ Cell *x, *y;
+ Awkfloat u;
+ int t;
+ char *p, *buf;
+ Node *nextarg;
+ FILE *fp;
+ void flush_all(void);
+
+ t = ptoi(a[0]);
+ x = execute(a[1]);
+ nextarg = a[1]->nnext;
+ switch (t) {
+ case FLENGTH:
+ if (isarr(x))
+ u = ((Array *) x->sval)->nelem; /* GROT. should be function*/
+ else
+ u = strlen(getsval(x));
+ break;
+ case FLOG:
+ u = errcheck(log(getfval(x)), "log"); break;
+ case FINT:
+ modf(getfval(x), &u); break;
+ case FEXP:
+ u = errcheck(exp(getfval(x)), "exp"); break;
+ case FSQRT:
+ u = errcheck(sqrt(getfval(x)), "sqrt"); break;
+ case FSIN:
+ u = sin(getfval(x)); break;
+ case FCOS:
+ u = cos(getfval(x)); break;
+ case FATAN:
+ if (nextarg == 0) {
+ WARNING("atan2 requires two arguments; returning 1.0");
+ u = 1.0;
+ } else {
+ y = execute(a[1]->nnext);
+ u = atan2(getfval(x), getfval(y));
+ tempfree(y);
+ nextarg = nextarg->nnext;
+ }
+ break;
+ case FSYSTEM:
+ fflush(thread_stdout); /* in case something is buffered already */
+ u = (Awkfloat) ios_system(getsval(x)) / 256; /* 256 is unix-dep */
+ break;
+ case FRAND:
+ /* in principle, rand() returns something in 0..RAND_MAX */
+ u = (Awkfloat) (random() % RAND_MAX) / RAND_MAX;
+ break;
+ case FSRAND:
+ if (isrec(x)) /* no argument provided */
+ u = time((time_t *)0);
+ else
+ u = getfval(x);
+ srandom((unsigned int) u);
+ tmp_srand = u;
+ u = prev_srand; /* return the previous value */
+ prev_srand = tmp_srand; /* remember for next time */
+ break;
+ case FTOUPPER:
+ case FTOLOWER:
+ buf = tostring(getsval(x));
+ if (t == FTOUPPER) {
+ for (p = buf; *p; p++)
+ if (islower((uschar) *p))
+ *p = toupper((uschar)*p);
+ } else {
+ for (p = buf; *p; p++)
+ if (isupper((uschar) *p))
+ *p = tolower((uschar)*p);
+ }
+ tempfree(x);
+ x = gettemp();
+ setsval(x, buf);
+ free(buf);
+ return x;
+ case FFLUSH:
+ if (isrec(x) || strlen(getsval(x)) == 0) {
+ flush_all(); /* fflush() or fflush("") -> all */
+ u = 0;
+ } else if ((fp = openfile(FFLUSH, getsval(x))) == NULL)
+ u = EOF;
+ else
+ u = fflush(fp);
+ break;
+ default: /* can't happen */
+ FATAL("illegal function type %d", t);
+ break;
+ }
+ tempfree(x);
+ x = gettemp();
+ setfval(x, u);
+ if (nextarg != 0) {
+ WARNING("warning: function has too many arguments");
+ for ( ; nextarg; nextarg = nextarg->nnext)
+ execute(nextarg);
+ }
+ return(x);
+}
+
+Cell *printstat(Node **a, int n) /* print a[0] */
+{
+ Node *x;
+ Cell *y;
+ FILE *fp;
+
+ if (a[1] == 0) /* a[1] is redirection operator, a[2] is file */
+ fp = thread_stdout;
+ else
+ fp = redirect(ptoi(a[1]), a[2]);
+ for (x = a[0]; x != NULL; x = x->nnext) {
+ y = execute(x);
+ fputs(getpssval(y), fp);
+ tempfree(y);
+ if (x->nnext == NULL)
+ fputs(*ORS, fp);
+ else
+ fputs(*OFS, fp);
+ }
+ if (a[1] != 0)
+ fflush(fp);
+ if (ferror(fp))
+ FATAL("write error on %s", filename(fp));
+ return(True);
+}
+
+Cell *nullproc(Node **a, int n)
+{
+ n = n;
+ a = a;
+ return 0;
+}
+
+
+FILE *redirect(int a, Node *b) /* set up all i/o redirections */
+{
+ FILE *fp;
+ Cell *x;
+ char *fname;
+
+ x = execute(b);
+ fname = getsval(x);
+ fp = openfile(a, fname);
+ if (fp == NULL)
+ FATAL("can't open file %s", fname);
+ tempfree(x);
+ return fp;
+}
+
+
+FILE *openfile(int a, const char *us)
+{
+ const char *s = us;
+ int i, m;
+ FILE *fp = 0;
+
+ if (*s == '\0')
+ FATAL("null file name in print or getline");
+ for (i=0; i < FOPEN_MAX; i++)
+ if (files[i].fname && strcmp(s, files[i].fname) == 0) {
+ if (a == files[i].mode || (a==APPEND && files[i].mode==GT))
+ return files[i].fp;
+ if (a == FFLUSH)
+ return files[i].fp;
+ }
+ if (a == FFLUSH) /* didn't find it, so don't create it! */
+ return NULL;
+
+ for (i=0; i < FOPEN_MAX; i++)
+ if (files[i].fp == 0)
+ break;
+ if (i >= FOPEN_MAX)
+ FATAL("%s makes too many open files", s);
+ fflush(thread_stdout); /* force a semblance of order */
+ m = a;
+ if (a == GT) {
+ fp = fopen(s, "w");
+ } else if (a == APPEND) {
+ fp = fopen(s, "a");
+ m = GT; /* so can mix > and >> */
+ } else if (a == '|') { /* output pipe */
+ fp = popen(s, "w");
+ } else if (a == LE) { /* input pipe */
+ fp = popen(s, "r");
+ } else if (a == LT) { /* getline sval, files[i].fname) == 0) {
+ if (ferror(files[i].fp))
+ WARNING( "i/o error occurred on %s", files[i].fname );
+ if (files[i].mode == '|' || files[i].mode == LE)
+ stat = pclose(files[i].fp);
+ else {
+ stat = fclose(files[i].fp);
+ files[i].fp = 0;
+ }
+ if (stat == EOF)
+ WARNING( "i/o error occurred closing %s", files[i].fname );
+ if (i > 2) /* don't do /dev/std... */
+ xfree(files[i].fname);
+ files[i].fname = NULL; /* watch out for ref thru this */
+ files[i].fp = NULL;
+ }
+ }
+ tempfree(x);
+ x = gettemp();
+ setfval(x, (Awkfloat) stat);
+ return(x);
+}
+
+void closeall(void)
+{
+ int i, stat;
+
+ for (i = 0; i < FOPEN_MAX; i++) {
+ if (files[i].fp) {
+ // Do not close stdin or the others
+ if (files[i].fp == thread_stdin) continue;
+ if (files[i].fp == thread_stdout) continue;
+ if (files[i].fp == thread_stderr) continue;
+ if (ferror(files[i].fp))
+ WARNING( "i/o error occurred on %s", files[i].fname );
+ if (files[i].mode == '|' || files[i].mode == LE)
+ stat = pclose(files[i].fp);
+ else {
+ stat = fclose(files[i].fp);
+ files[i].fp = 0;
+ }
+ if (stat == EOF)
+ WARNING( "i/o error occurred while closing %s", files[i].fname );
+ }
+ }
+}
+
+void flush_all(void)
+{
+ int i;
+
+ for (i = 0; i < FOPEN_MAX; i++)
+ if (files[i].fp)
+ fflush(files[i].fp);
+}
+
+void backsub(char **pb_ptr, char **sptr_ptr);
+
+Cell *sub(Node **a, int nnn) /* substitute command */
+{
+ char *sptr, *pb, *q;
+ Cell *x, *y, *result;
+ char *t, *buf;
+ fa *pfa;
+ int bufsz = recsize;
+
+ if ((buf = (char *) malloc(bufsz)) == NULL)
+ FATAL("out of memory in sub");
+ x = execute(a[3]); /* target string */
+ t = getsval(x);
+ if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */
+ pfa = (fa *) a[1]; /* regular expression */
+ else {
+ y = execute(a[1]);
+ pfa = makedfa(getsval(y), 1);
+ tempfree(y);
+ }
+ y = execute(a[2]); /* replacement string */
+ result = False;
+ if (pmatch(pfa, t)) {
+ sptr = t;
+ adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub");
+ pb = buf;
+ while (sptr < patbeg)
+ *pb++ = *sptr++;
+ sptr = getsval(y);
+ while (*sptr != 0) {
+ adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub");
+ if (*sptr == '\\') {
+ backsub(&pb, &sptr);
+ } else if (*sptr == '&') {
+ sptr++;
+ adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub");
+ for (q = patbeg; q < patbeg+patlen; )
+ *pb++ = *q++;
+ } else
+ *pb++ = *sptr++;
+ }
+ *pb = '\0';
+ if (pb > buf + bufsz)
+ FATAL("sub result1 %.30s too big; can't happen", buf);
+ sptr = patbeg + patlen;
+ if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) {
+ adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub");
+ while ((*pb++ = *sptr++) != 0)
+ ;
+ }
+ if (pb > buf + bufsz)
+ FATAL("sub result2 %.30s too big; can't happen", buf);
+ setsval(x, buf); /* BUG: should be able to avoid copy */
+ result = True;;
+ }
+ tempfree(x);
+ tempfree(y);
+ free(buf);
+ return result;
+}
+
+Cell *gsub(Node **a, int nnn) /* global substitute */
+{
+ Cell *x, *y;
+ char *rptr, *sptr, *t, *pb, *q;
+ char *buf;
+ fa *pfa;
+ int mflag, tempstat, num;
+ int bufsz = recsize;
+
+ if ((buf = (char *) malloc(bufsz)) == NULL)
+ FATAL("out of memory in gsub");
+ mflag = 0; /* if mflag == 0, can replace empty string */
+ num = 0;
+ x = execute(a[3]); /* target string */
+ t = getsval(x);
+ if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */
+ pfa = (fa *) a[1]; /* regular expression */
+ else {
+ y = execute(a[1]);
+ pfa = makedfa(getsval(y), 1);
+ tempfree(y);
+ }
+ y = execute(a[2]); /* replacement string */
+ if (pmatch(pfa, t)) {
+ tempstat = pfa->initstat;
+ pfa->initstat = 2;
+ pb = buf;
+ rptr = getsval(y);
+ do {
+ if (patlen == 0 && *patbeg != 0) { /* matched empty string */
+ if (mflag == 0) { /* can replace empty */
+ num++;
+ sptr = rptr;
+ while (*sptr != 0) {
+ adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
+ if (*sptr == '\\') {
+ backsub(&pb, &sptr);
+ } else if (*sptr == '&') {
+ sptr++;
+ adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
+ for (q = patbeg; q < patbeg+patlen; )
+ *pb++ = *q++;
+ } else
+ *pb++ = *sptr++;
+ }
+ }
+ if (*t == 0) /* at end */
+ goto done;
+ adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub");
+ *pb++ = *t++;
+ if (pb > buf + bufsz) /* BUG: not sure of this test */
+ FATAL("gsub result0 %.30s too big; can't happen", buf);
+ mflag = 0;
+ }
+ else { /* matched nonempty string */
+ num++;
+ sptr = t;
+ adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub");
+ while (sptr < patbeg)
+ *pb++ = *sptr++;
+ sptr = rptr;
+ while (*sptr != 0) {
+ adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
+ if (*sptr == '\\') {
+ backsub(&pb, &sptr);
+ } else if (*sptr == '&') {
+ sptr++;
+ adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
+ for (q = patbeg; q < patbeg+patlen; )
+ *pb++ = *q++;
+ } else
+ *pb++ = *sptr++;
+ }
+ t = patbeg + patlen;
+ if (patlen == 0 || *t == 0 || *(t-1) == 0)
+ goto done;
+ if (pb > buf + bufsz)
+ FATAL("gsub result1 %.30s too big; can't happen", buf);
+ mflag = 1;
+ }
+ } while (pmatch(pfa,t));
+ sptr = t;
+ adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub");
+ while ((*pb++ = *sptr++) != 0)
+ ;
+ done: if (pb > buf + bufsz)
+ FATAL("gsub result2 %.30s too big; can't happen", buf);
+ *pb = '\0';
+ setsval(x, buf); /* BUG: should be able to avoid copy + free */
+ pfa->initstat = tempstat;
+ }
+ tempfree(x);
+ tempfree(y);
+ x = gettemp();
+ x->tval = NUM;
+ x->fval = num;
+ free(buf);
+ return(x);
+}
+
+void backsub(char **pb_ptr, char **sptr_ptr) /* handle \\& variations */
+{ /* sptr[0] == '\\' */
+ char *pb = *pb_ptr, *sptr = *sptr_ptr;
+
+ if (sptr[1] == '\\') {
+ if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */
+ *pb++ = '\\';
+ *pb++ = '&';
+ sptr += 4;
+ } else if (sptr[2] == '&') { /* \\& -> \ + matched */
+ *pb++ = '\\';
+ sptr += 2;
+ } else { /* \\x -> \\x */
+ *pb++ = *sptr++;
+ *pb++ = *sptr++;
+ }
+ } else if (sptr[1] == '&') { /* literal & */
+ sptr++;
+ *pb++ = *sptr++;
+ } else /* literal \ */
+ *pb++ = *sptr++;
+
+ *pb_ptr = pb;
+ *sptr_ptr = sptr;
+}
diff --git a/awk/Sources/awk/tran.c b/awk/Sources/awk/tran.c
new file mode 100644
index 00000000..af9b9b46
--- /dev/null
+++ b/awk/Sources/awk/tran.c
@@ -0,0 +1,467 @@
+/****************************************************************
+Copyright (C) Lucent Technologies 1997
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name Lucent Technologies or any of
+its entities not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+****************************************************************/
+
+#define DEBUG
+#include
+#include
+#include
+#include
+#include
+#include "awk.h"
+#include "ytab.h"
+#include "ios_error.h"
+
+#define FULLTAB 2 /* rehash when table gets this x full */
+#define GROWTAB 4 /* grow table by this factor */
+
+__thread Array *symtab; /* main symbol table */
+
+__thread char **FS; /* initial field sep */
+__thread char **RS; /* initial record sep */
+__thread char **OFS; /* output field sep */
+__thread char **ORS; /* output record sep */
+__thread char **OFMT; /* output format for numbers */
+static __thread char **CONVFMT; /* format for conversions in getsval */
+__thread Awkfloat *NF; /* number of fields in current record */
+__thread Awkfloat *NR; /* number of current record */
+__thread Awkfloat *FNR; /* number of current record in current file */
+__thread char **FILENAME; /* current filename argument */
+__thread Awkfloat *ARGC; /* number of arguments from command line */
+__thread char **SUBSEP; /* subscript separator for a[i,j,k]; default \034 */
+__thread Awkfloat *RSTART; /* start of re matched with ~; origin 1 (!) */
+__thread Awkfloat *RLENGTH; /* length of same */
+
+static __thread Cell *fsloc; /* FS */
+__thread Cell *nrloc; /* NR */
+__thread Cell *nfloc; /* NF */
+__thread Cell *fnrloc; /* FNR */
+__thread Array *ARGVtab; /* symbol table containing ARGV[...] */
+static __thread Array *ENVtab; /* symbol table containing ENVIRON[...] */
+__thread Cell *rstartloc; /* RSTART */
+__thread Cell *rlengthloc; /* RLENGTH */
+static __thread Cell *symtabloc; /* SYMTAB */
+
+static __thread Cell *nullloc; /* a guaranteed empty cell */
+__thread Node *nullnode; /* zero&null, converted into a node for comparisons */
+__thread Cell *literal0;
+
+extern __thread Cell **fldtab;
+
+void syminit(void) /* initialize symbol table with builtin vars */
+{
+ literal0 = setsymtab("0", "0", 0.0, NUM|STR|CON|DONTFREE, symtab);
+ /* this is used for if(x)... tests: */
+ nullloc = setsymtab("$zero&null", "", 0.0, NUM|STR|CON|DONTFREE, symtab);
+ nullnode = celltonode(nullloc, CCON);
+
+ fsloc = setsymtab("FS", " ", 0.0, STR|DONTFREE, symtab);
+ FS = &fsloc->sval;
+ RS = &setsymtab("RS", "\n", 0.0, STR|DONTFREE, symtab)->sval;
+ OFS = &setsymtab("OFS", " ", 0.0, STR|DONTFREE, symtab)->sval;
+ ORS = &setsymtab("ORS", "\n", 0.0, STR|DONTFREE, symtab)->sval;
+ OFMT = &setsymtab("OFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval;
+ CONVFMT = &setsymtab("CONVFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval;
+ FILENAME = &setsymtab("FILENAME", "", 0.0, STR|DONTFREE, symtab)->sval;
+ nfloc = setsymtab("NF", "", 0.0, NUM, symtab);
+ NF = &nfloc->fval;
+ nrloc = setsymtab("NR", "", 0.0, NUM, symtab);
+ NR = &nrloc->fval;
+ fnrloc = setsymtab("FNR", "", 0.0, NUM, symtab);
+ FNR = &fnrloc->fval;
+ SUBSEP = &setsymtab("SUBSEP", "\034", 0.0, STR|DONTFREE, symtab)->sval;
+ rstartloc = setsymtab("RSTART", "", 0.0, NUM, symtab);
+ RSTART = &rstartloc->fval;
+ rlengthloc = setsymtab("RLENGTH", "", 0.0, NUM, symtab);
+ RLENGTH = &rlengthloc->fval;
+ symtabloc = setsymtab("SYMTAB", "", 0.0, ARR, symtab);
+ symtabloc->sval = (char *) symtab;
+}
+
+void arginit(int ac, char **av) /* set up ARGV and ARGC */
+{
+ Cell *cp;
+ int i;
+ char temp[50];
+
+ ARGC = &setsymtab("ARGC", "", (Awkfloat) ac, NUM, symtab)->fval;
+ cp = setsymtab("ARGV", "", 0.0, ARR, symtab);
+ ARGVtab = makesymtab(NSYMTAB); /* could be (int) ARGC as well */
+ cp->sval = (char *) ARGVtab;
+ for (i = 0; i < ac; i++) {
+ sprintf(temp, "%d", i);
+ if (is_number(*av))
+ setsymtab(temp, *av, atof(*av), STR|NUM, ARGVtab);
+ else
+ setsymtab(temp, *av, 0.0, STR, ARGVtab);
+ av++;
+ }
+}
+
+void envinit(char **envp) /* set up ENVIRON variable */
+{
+ Cell *cp;
+ char *p;
+
+ cp = setsymtab("ENVIRON", "", 0.0, ARR, symtab);
+ ENVtab = makesymtab(NSYMTAB);
+ cp->sval = (char *) ENVtab;
+ for ( ; *envp; envp++) {
+ if ((p = strchr(*envp, '=')) == NULL)
+ continue;
+ if( p == *envp ) /* no left hand side name in env string */
+ continue;
+ *p++ = 0; /* split into two strings at = */
+ if (is_number(p))
+ setsymtab(*envp, p, atof(p), STR|NUM, ENVtab);
+ else
+ setsymtab(*envp, p, 0.0, STR, ENVtab);
+ p[-1] = '='; /* restore in case env is passed down to a shell */
+ }
+}
+
+Array *makesymtab(int n) /* make a new symbol table */
+{
+ Array *ap;
+ Cell **tp;
+
+ ap = (Array *) calloc(1, sizeof(Array));
+ tp = (Cell **) calloc(n, sizeof(Cell *));
+ if (ap == NULL || tp == NULL)
+ FATAL("out of space in makesymtab");
+
+ ap->nelem = 0;
+ ap->size = n;
+ ap->tab = tp;
+ return(ap);
+}
+
+void freesymtab(Cell *ap) /* free a symbol table */
+{
+ Cell *cp, *temp;
+ Array *tp;
+ int i;
+
+ if (!isarr(ap))
+ return;
+ tp = (Array *) ap->sval;
+ if (tp == NULL)
+ return;
+ for (i = 0; i < tp->size; i++) {
+ for (cp = tp->tab[i]; cp != NULL; cp = temp) {
+ xfree(cp->nval);
+ if (freeable(cp))
+ xfree(cp->sval);
+ temp = cp->cnext; /* avoids freeing then using */
+ free(cp);
+ tp->nelem--;
+ }
+ tp->tab[i] = 0;
+ }
+ if (tp->nelem != 0)
+ WARNING("can't happen: inconsistent element count freeing %s", ap->nval);
+ free(tp->tab);
+ free(tp);
+}
+
+void freeelem(Cell *ap, const char *s) /* free elem s from ap (i.e., ap["s"] */
+{
+ Array *tp;
+ Cell *p, *prev = NULL;
+ int h;
+
+ tp = (Array *) ap->sval;
+ h = hash(s, tp->size);
+ for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext)
+ if (strcmp(s, p->nval) == 0) {
+ if (prev == NULL) /* 1st one */
+ tp->tab[h] = p->cnext;
+ else /* middle somewhere */
+ prev->cnext = p->cnext;
+ if (freeable(p))
+ xfree(p->sval);
+ free(p->nval);
+ free(p);
+ tp->nelem--;
+ return;
+ }
+}
+
+Cell *setsymtab(const char *n, const char *s, Awkfloat f, unsigned t, Array *tp)
+{
+ int h;
+ Cell *p;
+
+ if (n != NULL && (p = lookup(n, tp)) != NULL) {
+ dprintf( (thread_stdout, "setsymtab found %p: n=%s s=\"%s\" f=%g t=%o\n",
+ p, NN(p->nval), NN(p->sval), p->fval, p->tval) );
+ return(p);
+ }
+ p = (Cell *) malloc(sizeof(Cell));
+ if (p == NULL)
+ FATAL("out of space for symbol table at %s", n);
+ p->nval = tostring(n);
+ p->sval = s ? tostring(s) : tostring("");
+ p->fval = f;
+ p->tval = t;
+ p->csub = CUNK;
+ p->ctype = OCELL;
+ tp->nelem++;
+ if (tp->nelem > FULLTAB * tp->size)
+ rehash(tp);
+ h = hash(n, tp->size);
+ p->cnext = tp->tab[h];
+ tp->tab[h] = p;
+ dprintf( (thread_stdout, "setsymtab set %p: n=%s s=\"%s\" f=%g t=%o\n",
+ p, p->nval, p->sval, p->fval, p->tval) );
+ return(p);
+}
+
+int hash(const char *s, int n) /* form hash value for string s */
+{
+ unsigned hashval;
+
+ for (hashval = 0; *s != '\0'; s++)
+ hashval = (*s + 31 * hashval);
+ return hashval % n;
+}
+
+void rehash(Array *tp) /* rehash items in small table into big one */
+{
+ int i, nh, nsz;
+ Cell *cp, *op, **np;
+
+ nsz = GROWTAB * tp->size;
+ np = (Cell **) calloc(nsz, sizeof(Cell *));
+ if (np == NULL) /* can't do it, but can keep running. */
+ return; /* someone else will run out later. */
+ for (i = 0; i < tp->size; i++) {
+ for (cp = tp->tab[i]; cp; cp = op) {
+ op = cp->cnext;
+ nh = hash(cp->nval, nsz);
+ cp->cnext = np[nh];
+ np[nh] = cp;
+ }
+ }
+ free(tp->tab);
+ tp->tab = np;
+ tp->size = nsz;
+}
+
+Cell *lookup(const char *s, Array *tp) /* look for s in tp */
+{
+ Cell *p;
+ int h;
+
+ h = hash(s, tp->size);
+ for (p = tp->tab[h]; p != NULL; p = p->cnext)
+ if (strcmp(s, p->nval) == 0)
+ return(p); /* found it */
+ return(NULL); /* not found */
+}
+
+Awkfloat setfval(Cell *vp, Awkfloat f) /* set float val of a Cell */
+{
+ int fldno;
+
+ if ((vp->tval & (NUM | STR)) == 0)
+ funnyvar(vp, "assign to");
+ if (isfld(vp)) {
+ donerec = 0; /* mark $0 invalid */
+ fldno = atoi(vp->nval);
+ if (fldno > *NF)
+ newfld(fldno);
+ dprintf( (thread_stdout, "setting field %d to %g\n", fldno, f) );
+ } else if (isrec(vp)) {
+ donefld = 0; /* mark $1... invalid */
+ donerec = 1;
+ }
+ if (freeable(vp))
+ xfree(vp->sval); /* free any previous string */
+ vp->tval &= ~STR; /* mark string invalid */
+ vp->tval |= NUM; /* mark number ok */
+ if (f == -0) /* who would have thought this possible? */
+ f = 0;
+ dprintf( (thread_stdout, "setfval %p: %s = %g, t=%o\n", vp, NN(vp->nval), f, vp->tval) );
+ return vp->fval = f;
+}
+
+void funnyvar(Cell *vp, const char *rw)
+{
+ if (isarr(vp))
+ FATAL("can't %s %s; it's an array name.", rw, vp->nval);
+ if (vp->tval & FCN)
+ FATAL("can't %s %s; it's a function.", rw, vp->nval);
+ WARNING("funny variable %p: n=%s s=\"%s\" f=%g t=%o",
+ vp, vp->nval, vp->sval, vp->fval, vp->tval);
+}
+
+char *setsval(Cell *vp, const char *s) /* set string val of a Cell */
+{
+ char *t;
+ int fldno;
+
+ dprintf( (thread_stdout, "starting setsval %p: %s = \"%s\", t=%o, r,f=%d,%d\n",
+ vp, NN(vp->nval), s, vp->tval, donerec, donefld) );
+ if ((vp->tval & (NUM | STR)) == 0)
+ funnyvar(vp, "assign to");
+ if (isfld(vp)) {
+ donerec = 0; /* mark $0 invalid */
+ fldno = atoi(vp->nval);
+ if (fldno > *NF)
+ newfld(fldno);
+ dprintf( (thread_stdout, "setting field %d to %s (%p)\n", fldno, s, s) );
+ } else if (isrec(vp)) {
+ donefld = 0; /* mark $1... invalid */
+ donerec = 1;
+ }
+ t = tostring(s); /* in case it's self-assign */
+ if (freeable(vp))
+ xfree(vp->sval);
+ vp->tval &= ~NUM;
+ vp->tval |= STR;
+ vp->tval &= ~DONTFREE;
+ dprintf( (thread_stdout, "setsval %p: %s = \"%s (%p) \", t=%o r,f=%d,%d\n",
+ vp, NN(vp->nval), t,t, vp->tval, donerec, donefld) );
+ return(vp->sval = t);
+}
+
+Awkfloat getfval(Cell *vp) /* get float val of a Cell */
+{
+ if ((vp->tval & (NUM | STR)) == 0)
+ funnyvar(vp, "read value of");
+ if (isfld(vp) && donefld == 0)
+ fldbld();
+ else if (isrec(vp) && donerec == 0)
+ recbld();
+ if (!isnum(vp)) { /* not a number */
+ vp->fval = atof(vp->sval); /* best guess */
+ if (is_number(vp->sval) && !(vp->tval&CON))
+ vp->tval |= NUM; /* make NUM only sparingly */
+ }
+ dprintf( (thread_stdout, "getfval %p: %s = %g, t=%o\n", vp, NN(vp->nval), vp->fval, vp->tval) );
+ return(vp->fval);
+}
+
+static char *get_str_val(Cell *vp, char **fmt) /* get string val of a Cell */
+{
+ char s[100]; /* BUG: unchecked */
+ double dtemp;
+
+ if ((vp->tval & (NUM | STR)) == 0)
+ funnyvar(vp, "read value of");
+ if (isfld(vp) && donefld == 0)
+ fldbld();
+ else if (isrec(vp) && donerec == 0)
+ recbld();
+ if (isstr(vp) == 0) {
+ if (freeable(vp))
+ xfree(vp->sval);
+ if (modf(vp->fval, &dtemp) == 0) /* it's integral */
+ sprintf(s, "%.30g", vp->fval);
+ else
+ sprintf(s, *fmt, vp->fval);
+ vp->sval = tostring(s);
+#if 0
+ /*
+ Cannot reuse the converted form unless you confirm
+ that the current value of CONVFMT is the same as that
+ which was used to convert the previous string. See
+ conformance test awk.ex 233
+ */
+ vp->tval &= ~DONTFREE;
+ vp->tval |= STR;
+#endif
+ }
+ dprintf( (thread_stdout, "getsval %p: %s = \"%s (%p)\", t=%o\n", vp, NN(vp->nval), vp->sval, vp->sval, vp->tval) );
+ return(vp->sval);
+}
+
+char *getsval(Cell *vp) /* get string val of a Cell */
+{
+ return get_str_val(vp, CONVFMT);
+}
+
+char *getpssval(Cell *vp) /* get string val of a Cell for print */
+{
+ return get_str_val(vp, OFMT);
+}
+
+
+char *tostring(const char *s) /* make a copy of string s */
+{
+ char *p;
+
+ p = (char *) malloc(strlen(s)+1);
+ if (p == NULL)
+ FATAL("out of space in tostring on %s", s);
+ strcpy(p, s);
+ return(p);
+}
+
+char *qstring(const char *is, int delim) /* collect string up to next delim */
+{
+ const char *os = is;
+ int c, n;
+ uschar *s = (uschar *) is;
+ uschar *buf, *bp;
+
+ if ((buf = (uschar *) malloc(strlen(is)+3)) == NULL)
+ FATAL( "out of space in qstring(%s)", s);
+ for (bp = buf; (c = *s) != delim; s++) {
+ if (c == '\n')
+ SYNTAX( "newline in string %.20s...", os );
+ else if (c != '\\')
+ *bp++ = c;
+ else { /* \something */
+ c = *++s;
+ if (c == 0) { /* \ at end */
+ *bp++ = '\\';
+ break; /* for loop */
+ }
+ switch (c) {
+ case '\\': *bp++ = '\\'; break;
+ case 'n': *bp++ = '\n'; break;
+ case 't': *bp++ = '\t'; break;
+ case 'b': *bp++ = '\b'; break;
+ case 'f': *bp++ = '\f'; break;
+ case 'r': *bp++ = '\r'; break;
+ default:
+ if (!isdigit(c)) {
+ *bp++ = c;
+ break;
+ }
+ n = c - '0';
+ if (isdigit(s[1])) {
+ n = 8 * n + *++s - '0';
+ if (isdigit(s[1]))
+ n = 8 * n + *++s - '0';
+ }
+ *bp++ = n;
+ break;
+ }
+ }
+ }
+ *bp++ = 0;
+ return (char *) buf;
+}
diff --git a/awk/Sources/awk/ytab.c b/awk/Sources/awk/ytab.c
new file mode 100644
index 00000000..a25b610e
--- /dev/null
+++ b/awk/Sources/awk/ytab.c
@@ -0,0 +1,3753 @@
+/* A Bison parser, made by GNU Bison 2.3. */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+#include "ios_error.h"
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "2.3"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 0
+
+/* Using locations. */
+#define YYLSP_NEEDED 0
+
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ FIRSTTOKEN = 258,
+ PROGRAM = 259,
+ PASTAT = 260,
+ PASTAT2 = 261,
+ XBEGIN = 262,
+ XEND = 263,
+ NL = 264,
+ ARRAY = 265,
+ MATCH = 266,
+ NOTMATCH = 267,
+ MATCHOP = 268,
+ FINAL = 269,
+ DOT = 270,
+ ALL = 271,
+ CCL = 272,
+ NCCL = 273,
+ CHAR = 274,
+ OR = 275,
+ STAR = 276,
+ QUEST = 277,
+ PLUS = 278,
+ EMPTYRE = 279,
+ IGNORE_PRIOR_ATOM = 280,
+ AND = 281,
+ BOR = 282,
+ APPEND = 283,
+ EQ = 284,
+ GE = 285,
+ GT = 286,
+ LE = 287,
+ LT = 288,
+ NE = 289,
+ IN = 290,
+ ARG = 291,
+ BLTIN = 292,
+ BREAK = 293,
+ CLOSE = 294,
+ CONTINUE = 295,
+ DELETE = 296,
+ DO = 297,
+ EXIT = 298,
+ FOR = 299,
+ FUNC = 300,
+ SUB = 301,
+ GSUB = 302,
+ IF = 303,
+ INDEX = 304,
+ LSUBSTR = 305,
+ MATCHFCN = 306,
+ NEXT = 307,
+ NEXTFILE = 308,
+ ADD = 309,
+ MINUS = 310,
+ MULT = 311,
+ DIVIDE = 312,
+ MOD = 313,
+ ASSIGN = 314,
+ ASGNOP = 315,
+ ADDEQ = 316,
+ SUBEQ = 317,
+ MULTEQ = 318,
+ DIVEQ = 319,
+ MODEQ = 320,
+ POWEQ = 321,
+ PRINT = 322,
+ PRINTF = 323,
+ SPRINTF = 324,
+ ELSE = 325,
+ INTEST = 326,
+ CONDEXPR = 327,
+ POSTINCR = 328,
+ PREINCR = 329,
+ POSTDECR = 330,
+ PREDECR = 331,
+ VAR = 332,
+ IVAR = 333,
+ VARNF = 334,
+ CALL = 335,
+ NUMBER = 336,
+ STRING = 337,
+ REGEXPR = 338,
+ GETLINE = 339,
+ SUBSTR = 340,
+ SPLIT = 341,
+ RETURN = 342,
+ WHILE = 343,
+ CAT = 344,
+ UPLUS = 345,
+ UMINUS = 346,
+ NOT = 347,
+ POWER = 348,
+ INCR = 349,
+ DECR = 350,
+ INDIRECT = 351,
+ LASTTOKEN = 352
+ };
+#endif
+/* Tokens. */
+#define FIRSTTOKEN 258
+#define PROGRAM 259
+#define PASTAT 260
+#define PASTAT2 261
+#define XBEGIN 262
+#define XEND 263
+#define NL 264
+#define ARRAY 265
+#define MATCH 266
+#define NOTMATCH 267
+#define MATCHOP 268
+#define FINAL 269
+#define DOT 270
+#define ALL 271
+#define CCL 272
+#define NCCL 273
+#define CHAR 274
+#define OR 275
+#define STAR 276
+#define QUEST 277
+#define PLUS 278
+#define EMPTYRE 279
+#define IGNORE_PRIOR_ATOM 280
+#define AND 281
+#define BOR 282
+#define APPEND 283
+#define EQ 284
+#define GE 285
+#define GT 286
+#define LE 287
+#define LT 288
+#define NE 289
+#define IN 290
+#define ARG 291
+#define BLTIN 292
+#define BREAK 293
+#define CLOSE 294
+#define CONTINUE 295
+#define DELETE 296
+#define DO 297
+#define EXIT 298
+#define FOR 299
+#define FUNC 300
+#define SUB 301
+#define GSUB 302
+#define IF 303
+#define INDEX 304
+#define LSUBSTR 305
+#define MATCHFCN 306
+#define NEXT 307
+#define NEXTFILE 308
+#define ADD 309
+#define MINUS 310
+#define MULT 311
+#define DIVIDE 312
+#define MOD 313
+#define ASSIGN 314
+#define ASGNOP 315
+#define ADDEQ 316
+#define SUBEQ 317
+#define MULTEQ 318
+#define DIVEQ 319
+#define MODEQ 320
+#define POWEQ 321
+#define PRINT 322
+#define PRINTF 323
+#define SPRINTF 324
+#define ELSE 325
+#define INTEST 326
+#define CONDEXPR 327
+#define POSTINCR 328
+#define PREINCR 329
+#define POSTDECR 330
+#define PREDECR 331
+#define VAR 332
+#define IVAR 333
+#define VARNF 334
+#define CALL 335
+#define NUMBER 336
+#define STRING 337
+#define REGEXPR 338
+#define GETLINE 339
+#define SUBSTR 340
+#define SPLIT 341
+#define RETURN 342
+#define WHILE 343
+#define CAT 344
+#define UPLUS 345
+#define UMINUS 346
+#define NOT 347
+#define POWER 348
+#define INCR 349
+#define DECR 350
+#define INDIRECT 351
+#define LASTTOKEN 352
+
+
+
+
+/* Copy the first part of user declarations. */
+#line 25 "awkgram.y"
+
+#include
+#include
+#include "awk.h"
+
+void checkdup(Node *list, Cell *item);
+int yywrap(void) { return(1); }
+
+__thread Node *beginloc = 0;
+__thread Node *endloc = 0;
+__thread int infunc = 0; /* = 1 if in arglist or body of func */
+__thread int inloop = 0; /* = 1 if in while, for, do */
+__thread char *curfname = 0; /* current function name */
+__thread Node *arglist = 0; /* list of args for current function */
+
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 41 "awkgram.y"
+{
+ Node *p;
+ Cell *cp;
+ int i;
+ char *s;
+}
+/* Line 193 of yacc.c. */
+#line 313 "y.tab.c"
+ YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations. */
+
+
+/* Line 216 of yacc.c. */
+#line 326 "y.tab.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+# if ENABLE_NLS
+# include /* INFRINGES ON USER NAME SPACE */
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int i)
+#else
+static int
+YYID (i)
+ int i;
+#endif
+{
+ return i;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined _STDLIB_H \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss;
+ YYSTYPE yyvs;
+ };
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack, Stack, yysize); \
+ Stack = &yyptr->Stack; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 8
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 4787
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 114
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 49
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 186
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 369
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 352
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 105, 2, 2,
+ 12, 16, 104, 102, 9, 103, 2, 15, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 95, 14,
+ 2, 2, 2, 94, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 18, 2, 19, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 11, 13, 17, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 10, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+ 85, 86, 87, 88, 89, 90, 91, 92, 93, 96,
+ 97, 98, 99, 100, 101, 106, 107, 108, 109, 110,
+ 111, 112, 113
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const yytype_uint16 yyprhs[] =
+{
+ 0, 0, 3, 5, 7, 9, 12, 14, 17, 19,
+ 22, 24, 27, 29, 32, 33, 46, 47, 58, 59,
+ 68, 70, 72, 77, 79, 82, 84, 87, 88, 90,
+ 91, 93, 94, 96, 98, 102, 104, 106, 111, 115,
+ 122, 126, 131, 136, 137, 147, 149, 153, 155, 159,
+ 163, 169, 173, 177, 181, 185, 189, 195, 198, 200,
+ 202, 206, 212, 216, 220, 224, 228, 232, 236, 240,
+ 244, 248, 252, 256, 262, 267, 271, 274, 276, 278,
+ 282, 286, 288, 292, 293, 295, 299, 301, 303, 305,
+ 307, 310, 313, 315, 318, 320, 323, 324, 329, 331,
+ 334, 339, 344, 349, 352, 358, 361, 363, 365, 367,
+ 370, 373, 376, 377, 378, 388, 392, 395, 397, 402,
+ 405, 409, 412, 415, 419, 422, 425, 426, 430, 433,
+ 435, 438, 440, 442, 447, 451, 455, 459, 463, 467,
+ 471, 475, 478, 481, 484, 488, 493, 495, 499, 504,
+ 507, 510, 513, 516, 519, 524, 528, 531, 533, 540,
+ 547, 551, 558, 565, 567, 576, 585, 592, 597, 599,
+ 606, 613, 622, 631, 640, 647, 649, 651, 656, 658,
+ 661, 662, 664, 668, 670, 672, 674
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int16 yyrhs[] =
+{
+ 115, 0, -1, 132, -1, 1, -1, 36, -1, 116,
+ 10, -1, 37, -1, 117, 10, -1, 9, -1, 118,
+ 10, -1, 52, -1, 119, 10, -1, 80, -1, 120,
+ 10, -1, -1, 54, 12, 131, 14, 129, 139, 14,
+ 129, 131, 149, 122, 152, -1, -1, 54, 12, 131,
+ 14, 14, 129, 131, 149, 123, 152, -1, -1, 54,
+ 12, 161, 45, 161, 149, 124, 152, -1, 87, -1,
+ 90, -1, 58, 12, 139, 149, -1, 11, -1, 127,
+ 10, -1, 10, -1, 128, 10, -1, -1, 128, -1,
+ -1, 144, -1, -1, 150, -1, 130, -1, 130, 136,
+ 130, -1, 139, -1, 133, -1, 133, 127, 156, 17,
+ -1, 133, 9, 133, -1, 133, 9, 133, 127, 156,
+ 17, -1, 127, 156, 17, -1, 7, 127, 156, 17,
+ -1, 8, 127, 156, 17, -1, -1, 55, 125, 12,
+ 160, 149, 135, 127, 156, 17, -1, 134, -1, 136,
+ 130, 134, -1, 139, -1, 137, 118, 139, -1, 159,
+ 70, 138, -1, 138, 94, 138, 95, 138, -1, 138,
+ 117, 138, -1, 138, 116, 138, -1, 138, 23, 147,
+ -1, 138, 23, 138, -1, 138, 45, 161, -1, 12,
+ 140, 16, 45, 161, -1, 138, 158, -1, 146, -1,
+ 158, -1, 159, 70, 139, -1, 139, 94, 139, 95,
+ 139, -1, 139, 117, 139, -1, 139, 116, 139, -1,
+ 139, 39, 139, -1, 139, 40, 139, -1, 139, 41,
+ 139, -1, 139, 42, 139, -1, 139, 43, 139, -1,
+ 139, 44, 139, -1, 139, 23, 147, -1, 139, 23,
+ 139, -1, 139, 45, 161, -1, 12, 140, 16, 45,
+ 161, -1, 139, 13, 96, 159, -1, 139, 13, 96,
+ -1, 139, 158, -1, 146, -1, 158, -1, 139, 118,
+ 139, -1, 140, 118, 139, -1, 138, -1, 141, 118,
+ 138, -1, -1, 141, -1, 12, 140, 16, -1, 77,
+ -1, 78, -1, 10, -1, 14, -1, 144, 10, -1,
+ 144, 14, -1, 17, -1, 145, 10, -1, 147, -1,
+ 108, 146, -1, -1, 15, 148, 93, 15, -1, 16,
+ -1, 149, 10, -1, 143, 142, 13, 158, -1, 143,
+ 142, 38, 158, -1, 143, 142, 41, 158, -1, 143,
+ 142, -1, 51, 161, 18, 137, 19, -1, 51, 161,
+ -1, 139, -1, 1, -1, 128, -1, 14, 129, -1,
+ 48, 151, -1, 50, 151, -1, -1, -1, 119, 153,
+ 152, 154, 100, 12, 139, 16, 151, -1, 53, 139,
+ 151, -1, 53, 151, -1, 121, -1, 126, 152, 120,
+ 152, -1, 126, 152, -1, 127, 156, 145, -1, 62,
+ 151, -1, 63, 151, -1, 99, 139, 151, -1, 99,
+ 151, -1, 150, 151, -1, -1, 162, 155, 152, -1,
+ 14, 129, -1, 152, -1, 156, 152, -1, 56, -1,
+ 57, -1, 158, 15, 70, 158, -1, 158, 102, 158,
+ -1, 158, 103, 158, -1, 158, 104, 158, -1, 158,
+ 15, 158, -1, 146, 15, 158, -1, 158, 105, 158,
+ -1, 158, 109, 158, -1, 103, 158, -1, 102, 158,
+ -1, 108, 158, -1, 47, 12, 16, -1, 47, 12,
+ 137, 16, -1, 47, -1, 90, 12, 16, -1, 90,
+ 12, 137, 16, -1, 49, 158, -1, 111, 159, -1,
+ 110, 159, -1, 159, 111, -1, 159, 110, -1, 96,
+ 159, 43, 158, -1, 96, 43, 158, -1, 96, 159,
+ -1, 96, -1, 59, 12, 139, 118, 139, 16, -1,
+ 59, 12, 139, 118, 147, 16, -1, 12, 139, 16,
+ -1, 61, 12, 139, 118, 147, 16, -1, 61, 12,
+ 139, 118, 139, 16, -1, 91, -1, 98, 12, 139,
+ 118, 161, 118, 139, 16, -1, 98, 12, 139, 118,
+ 161, 118, 147, 16, -1, 98, 12, 139, 118, 161,
+ 16, -1, 79, 12, 137, 16, -1, 92, -1, 157,
+ 12, 147, 118, 139, 16, -1, 157, 12, 139, 118,
+ 139, 16, -1, 157, 12, 147, 118, 139, 118, 159,
+ 16, -1, 157, 12, 139, 118, 139, 118, 159, 16,
+ -1, 97, 12, 139, 118, 139, 118, 139, 16, -1,
+ 97, 12, 139, 118, 139, 16, -1, 159, -1, 161,
+ -1, 161, 18, 137, 19, -1, 88, -1, 112, 158,
+ -1, -1, 87, -1, 160, 118, 87, -1, 87, -1,
+ 46, -1, 89, -1, 100, 12, 139, 149, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 98, 98, 100, 104, 104, 108, 108, 112, 112,
+ 116, 116, 120, 120, 124, 124, 126, 126, 128, 128,
+ 133, 134, 138, 142, 142, 146, 146, 150, 151, 155,
+ 156, 161, 162, 166, 167, 171, 175, 176, 177, 178,
+ 179, 180, 182, 184, 184, 189, 190, 194, 195, 199,
+ 200, 202, 204, 206, 207, 212, 213, 214, 215, 216,
+ 220, 221, 223, 225, 227, 228, 229, 230, 231, 232,
+ 233, 234, 239, 240, 241, 244, 247, 248, 249, 253,
+ 254, 258, 259, 263, 264, 265, 269, 269, 273, 273,
+ 273, 273, 277, 277, 281, 283, 287, 287, 291, 291,
+ 295, 298, 301, 304, 305, 306, 307, 308, 312, 313,
+ 317, 319, 321, 321, 321, 323, 324, 325, 326, 327,
+ 328, 329, 332, 335, 336, 337, 338, 338, 339, 343,
+ 344, 348, 348, 352, 353, 354, 355, 356, 357, 358,
+ 359, 360, 361, 362, 363, 364, 365, 366, 367, 368,
+ 369, 370, 371, 372, 373, 374, 375, 376, 377, 379,
+ 382, 383, 385, 390, 391, 393, 395, 397, 398, 399,
+ 401, 406, 408, 413, 415, 417, 421, 422, 423, 424,
+ 428, 429, 430, 436, 437, 438, 443
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "FIRSTTOKEN", "PROGRAM", "PASTAT",
+ "PASTAT2", "XBEGIN", "XEND", "','", "NL", "'{'", "'('", "'|'", "';'",
+ "'/'", "')'", "'}'", "'['", "']'", "ARRAY", "MATCH", "NOTMATCH",
+ "MATCHOP", "FINAL", "DOT", "ALL", "CCL", "NCCL", "CHAR", "OR", "STAR",
+ "QUEST", "PLUS", "EMPTYRE", "IGNORE_PRIOR_ATOM", "AND", "BOR", "APPEND",
+ "EQ", "GE", "GT", "LE", "LT", "NE", "IN", "ARG", "BLTIN", "BREAK",
+ "CLOSE", "CONTINUE", "DELETE", "DO", "EXIT", "FOR", "FUNC", "SUB",
+ "GSUB", "IF", "INDEX", "LSUBSTR", "MATCHFCN", "NEXT", "NEXTFILE", "ADD",
+ "MINUS", "MULT", "DIVIDE", "MOD", "ASSIGN", "ASGNOP", "ADDEQ", "SUBEQ",
+ "MULTEQ", "DIVEQ", "MODEQ", "POWEQ", "PRINT", "PRINTF", "SPRINTF",
+ "ELSE", "INTEST", "CONDEXPR", "POSTINCR", "PREINCR", "POSTDECR",
+ "PREDECR", "VAR", "IVAR", "VARNF", "CALL", "NUMBER", "STRING", "REGEXPR",
+ "'?'", "':'", "GETLINE", "SUBSTR", "SPLIT", "RETURN", "WHILE", "CAT",
+ "'+'", "'-'", "'*'", "'%'", "UPLUS", "UMINUS", "NOT", "POWER", "INCR",
+ "DECR", "INDIRECT", "LASTTOKEN", "$accept", "program", "and", "bor",
+ "comma", "do", "else", "for", "@1", "@2", "@3", "funcname", "if",
+ "lbrace", "nl", "opt_nl", "opt_pst", "opt_simple_stmt", "pas", "pa_pat",
+ "pa_stat", "@4", "pa_stats", "patlist", "ppattern", "pattern", "plist",
+ "pplist", "prarg", "print", "pst", "rbrace", "re", "reg_expr", "@5",
+ "rparen", "simple_stmt", "st", "stmt", "@6", "@7", "@8", "stmtlist",
+ "subop", "term", "var", "varlist", "varname", "while", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 44,
+ 264, 123, 40, 124, 59, 47, 41, 125, 91, 93,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 298, 299, 300, 301, 302, 303, 304,
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, 318, 319, 320, 321, 322, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
+ 335, 336, 337, 338, 63, 58, 339, 340, 341, 342,
+ 343, 344, 43, 45, 42, 37, 345, 346, 347, 348,
+ 349, 350, 351, 352
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 114, 115, 115, 116, 116, 117, 117, 118, 118,
+ 119, 119, 120, 120, 122, 121, 123, 121, 124, 121,
+ 125, 125, 126, 127, 127, 128, 128, 129, 129, 130,
+ 130, 131, 131, 132, 132, 133, 134, 134, 134, 134,
+ 134, 134, 134, 135, 134, 136, 136, 137, 137, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
+ 139, 139, 139, 139, 139, 139, 139, 139, 139, 140,
+ 140, 141, 141, 142, 142, 142, 143, 143, 144, 144,
+ 144, 144, 145, 145, 146, 146, 148, 147, 149, 149,
+ 150, 150, 150, 150, 150, 150, 150, 150, 151, 151,
+ 152, 152, 153, 154, 152, 152, 152, 152, 152, 152,
+ 152, 152, 152, 152, 152, 152, 155, 152, 152, 156,
+ 156, 157, 157, 158, 158, 158, 158, 158, 158, 158,
+ 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
+ 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
+ 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
+ 158, 158, 158, 158, 158, 158, 159, 159, 159, 159,
+ 160, 160, 160, 161, 161, 161, 162
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 1, 1, 1, 2, 1, 2, 1, 2,
+ 1, 2, 1, 2, 0, 12, 0, 10, 0, 8,
+ 1, 1, 4, 1, 2, 1, 2, 0, 1, 0,
+ 1, 0, 1, 1, 3, 1, 1, 4, 3, 6,
+ 3, 4, 4, 0, 9, 1, 3, 1, 3, 3,
+ 5, 3, 3, 3, 3, 3, 5, 2, 1, 1,
+ 3, 5, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 5, 4, 3, 2, 1, 1, 3,
+ 3, 1, 3, 0, 1, 3, 1, 1, 1, 1,
+ 2, 2, 1, 2, 1, 2, 0, 4, 1, 2,
+ 4, 4, 4, 2, 5, 2, 1, 1, 1, 2,
+ 2, 2, 0, 0, 9, 3, 2, 1, 4, 2,
+ 3, 2, 2, 3, 2, 2, 0, 3, 2, 1,
+ 2, 1, 1, 4, 3, 3, 3, 3, 3, 3,
+ 3, 2, 2, 2, 3, 4, 1, 3, 4, 2,
+ 2, 2, 2, 2, 4, 3, 2, 1, 6, 6,
+ 3, 6, 6, 1, 8, 8, 6, 4, 1, 6,
+ 6, 8, 8, 8, 6, 1, 1, 4, 1, 2,
+ 0, 1, 3, 1, 1, 1, 4
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
+{
+ 0, 3, 88, 89, 0, 33, 2, 30, 1, 0,
+ 0, 23, 0, 96, 184, 146, 0, 0, 131, 132,
+ 0, 0, 0, 183, 178, 185, 0, 163, 168, 157,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 36,
+ 45, 29, 35, 77, 94, 0, 78, 175, 176, 90,
+ 91, 0, 0, 0, 0, 0, 0, 0, 0, 149,
+ 175, 20, 21, 0, 0, 0, 0, 0, 0, 156,
+ 0, 0, 142, 141, 95, 143, 151, 150, 179, 107,
+ 24, 27, 0, 0, 0, 10, 0, 0, 0, 0,
+ 0, 86, 87, 0, 0, 112, 117, 0, 0, 106,
+ 83, 0, 129, 0, 126, 0, 0, 34, 0, 0,
+ 4, 6, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 76, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 153, 152, 0, 0, 0, 8, 160, 0,
+ 0, 0, 0, 144, 0, 47, 0, 180, 0, 0,
+ 0, 147, 0, 155, 0, 0, 0, 25, 28, 128,
+ 27, 108, 110, 111, 105, 0, 116, 0, 0, 121,
+ 122, 0, 124, 0, 11, 0, 119, 0, 0, 81,
+ 84, 103, 58, 59, 175, 125, 40, 130, 0, 38,
+ 0, 46, 75, 71, 70, 64, 65, 66, 67, 68,
+ 69, 72, 0, 5, 63, 7, 62, 138, 0, 94,
+ 0, 137, 134, 135, 136, 139, 140, 60, 0, 41,
+ 42, 9, 79, 0, 80, 97, 145, 0, 181, 0,
+ 0, 0, 167, 148, 154, 0, 0, 26, 109, 0,
+ 115, 0, 32, 176, 0, 123, 0, 113, 12, 0,
+ 92, 120, 0, 0, 0, 0, 0, 0, 57, 0,
+ 0, 0, 0, 0, 127, 0, 37, 74, 0, 0,
+ 0, 133, 177, 73, 48, 98, 0, 43, 0, 94,
+ 0, 94, 0, 0, 0, 27, 0, 22, 186, 0,
+ 13, 118, 93, 85, 0, 54, 53, 55, 0, 52,
+ 51, 82, 100, 101, 102, 49, 0, 61, 0, 0,
+ 182, 99, 0, 158, 159, 162, 161, 174, 0, 166,
+ 0, 104, 27, 0, 0, 0, 0, 0, 0, 39,
+ 170, 0, 169, 0, 0, 0, 0, 94, 0, 0,
+ 18, 0, 56, 0, 50, 0, 0, 0, 173, 164,
+ 165, 0, 27, 0, 0, 172, 171, 44, 16, 0,
+ 19, 0, 0, 0, 114, 17, 14, 0, 15
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int16 yydefgoto[] =
+{
+ -1, 4, 120, 121, 227, 95, 249, 96, 367, 362,
+ 353, 63, 97, 98, 161, 159, 5, 241, 6, 39,
+ 40, 312, 41, 144, 179, 99, 54, 180, 181, 100,
+ 7, 251, 43, 44, 55, 277, 101, 162, 102, 175,
+ 289, 188, 103, 45, 46, 47, 229, 48, 104
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -327
+static const yytype_int16 yypact[] =
+{
+ 744, -327, -327, -327, 48, 1663, -327, 30, -327, 51,
+ 51, -327, 4501, -327, -327, 45, 4559, -55, -327, -327,
+ 56, 59, 65, -327, -327, -327, 94, -327, -327, 164,
+ 108, 111, 4559, 4559, 4559, 185, 185, 4559, 847, 79,
+ -327, 77, 3663, 116, -327, 113, -7, -32, 118, -327,
+ -327, 847, 847, 1767, 106, -30, 4267, 4501, 116, -7,
+ -87, -327, -327, 122, 4501, 4501, 4501, 4325, 4559, 99,
+ 4501, 4501, 37, 37, -327, 37, -327, -327, -327, -327,
+ -327, 138, 91, 91, -40, -327, 2332, 142, 147, 91,
+ 91, -327, -327, 2332, 158, 163, -327, 1469, 847, 3663,
+ 4617, 91, -327, 916, -327, 4501, 847, 1663, 95, 4501,
+ -327, -327, 4501, 4501, 4501, 4501, 4501, 4501, -40, 4501,
+ 2390, 2448, -7, 4559, 4501, 4383, 4559, 4559, 4559, 4559,
+ 4559, 4501, -327, -327, 4501, 985, 1054, -327, -327, 2506,
+ 130, 2506, 172, -327, 110, 3663, 2781, 112, 2171, 2171,
+ 128, -327, 149, -7, 4559, 2171, 2171, -327, 190, -327,
+ 138, 190, -327, -327, 177, 2274, -327, 1537, 4501, -327,
+ -327, 2274, -327, 4501, -327, 1469, 123, 1123, 4501, 4079,
+ 195, 15, 116, -7, -29, -327, -327, -327, 1469, 51,
+ 1192, -327, 185, 3939, -327, 3939, 3939, 3939, 3939, 3939,
+ 3939, -327, 2873, -327, 3847, -327, 3755, 37, 2171, 195,
+ 4559, 37, -1, -1, 37, 37, 37, 3663, 46, -327,
+ -327, -327, 3663, -40, 3663, -327, -327, 2506, -327, 155,
+ 2506, 2506, -327, -327, -7, 2506, 54, -327, -327, 4501,
+ -327, 210, -327, 16, 2974, -327, 2974, -327, -327, 1262,
+ -327, 215, 169, 4675, -40, 4675, 2564, 2622, -7, 2680,
+ 4559, 4559, 4559, 4675, -327, 847, -327, -327, 4501, 2506,
+ 2506, -7, -327, -327, 3663, -327, 12, 216, 3075, 213,
+ 3176, 217, 1871, 196, 66, 146, -40, 216, 216, 135,
+ -327, -327, -327, 187, 4501, 4443, -327, -327, 4009, 4209,
+ 4149, 4079, -7, -7, -7, 4079, 1331, 3663, 1975, 2079,
+ -327, -327, 51, -327, -327, -327, -327, -327, 2506, -327,
+ 2506, -327, 138, 4501, 220, 226, -40, 211, 4675, -327,
+ -327, 5, -327, 5, 847, 3277, 3378, 238, 1605, 3470,
+ 216, 4501, -327, 187, 4079, 239, 241, 1400, -327, -327,
+ -327, 220, 138, 1469, 3571, -327, -327, -327, 216, 1605,
+ -327, 91, 1469, 220, -327, -327, 216, 1469, -327
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int16 yypgoto[] =
+{
+ -327, -327, -148, 152, 13, -327, -327, -327, -327, -327,
+ -327, -327, -327, 20, -74, -150, 218, -326, -327, 156,
+ 153, -327, -327, -65, -183, 550, -173, -327, -327, -327,
+ -327, -327, 181, -64, -327, -235, -140, -47, 395, -327,
+ -327, -327, -48, -327, 378, -16, -327, 132, -327
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -32
+static const yytype_int16 yytable[] =
+{
+ 60, 150, 152, 135, 136, 252, 14, 158, 125, 287,
+ 238, 288, 351, 69, 125, 221, 60, 60, 60, 76,
+ 77, 60, 221, 132, 133, 38, 60, 242, 260, 51,
+ 52, 256, 61, 363, 134, 62, 163, 60, 131, 166,
+ 49, 263, 169, 170, 50, 194, 172, 23, 8, 25,
+ 177, 14, 60, 261, 185, 137, 262, 56, 190, 106,
+ 209, 286, 11, 142, 221, 272, 139, 141, 64, 218,
+ 295, 65, 298, 299, 300, 137, 301, 66, 132, 133,
+ 305, 132, 133, 60, 184, 321, 158, 2, 105, 340,
+ 11, 3, 23, 24, 25, 126, 127, 128, 129, 310,
+ 14, 157, 130, 128, 129, 160, 67, 60, 130, 60,
+ 60, 60, 60, 60, 60, 137, 358, 37, 240, 137,
+ 70, 327, 140, 71, 245, 124, 226, 38, 366, 60,
+ 60, 123, 60, 60, 147, 323, 134, 137, 60, 60,
+ 60, 23, 154, 25, 232, 344, 130, 256, 157, 60,
+ 256, 256, 256, 256, 167, 60, 157, 256, 137, 168,
+ 322, 230, 231, 60, 137, 233, 279, 281, 235, 236,
+ 173, 275, 338, 174, 284, 223, 267, 60, 137, 60,
+ 60, 60, 60, 60, 60, 293, 60, 225, 60, 296,
+ 60, 192, 60, 259, 60, 239, 256, 58, 242, 228,
+ 237, 60, 359, 248, 137, 137, 60, 68, 60, 265,
+ 14, 158, 319, 58, 58, 74, 164, 306, 58, 242,
+ 137, 269, 270, 58, 285, 292, 311, 343, 60, 314,
+ 60, 14, 326, 316, 58, 325, 275, 184, 341, 184,
+ 184, 184, 276, 184, 60, 60, 60, 184, 158, 58,
+ 201, 23, 24, 25, 350, 355, 337, 356, 60, 107,
+ 191, 189, 60, 0, 60, 141, 60, 0, 0, 0,
+ 0, 0, 23, 24, 25, 0, 37, 0, 158, 60,
+ 58, 182, 60, 60, 60, 60, 347, 0, 0, 60,
+ 0, 60, 60, 60, 0, 318, 320, 37, 0, 243,
+ 0, 0, 0, 0, 58, 0, 58, 58, 58, 58,
+ 58, 58, 184, 0, 364, 345, 0, 346, 0, 60,
+ 60, 331, 333, 60, 0, 0, 58, 58, 60, 58,
+ 58, 257, 334, 0, 0, 58, 58, 58, 60, 0,
+ 141, 0, 0, 0, 0, 0, 58, 0, 0, 0,
+ 0, 0, 58, 0, 0, 273, 0, 0, 0, 0,
+ 58, 0, 0, 0, 0, 0, 0, 0, 283, 0,
+ 0, 0, 0, 0, 58, 0, 58, 58, 58, 58,
+ 58, 58, 0, 58, 0, 58, 297, 58, 0, 58,
+ 0, 58, 0, 0, 59, 0, 0, 0, 58, 0,
+ 0, 0, 0, 58, 0, 58, 0, 0, 0, 0,
+ 72, 73, 75, 0, 0, 78, 0, 0, 324, 0,
+ 122, 0, 0, 0, 0, 58, 0, 58, 0, 0,
+ 0, 122, 0, 0, 182, 0, 182, 182, 182, 0,
+ 182, 58, 58, 58, 182, 0, 153, 257, 0, 0,
+ 257, 257, 257, 257, 0, 58, 0, 257, 342, 58,
+ 0, 58, 0, 58, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 58, 122, 183, 58,
+ 58, 58, 58, 0, 0, 0, 58, 0, 58, 58,
+ 58, 0, 176, 0, 0, 0, 257, 0, 187, 0,
+ 0, 207, 0, 211, 212, 213, 214, 215, 216, 182,
+ 0, 0, 0, 0, 0, 0, 58, 58, 0, 0,
+ 58, 0, 0, 122, 122, 58, 122, 122, 0, 0,
+ 187, 187, 234, 122, 122, 58, 0, 0, 0, 0,
+ 0, 0, 0, 122, 0, 0, 0, 0, 0, 122,
+ 0, 0, 0, 0, 0, 42, 0, 258, 0, 0,
+ 0, 0, 53, 0, 0, 0, 0, 0, 0, 0,
+ 247, 122, 187, 122, 122, 122, 122, 122, 122, 0,
+ 122, 0, 122, 264, 122, 187, 122, 0, 271, 0,
+ 0, 0, 0, 0, 0, 122, 0, 0, 0, 0,
+ 122, 0, 122, 0, 0, 0, 145, 146, 0, 0,
+ 0, 0, 0, 0, 148, 149, 145, 145, 0, 0,
+ 155, 156, 122, 0, 122, 0, 0, 0, 0, 0,
+ 0, 183, 0, 183, 183, 183, 165, 183, 302, 303,
+ 304, 183, 0, 171, 291, 0, 0, 0, 0, 0,
+ 0, 0, 122, 0, 0, 42, 122, 42, 122, 193,
+ 122, 0, 195, 196, 197, 198, 199, 200, 0, 202,
+ 204, 206, 0, 258, 208, 0, 258, 258, 258, 258,
+ 0, 217, 0, 258, 145, 122, 122, 122, 0, 222,
+ 0, 224, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 187, 0, 0, 0, 0, 183, 0, 0, 0,
+ 0, 0, 0, 122, 122, 0, 0, 122, 244, 0,
+ 0, 0, 258, 246, 0, 0, 0, 0, 53, 0,
+ 0, 0, 122, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 187, 0, -29, 1, 0, 0, 360, 0,
+ 0, -29, -29, 0, 2, -29, -29, 365, 3, -29,
+ 0, 0, 368, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 274, 0, 0,
+ 278, 280, 0, 0, 0, 282, 0, 0, 0, 145,
+ -29, -29, 0, -29, 0, 0, 0, 0, 0, -29,
+ -29, -29, 0, -29, 0, -29, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 307, 308,
+ 309, 0, 0, -29, 0, 0, 0, 0, 0, 0,
+ 0, -29, -29, -29, -29, -29, -29, 0, 0, 0,
+ -29, -29, -29, 0, 53, 0, -29, -29, 79, 0,
+ 0, 0, -29, 0, -29, -29, -29, 80, 11, 12,
+ 0, 81, 13, 0, 0, 0, 0, 0, 335, 0,
+ 336, 0, 0, 339, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 354, 0, 14, 15, 82, 16, 83, 84, 85,
+ 86, 87, 0, 18, 19, 88, 20, 0, 21, 89,
+ 90, 0, 0, 0, 0, 0, 0, 79, 0, 0,
+ 0, 0, 0, 0, 91, 92, 22, 11, 12, 0,
+ 81, 13, 0, 186, 23, 24, 25, 26, 27, 28,
+ 0, 0, 0, 29, 30, 31, 93, 94, 0, 32,
+ 33, 0, 0, 0, 0, 34, 0, 35, 36, 37,
+ 0, 0, 14, 15, 82, 16, 83, 84, 85, 86,
+ 87, 0, 18, 19, 88, 20, 0, 21, 89, 90,
+ 0, 0, 0, 0, 0, 0, 79, 0, 0, 0,
+ 0, 0, 0, 91, 92, 22, 11, 12, 0, 81,
+ 13, 0, 219, 23, 24, 25, 26, 27, 28, 0,
+ 0, 0, 29, 30, 31, 93, 94, 0, 32, 33,
+ 0, 0, 0, 0, 34, 0, 35, 36, 37, 0,
+ 0, 14, 15, 82, 16, 83, 84, 85, 86, 87,
+ 0, 18, 19, 88, 20, 0, 21, 89, 90, 0,
+ 0, 0, 0, 0, 0, 79, 0, 0, 0, 0,
+ 0, 0, 91, 92, 22, 11, 12, 0, 81, 13,
+ 0, 220, 23, 24, 25, 26, 27, 28, 0, 0,
+ 0, 29, 30, 31, 93, 94, 0, 32, 33, 0,
+ 0, 0, 0, 34, 0, 35, 36, 37, 0, 0,
+ 14, 15, 82, 16, 83, 84, 85, 86, 87, 0,
+ 18, 19, 88, 20, 0, 21, 89, 90, 0, 0,
+ 0, 0, 0, 0, 79, 0, 0, 0, 0, 0,
+ 0, 91, 92, 22, 11, 12, 0, 81, 13, 0,
+ 250, 23, 24, 25, 26, 27, 28, 0, 0, 0,
+ 29, 30, 31, 93, 94, 0, 32, 33, 0, 0,
+ 0, 0, 34, 0, 35, 36, 37, 0, 0, 14,
+ 15, 82, 16, 83, 84, 85, 86, 87, 0, 18,
+ 19, 88, 20, 0, 21, 89, 90, 0, 0, 0,
+ 0, 0, 0, 79, 0, 0, 0, 0, 0, 0,
+ 91, 92, 22, 11, 12, 0, 81, 13, 0, 266,
+ 23, 24, 25, 26, 27, 28, 0, 0, 0, 29,
+ 30, 31, 93, 94, 0, 32, 33, 0, 0, 0,
+ 0, 34, 0, 35, 36, 37, 0, 0, 14, 15,
+ 82, 16, 83, 84, 85, 86, 87, 0, 18, 19,
+ 88, 20, 0, 21, 89, 90, 0, 0, 0, 0,
+ 0, 0, 0, 79, 0, 0, 0, 0, 0, 91,
+ 92, 22, 290, 11, 12, 0, 81, 13, 0, 23,
+ 24, 25, 26, 27, 28, 0, 0, 0, 29, 30,
+ 31, 93, 94, 0, 32, 33, 0, 0, 0, 0,
+ 34, 0, 35, 36, 37, 0, 0, 0, 14, 15,
+ 82, 16, 83, 84, 85, 86, 87, 0, 18, 19,
+ 88, 20, 0, 21, 89, 90, 0, 0, 0, 0,
+ 0, 0, 79, 0, 0, 0, 0, 0, 0, 91,
+ 92, 22, 11, 12, 0, 81, 13, 0, 329, 23,
+ 24, 25, 26, 27, 28, 0, 0, 0, 29, 30,
+ 31, 93, 94, 0, 32, 33, 0, 0, 0, 0,
+ 34, 0, 35, 36, 37, 0, 0, 14, 15, 82,
+ 16, 83, 84, 85, 86, 87, 0, 18, 19, 88,
+ 20, 0, 21, 89, 90, 0, 0, 0, 0, 0,
+ 0, 79, 0, 0, 0, 0, 0, 0, 91, 92,
+ 22, 11, 12, 0, 81, 13, 0, 357, 23, 24,
+ 25, 26, 27, 28, 0, 0, 0, 29, 30, 31,
+ 93, 94, 0, 32, 33, 0, 0, 0, 0, 34,
+ 0, 35, 36, 37, 0, 0, 14, 15, 82, 16,
+ 83, 84, 85, 86, 87, 0, 18, 19, 88, 20,
+ 0, 21, 89, 90, 0, 0, 0, 0, 0, 0,
+ 79, 0, 0, 0, 0, 0, 0, 91, 92, 22,
+ 11, 12, 0, 81, 13, 0, 0, 23, 24, 25,
+ 26, 27, 28, 0, 0, 0, 29, 30, 31, 93,
+ 94, 0, 32, 33, 0, 0, 0, 0, 34, 0,
+ 35, 36, 37, 0, 0, 14, 15, 82, 16, 83,
+ 84, 85, 86, 87, 0, 18, 19, 88, 20, 0,
+ 21, 89, 90, 0, 0, 0, 0, 0, 79, 0,
+ 0, 0, 0, 0, 0, 0, 91, 92, 22, 12,
+ 0, -31, 13, 0, 0, 0, 23, 24, 25, 26,
+ 27, 28, 0, 0, 0, 29, 30, 31, 93, 94,
+ 0, 32, 33, 0, 0, 0, 0, 34, 0, 35,
+ 36, 37, 0, 14, 15, 0, 16, 0, 84, 0,
+ 0, 0, 0, 18, 19, 0, 20, 0, 21, 0,
+ 0, 0, 0, 0, 0, 0, 79, 0, 0, 0,
+ 0, 0, 0, 0, 91, 92, 22, 12, 0, 0,
+ 13, -31, 0, 0, 23, 24, 25, 26, 27, 28,
+ 0, 0, 0, 29, 30, 31, 0, 0, 0, 32,
+ 33, 0, 0, 0, 0, 34, 0, 35, 36, 37,
+ 0, 14, 15, 0, 16, 0, 84, 0, 0, 0,
+ 0, 18, 19, 0, 20, 0, 21, 0, 0, 0,
+ 9, 10, 0, 0, 11, 12, 0, 0, 13, 0,
+ 0, 0, 91, 92, 22, 0, 0, 0, 0, 0,
+ 0, 0, 23, 24, 25, 26, 27, 28, 0, 0,
+ 0, 29, 30, 31, 0, 0, 0, 32, 33, 14,
+ 15, 0, 16, 34, 0, 35, 36, 37, 17, 18,
+ 19, 0, 20, 0, 21, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 22, 0, 0, 0, 0, 0, 0, 0,
+ 23, 24, 25, 26, 27, 28, 0, 0, 0, 29,
+ 30, 31, 0, 0, 0, 32, 33, 0, 0, 0,
+ 0, 34, 0, 35, 36, 37, 137, 0, 0, 57,
+ 108, 0, 13, 138, 0, 0, 0, 0, 0, 0,
+ 109, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 110, 111, 0, 112, 113, 114, 115,
+ 116, 117, 118, 14, 15, 0, 16, 0, 0, 0,
+ 0, 0, 0, 18, 19, 0, 20, 0, 21, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 22, 0, 0, 0,
+ 0, 0, 0, 0, 23, 24, 25, 26, 27, 28,
+ 0, 119, 0, 29, 30, 31, 0, 0, 0, 32,
+ 33, 0, 0, 0, 0, 34, 0, 35, 36, 37,
+ 137, 0, 0, 57, 108, 0, 13, 317, 0, 0,
+ 0, 0, 0, 0, 109, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 110, 111, 0,
+ 112, 113, 114, 115, 116, 117, 118, 14, 15, 0,
+ 16, 0, 0, 0, 0, 0, 0, 18, 19, 0,
+ 20, 0, 21, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 22, 0, 0, 0, 0, 0, 0, 0, 23, 24,
+ 25, 26, 27, 28, 0, 119, 0, 29, 30, 31,
+ 0, 0, 0, 32, 33, 0, 0, 0, 0, 34,
+ 0, 35, 36, 37, 137, 0, 0, 57, 108, 0,
+ 13, 330, 0, 0, 0, 0, 0, 0, 109, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 110, 111, 0, 112, 113, 114, 115, 116, 117,
+ 118, 14, 15, 0, 16, 0, 0, 0, 0, 0,
+ 0, 18, 19, 0, 20, 0, 21, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 22, 0, 0, 0, 0, 0,
+ 0, 0, 23, 24, 25, 26, 27, 28, 0, 119,
+ 0, 29, 30, 31, 0, 0, 0, 32, 33, 0,
+ 0, 0, 0, 34, 0, 35, 36, 37, 137, 0,
+ 0, 57, 108, 0, 13, 332, 0, 0, 0, 0,
+ 0, 0, 109, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 110, 111, 0, 112, 113,
+ 114, 115, 116, 117, 118, 14, 15, 0, 16, 0,
+ 0, 0, 0, 0, 0, 18, 19, 0, 20, 0,
+ 21, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 22, 0,
+ 0, 0, 0, 0, 0, 0, 23, 24, 25, 26,
+ 27, 28, 0, 119, 0, 29, 30, 31, 0, 0,
+ 137, 32, 33, 57, 108, 0, 13, 34, 0, 35,
+ 36, 37, 0, 0, 109, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 110, 111, 0,
+ 112, 113, 114, 115, 116, 117, 118, 14, 15, 0,
+ 16, 0, 0, 0, 0, 0, 0, 18, 19, 0,
+ 20, 0, 21, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 22, 0, 0, 0, 0, 0, 0, 0, 23, 24,
+ 25, 26, 27, 28, 0, 119, 0, 29, 30, 31,
+ 0, 0, 0, 32, 33, 0, 0, 0, 0, 34,
+ 0, 35, 36, 37, 157, 0, 57, 108, 160, 13,
+ 0, 0, 0, 0, 0, 0, 0, 109, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 110, 111, 0, 112, 113, 114, 115, 116, 117, 118,
+ 14, 15, 0, 16, 0, 0, 0, 0, 0, 0,
+ 18, 19, 0, 20, 0, 21, 0, 0, 0, 0,
+ 0, 0, 157, 0, 12, 0, 160, 13, 0, 0,
+ 0, 0, 0, 22, 0, 0, 0, 0, 0, 0,
+ 0, 23, 24, 25, 26, 27, 28, 0, 119, 0,
+ 29, 30, 31, 0, 0, 0, 32, 33, 14, 15,
+ 0, 16, 34, 0, 35, 36, 37, 0, 18, 19,
+ 0, 20, 0, 21, 0, 0, 0, 0, 0, 0,
+ 203, 0, 12, 0, 0, 13, 0, 0, 0, 0,
+ 0, 22, 0, 0, 0, 0, 0, 0, 0, 23,
+ 24, 25, 26, 27, 28, 0, 0, 0, 29, 30,
+ 31, 0, 0, 0, 32, 33, 14, 15, 0, 16,
+ 34, 0, 35, 36, 37, 0, 18, 19, 0, 20,
+ 0, 21, 0, 0, 0, 0, 0, 0, 205, 0,
+ 12, 0, 0, 13, 0, 0, 0, 0, 0, 22,
+ 0, 0, 0, 0, 0, 0, 0, 23, 24, 25,
+ 26, 27, 28, 0, 0, 0, 29, 30, 31, 0,
+ 0, 0, 32, 33, 14, 15, 0, 16, 34, 0,
+ 35, 36, 37, 0, 18, 19, 0, 20, 0, 21,
+ 0, 0, 0, 0, 0, 0, 221, 0, 12, 0,
+ 0, 13, 0, 0, 0, 0, 0, 22, 0, 0,
+ 0, 0, 0, 0, 0, 23, 24, 25, 26, 27,
+ 28, 0, 0, 0, 29, 30, 31, 0, 0, 0,
+ 32, 33, 14, 15, 0, 16, 34, 0, 35, 36,
+ 37, 0, 18, 19, 0, 20, 0, 21, 0, 0,
+ 0, 0, 0, 0, 203, 0, 294, 0, 0, 13,
+ 0, 0, 0, 0, 0, 22, 0, 0, 0, 0,
+ 0, 0, 0, 23, 24, 25, 26, 27, 28, 0,
+ 0, 0, 29, 30, 31, 0, 0, 0, 32, 33,
+ 14, 15, 0, 16, 34, 0, 35, 36, 37, 0,
+ 18, 19, 0, 20, 0, 21, 0, 0, 0, 0,
+ 0, 0, 205, 0, 294, 0, 0, 13, 0, 0,
+ 0, 0, 0, 22, 0, 0, 0, 0, 0, 0,
+ 0, 23, 24, 25, 26, 27, 28, 0, 0, 0,
+ 29, 30, 31, 0, 0, 0, 32, 33, 14, 15,
+ 0, 16, 34, 0, 35, 36, 37, 0, 18, 19,
+ 0, 20, 0, 21, 0, 0, 0, 0, 0, 0,
+ 221, 0, 294, 0, 0, 13, 0, 0, 0, 0,
+ 0, 22, 0, 0, 0, 0, 0, 0, 0, 23,
+ 24, 25, 26, 27, 28, 0, 0, 0, 29, 30,
+ 31, 0, 0, 0, 32, 33, 14, 15, 0, 16,
+ 34, 0, 35, 36, 37, 0, 18, 19, 0, 20,
+ 0, 21, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 22,
+ 0, 0, 0, 0, 0, 0, 0, 23, 24, 25,
+ 26, 27, 28, 0, 0, 0, 29, 30, 31, 0,
+ 0, 0, 32, 33, 0, 0, 0, 0, 34, 0,
+ 35, 36, 37, 57, 108, 0, 13, 138, 0, 0,
+ 0, 0, 0, 0, 109, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 110, 111, 0,
+ 112, 113, 114, 115, 116, 117, 118, 14, 15, 0,
+ 16, 0, 0, 0, 0, 0, 0, 18, 19, 0,
+ 20, 0, 21, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 22, 0, 0, 0, 0, 0, 0, 0, 23, 24,
+ 25, 26, 27, 28, 0, 119, 0, 29, 30, 31,
+ 0, 0, 0, 32, 33, 57, 108, 0, 13, 34,
+ 0, 35, 36, 37, 0, 0, 109, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 110,
+ 111, 0, 112, 113, 114, 115, 116, 117, 118, 14,
+ 15, 0, 16, 0, 0, 0, 0, 0, 0, 18,
+ 19, 0, 20, 0, 21, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 22, 0, 0, 0, 0, 0, 0, 0,
+ 23, 24, 25, 26, 27, 28, 0, 119, 268, 29,
+ 30, 31, 0, 0, 0, 32, 33, 0, 0, 0,
+ 0, 34, 0, 35, 36, 37, 57, 108, 0, 13,
+ 275, 0, 0, 0, 0, 0, 0, 109, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 110, 111, 0, 112, 113, 114, 115, 116, 117, 118,
+ 14, 15, 0, 16, 0, 0, 0, 0, 0, 0,
+ 18, 19, 0, 20, 0, 21, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 22, 0, 0, 0, 0, 0, 0,
+ 0, 23, 24, 25, 26, 27, 28, 0, 119, 0,
+ 29, 30, 31, 0, 0, 0, 32, 33, 0, 0,
+ 0, 0, 34, 0, 35, 36, 37, 57, 108, 0,
+ 13, 313, 0, 0, 0, 0, 0, 0, 109, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 110, 111, 0, 112, 113, 114, 115, 116, 117,
+ 118, 14, 15, 0, 16, 0, 0, 0, 0, 0,
+ 0, 18, 19, 0, 20, 0, 21, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 22, 0, 0, 0, 0, 0,
+ 0, 0, 23, 24, 25, 26, 27, 28, 0, 119,
+ 0, 29, 30, 31, 0, 0, 0, 32, 33, 0,
+ 0, 0, 0, 34, 0, 35, 36, 37, 57, 108,
+ 0, 13, 315, 0, 0, 0, 0, 0, 0, 109,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 110, 111, 0, 112, 113, 114, 115, 116,
+ 117, 118, 14, 15, 0, 16, 0, 0, 0, 0,
+ 0, 0, 18, 19, 0, 20, 0, 21, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 22, 0, 0, 0, 0,
+ 0, 0, 0, 23, 24, 25, 26, 27, 28, 0,
+ 119, 0, 29, 30, 31, 0, 0, 0, 32, 33,
+ 0, 0, 0, 0, 34, 0, 35, 36, 37, 57,
+ 108, 0, 13, 348, 0, 0, 0, 0, 0, 0,
+ 109, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 110, 111, 0, 112, 113, 114, 115,
+ 116, 117, 118, 14, 15, 0, 16, 0, 0, 0,
+ 0, 0, 0, 18, 19, 0, 20, 0, 21, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 22, 0, 0, 0,
+ 0, 0, 0, 0, 23, 24, 25, 26, 27, 28,
+ 0, 119, 0, 29, 30, 31, 0, 0, 0, 32,
+ 33, 0, 0, 0, 0, 34, 0, 35, 36, 37,
+ 57, 108, 0, 13, 349, 0, 0, 0, 0, 0,
+ 0, 109, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 110, 111, 0, 112, 113, 114,
+ 115, 116, 117, 118, 14, 15, 0, 16, 0, 0,
+ 0, 0, 0, 0, 18, 19, 0, 20, 0, 21,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 22, 0, 0,
+ 0, 0, 0, 0, 0, 23, 24, 25, 26, 27,
+ 28, 0, 119, 0, 29, 30, 31, 0, 0, 0,
+ 32, 33, 57, 108, 352, 13, 34, 0, 35, 36,
+ 37, 0, 0, 109, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 110, 111, 0, 112,
+ 113, 114, 115, 116, 117, 118, 14, 15, 0, 16,
+ 0, 0, 0, 0, 0, 0, 18, 19, 0, 20,
+ 0, 21, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 22,
+ 0, 0, 0, 0, 0, 0, 0, 23, 24, 25,
+ 26, 27, 28, 0, 119, 0, 29, 30, 31, 0,
+ 0, 0, 32, 33, 0, 0, 0, 0, 34, 0,
+ 35, 36, 37, 57, 108, 0, 13, 361, 0, 0,
+ 0, 0, 0, 0, 109, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 110, 111, 0,
+ 112, 113, 114, 115, 116, 117, 118, 14, 15, 0,
+ 16, 0, 0, 0, 0, 0, 0, 18, 19, 0,
+ 20, 0, 21, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 22, 0, 0, 0, 0, 0, 0, 0, 23, 24,
+ 25, 26, 27, 28, 0, 119, 0, 29, 30, 31,
+ 0, 0, 0, 32, 33, 57, 108, 0, 13, 34,
+ 0, 35, 36, 37, 0, 0, 109, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 110,
+ 111, 0, 112, 113, 114, 115, 116, 117, 118, 14,
+ 15, 0, 16, 0, 0, 0, 0, 0, 0, 18,
+ 19, 0, 20, 0, 21, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 22, 0, 0, 0, 0, 0, 0, 0,
+ 23, 24, 25, 26, 27, 28, 0, 119, 0, 29,
+ 30, 31, 0, 0, 0, 32, 33, 57, 108, 0,
+ 13, 34, 0, 35, 36, 37, 0, 0, 109, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 110, 0, 0, 112, 113, 114, 115, 116, 117,
+ 118, 14, 15, 0, 16, 0, 0, 0, 0, 0,
+ 0, 18, 19, 0, 20, 0, 21, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 22, 0, 0, 0, 0, 0,
+ 0, 0, 23, 24, 25, 26, 27, 28, 0, 0,
+ 0, 29, 30, 31, 0, 0, 0, 32, 33, 57,
+ 108, 0, 13, 34, 0, 35, 36, 37, 0, 0,
+ 109, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 112, 113, 114, 115,
+ 116, 117, 118, 14, 15, 0, 16, 0, 0, 0,
+ 0, 0, 0, 18, 19, 0, 20, 0, 21, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 22, 0, 0, 0,
+ 0, 0, 0, 0, 23, 24, 25, 26, 27, 28,
+ 0, 0, 0, 29, 30, 31, 0, 0, 0, 32,
+ 33, 57, -32, 0, 13, 34, 0, 35, 36, 37,
+ 0, 0, -32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, -32, -32,
+ -32, -32, -32, -32, -32, 14, 15, 0, 16, 0,
+ 0, 0, 0, 0, 0, 18, 19, 0, 20, 0,
+ 21, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 22, 0,
+ 0, 57, 0, 0, 13, 0, 23, 24, 25, 26,
+ 27, 28, 253, 0, 0, 0, 30, 31, 0, 0,
+ 0, 32, 33, 0, 0, 110, 111, 34, 0, 35,
+ 36, 37, 0, 0, 254, 14, 15, 0, 16, 0,
+ 0, 0, 0, 0, 0, 18, 19, 0, 20, 0,
+ 21, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 22, 0,
+ 0, 57, 0, 0, 13, 0, 23, 24, 25, 26,
+ 27, 28, 253, 255, 328, 29, 30, 31, 0, 0,
+ 0, 32, 33, 0, 0, 110, 111, 34, 0, 35,
+ 36, 37, 0, 0, 254, 14, 15, 0, 16, 0,
+ 0, 0, 0, 0, 0, 18, 19, 0, 20, 0,
+ 21, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 22, 0,
+ 0, 57, 0, 0, 13, 0, 23, 24, 25, 26,
+ 27, 28, 253, 255, 0, 29, 30, 31, 0, 0,
+ 0, 32, 33, 0, 0, 110, 0, 34, 0, 35,
+ 36, 37, 0, 0, 254, 14, 15, 0, 16, 0,
+ 0, 0, 0, 0, 0, 18, 19, 0, 20, 0,
+ 21, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 57, 0, 0, 13, 0, 0, 0, 22, 0,
+ 0, 0, 253, 0, 0, 0, 23, 24, 25, 26,
+ 27, 28, 0, 0, 0, 29, 30, 31, 0, 0,
+ 0, 32, 33, 0, 254, 14, 15, 34, 16, 35,
+ 36, 37, 0, 0, 0, 18, 19, 0, 20, 0,
+ 21, 0, 0, 0, 0, 0, 0, 0, 0, 12,
+ 0, 0, 13, 143, 0, 0, 0, 0, 22, 0,
+ 0, 0, 0, 0, 0, 0, 23, 24, 25, 26,
+ 27, 28, 0, 0, 0, 29, 30, 31, 0, 0,
+ 0, 32, 33, 14, 15, 0, 16, 34, 0, 35,
+ 36, 37, 0, 18, 19, 0, 20, 0, 21, 0,
+ 0, 0, 0, 0, 0, 0, 0, 12, 0, 0,
+ 13, 151, 0, 0, 0, 0, 22, 0, 0, 0,
+ 0, 0, 0, 0, 23, 24, 25, 26, 27, 28,
+ 0, 0, 0, 29, 30, 31, 0, 0, 0, 32,
+ 33, 14, 15, 0, 16, 34, 0, 35, 36, 37,
+ 0, 18, 19, 0, 20, 0, 21, 0, 0, 0,
+ 0, 0, 0, 0, 0, 57, 0, 0, 13, 0,
+ 0, 0, 0, 0, 22, 0, 0, 0, 0, 0,
+ 0, 0, 23, 24, 25, 26, 27, 28, 0, 0,
+ 0, 29, 30, 31, 0, 0, 0, 32, 33, 14,
+ 15, 0, 16, 34, 0, 35, 36, 37, 0, 18,
+ 19, 0, 20, 0, 21, 0, 0, 0, 0, 0,
+ 0, 0, 0, 210, 0, 57, 0, 0, 13, 0,
+ 0, 0, 22, 0, 0, 0, -32, 0, 0, 0,
+ 23, 24, 25, 26, 27, 28, 0, 0, 0, 29,
+ 30, 31, 0, 0, 0, 32, 33, 0, -32, 14,
+ 15, 34, 16, 35, 36, 37, 0, 0, 0, 18,
+ 19, 0, 20, 0, 21, 0, 0, 0, 0, 0,
+ 0, 0, 0, 12, 0, 0, 13, 0, 0, 0,
+ 0, 0, 22, 0, 0, 0, 0, 0, 0, 0,
+ 23, 24, 25, 26, 27, 28, 0, 0, 0, 0,
+ 30, 31, 0, 0, 0, 32, 33, 14, 15, 0,
+ 16, 34, 0, 35, 36, 37, 0, 18, 19, 0,
+ 20, 0, 21, 0, 0, 0, 0, 0, 0, 0,
+ 0, 57, 0, 0, 13, 0, 0, 0, 0, 0,
+ 22, 0, 0, 0, 0, 0, 0, 0, 23, 24,
+ 25, 26, 27, 28, 0, 0, 0, 29, 30, 31,
+ 0, 0, 0, 32, 33, 14, 15, 0, 16, 34,
+ 0, 35, 36, 37, 0, 18, 19, 0, 20, 0,
+ 21, 0, 0, 0, 0, 0, 0, 0, 0, 178,
+ 0, 0, 13, 0, 0, 0, 0, 0, 22, 0,
+ 0, 0, 0, 0, 0, 0, 23, 24, 25, 26,
+ 27, 28, 0, 0, 0, 29, 30, 31, 0, 0,
+ 0, 32, 33, 14, 15, 0, 16, 34, 0, 35,
+ 36, 37, 0, 18, 19, 0, 20, 0, 21, 0,
+ 0, 0, 0, 0, 0, 0, 0, 294, 0, 0,
+ 13, 0, 0, 0, 0, 0, 22, 0, 0, 0,
+ 0, 0, 0, 0, 23, 24, 25, 26, 27, 28,
+ 0, 0, 0, 29, 30, 31, 0, 0, 0, 32,
+ 33, 14, 15, 0, 16, 34, 0, 35, 36, 37,
+ 0, 18, 19, 0, 20, 0, 21, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 22, 0, 0, 0, 0, 0,
+ 0, 0, 23, 24, 25, 26, 27, 28, 0, 0,
+ 0, 29, 30, 31, 0, 0, 0, 32, 33, 0,
+ 0, 0, 0, 34, 0, 35, 36, 37
+};
+
+static const yytype_int16 yycheck[] =
+{
+ 16, 66, 67, 51, 52, 178, 46, 81, 15, 244,
+ 160, 246, 338, 29, 15, 10, 32, 33, 34, 35,
+ 36, 37, 10, 110, 111, 5, 42, 167, 13, 9,
+ 10, 179, 87, 359, 18, 90, 83, 53, 70, 86,
+ 10, 70, 89, 90, 14, 109, 93, 87, 0, 89,
+ 98, 46, 68, 38, 101, 9, 41, 12, 106, 39,
+ 124, 45, 11, 93, 10, 19, 53, 54, 12, 134,
+ 253, 12, 255, 256, 257, 9, 259, 12, 110, 111,
+ 263, 110, 111, 99, 100, 19, 160, 10, 9, 324,
+ 11, 14, 87, 88, 89, 102, 103, 104, 105, 87,
+ 46, 10, 109, 104, 105, 14, 12, 123, 109, 125,
+ 126, 127, 128, 129, 130, 9, 351, 112, 165, 9,
+ 12, 294, 16, 12, 171, 12, 16, 107, 363, 145,
+ 146, 15, 148, 149, 12, 285, 18, 9, 154, 155,
+ 156, 87, 43, 89, 16, 328, 109, 295, 10, 165,
+ 298, 299, 300, 301, 12, 171, 10, 305, 9, 12,
+ 14, 148, 149, 179, 9, 16, 230, 231, 155, 156,
+ 12, 16, 322, 10, 239, 45, 192, 193, 9, 195,
+ 196, 197, 198, 199, 200, 16, 202, 15, 204, 253,
+ 206, 96, 208, 180, 210, 18, 344, 16, 338, 87,
+ 10, 217, 352, 80, 9, 9, 222, 43, 224, 189,
+ 46, 285, 16, 32, 33, 34, 84, 265, 37, 359,
+ 9, 208, 209, 42, 14, 10, 10, 16, 244, 16,
+ 246, 46, 45, 16, 53, 100, 16, 253, 12, 255,
+ 256, 257, 229, 259, 260, 261, 262, 263, 322, 68,
+ 118, 87, 88, 89, 16, 16, 320, 16, 274, 41,
+ 107, 105, 278, -1, 280, 252, 282, -1, -1, -1,
+ -1, -1, 87, 88, 89, -1, 112, -1, 352, 295,
+ 99, 100, 298, 299, 300, 301, 334, -1, -1, 305,
+ -1, 307, 308, 309, -1, 282, 283, 112, -1, 167,
+ -1, -1, -1, -1, 123, -1, 125, 126, 127, 128,
+ 129, 130, 328, -1, 361, 331, -1, 333, -1, 335,
+ 336, 308, 309, 339, -1, -1, 145, 146, 344, 148,
+ 149, 179, 312, -1, -1, 154, 155, 156, 354, -1,
+ 327, -1, -1, -1, -1, -1, 165, -1, -1, -1,
+ -1, -1, 171, -1, -1, 223, -1, -1, -1, -1,
+ 179, -1, -1, -1, -1, -1, -1, -1, 236, -1,
+ -1, -1, -1, -1, 193, -1, 195, 196, 197, 198,
+ 199, 200, -1, 202, -1, 204, 254, 206, -1, 208,
+ -1, 210, -1, -1, 16, -1, -1, -1, 217, -1,
+ -1, -1, -1, 222, -1, 224, -1, -1, -1, -1,
+ 32, 33, 34, -1, -1, 37, -1, -1, 286, -1,
+ 42, -1, -1, -1, -1, 244, -1, 246, -1, -1,
+ -1, 53, -1, -1, 253, -1, 255, 256, 257, -1,
+ 259, 260, 261, 262, 263, -1, 68, 295, -1, -1,
+ 298, 299, 300, 301, -1, 274, -1, 305, 326, 278,
+ -1, 280, -1, 282, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 295, 99, 100, 298,
+ 299, 300, 301, -1, -1, -1, 305, -1, 307, 308,
+ 309, -1, 97, -1, -1, -1, 344, -1, 103, -1,
+ -1, 123, -1, 125, 126, 127, 128, 129, 130, 328,
+ -1, -1, -1, -1, -1, -1, 335, 336, -1, -1,
+ 339, -1, -1, 145, 146, 344, 148, 149, -1, -1,
+ 135, 136, 154, 155, 156, 354, -1, -1, -1, -1,
+ -1, -1, -1, 165, -1, -1, -1, -1, -1, 171,
+ -1, -1, -1, -1, -1, 5, -1, 179, -1, -1,
+ -1, -1, 12, -1, -1, -1, -1, -1, -1, -1,
+ 175, 193, 177, 195, 196, 197, 198, 199, 200, -1,
+ 202, -1, 204, 188, 206, 190, 208, -1, 210, -1,
+ -1, -1, -1, -1, -1, 217, -1, -1, -1, -1,
+ 222, -1, 224, -1, -1, -1, 56, 57, -1, -1,
+ -1, -1, -1, -1, 64, 65, 66, 67, -1, -1,
+ 70, 71, 244, -1, 246, -1, -1, -1, -1, -1,
+ -1, 253, -1, 255, 256, 257, 86, 259, 260, 261,
+ 262, 263, -1, 93, 249, -1, -1, -1, -1, -1,
+ -1, -1, 274, -1, -1, 105, 278, 107, 280, 109,
+ 282, -1, 112, 113, 114, 115, 116, 117, -1, 119,
+ 120, 121, -1, 295, 124, -1, 298, 299, 300, 301,
+ -1, 131, -1, 305, 134, 307, 308, 309, -1, 139,
+ -1, 141, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 306, -1, -1, -1, -1, 328, -1, -1, -1,
+ -1, -1, -1, 335, 336, -1, -1, 339, 168, -1,
+ -1, -1, 344, 173, -1, -1, -1, -1, 178, -1,
+ -1, -1, 354, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 347, -1, 0, 1, -1, -1, 353, -1,
+ -1, 7, 8, -1, 10, 11, 12, 362, 14, 15,
+ -1, -1, 367, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 227, -1, -1,
+ 230, 231, -1, -1, -1, 235, -1, -1, -1, 239,
+ 46, 47, -1, 49, -1, -1, -1, -1, -1, 55,
+ 56, 57, -1, 59, -1, 61, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 268, 269,
+ 270, -1, -1, 79, -1, -1, -1, -1, -1, -1,
+ -1, 87, 88, 89, 90, 91, 92, -1, -1, -1,
+ 96, 97, 98, -1, 294, -1, 102, 103, 1, -1,
+ -1, -1, 108, -1, 110, 111, 112, 10, 11, 12,
+ -1, 14, 15, -1, -1, -1, -1, -1, 318, -1,
+ 320, -1, -1, 323, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 341, -1, 46, 47, 48, 49, 50, 51, 52,
+ 53, 54, -1, 56, 57, 58, 59, -1, 61, 62,
+ 63, -1, -1, -1, -1, -1, -1, 1, -1, -1,
+ -1, -1, -1, -1, 77, 78, 79, 11, 12, -1,
+ 14, 15, -1, 17, 87, 88, 89, 90, 91, 92,
+ -1, -1, -1, 96, 97, 98, 99, 100, -1, 102,
+ 103, -1, -1, -1, -1, 108, -1, 110, 111, 112,
+ -1, -1, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, -1, 56, 57, 58, 59, -1, 61, 62, 63,
+ -1, -1, -1, -1, -1, -1, 1, -1, -1, -1,
+ -1, -1, -1, 77, 78, 79, 11, 12, -1, 14,
+ 15, -1, 17, 87, 88, 89, 90, 91, 92, -1,
+ -1, -1, 96, 97, 98, 99, 100, -1, 102, 103,
+ -1, -1, -1, -1, 108, -1, 110, 111, 112, -1,
+ -1, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ -1, 56, 57, 58, 59, -1, 61, 62, 63, -1,
+ -1, -1, -1, -1, -1, 1, -1, -1, -1, -1,
+ -1, -1, 77, 78, 79, 11, 12, -1, 14, 15,
+ -1, 17, 87, 88, 89, 90, 91, 92, -1, -1,
+ -1, 96, 97, 98, 99, 100, -1, 102, 103, -1,
+ -1, -1, -1, 108, -1, 110, 111, 112, -1, -1,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, -1,
+ 56, 57, 58, 59, -1, 61, 62, 63, -1, -1,
+ -1, -1, -1, -1, 1, -1, -1, -1, -1, -1,
+ -1, 77, 78, 79, 11, 12, -1, 14, 15, -1,
+ 17, 87, 88, 89, 90, 91, 92, -1, -1, -1,
+ 96, 97, 98, 99, 100, -1, 102, 103, -1, -1,
+ -1, -1, 108, -1, 110, 111, 112, -1, -1, 46,
+ 47, 48, 49, 50, 51, 52, 53, 54, -1, 56,
+ 57, 58, 59, -1, 61, 62, 63, -1, -1, -1,
+ -1, -1, -1, 1, -1, -1, -1, -1, -1, -1,
+ 77, 78, 79, 11, 12, -1, 14, 15, -1, 17,
+ 87, 88, 89, 90, 91, 92, -1, -1, -1, 96,
+ 97, 98, 99, 100, -1, 102, 103, -1, -1, -1,
+ -1, 108, -1, 110, 111, 112, -1, -1, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, -1, 56, 57,
+ 58, 59, -1, 61, 62, 63, -1, -1, -1, -1,
+ -1, -1, -1, 1, -1, -1, -1, -1, -1, 77,
+ 78, 79, 10, 11, 12, -1, 14, 15, -1, 87,
+ 88, 89, 90, 91, 92, -1, -1, -1, 96, 97,
+ 98, 99, 100, -1, 102, 103, -1, -1, -1, -1,
+ 108, -1, 110, 111, 112, -1, -1, -1, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, -1, 56, 57,
+ 58, 59, -1, 61, 62, 63, -1, -1, -1, -1,
+ -1, -1, 1, -1, -1, -1, -1, -1, -1, 77,
+ 78, 79, 11, 12, -1, 14, 15, -1, 17, 87,
+ 88, 89, 90, 91, 92, -1, -1, -1, 96, 97,
+ 98, 99, 100, -1, 102, 103, -1, -1, -1, -1,
+ 108, -1, 110, 111, 112, -1, -1, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, -1, 56, 57, 58,
+ 59, -1, 61, 62, 63, -1, -1, -1, -1, -1,
+ -1, 1, -1, -1, -1, -1, -1, -1, 77, 78,
+ 79, 11, 12, -1, 14, 15, -1, 17, 87, 88,
+ 89, 90, 91, 92, -1, -1, -1, 96, 97, 98,
+ 99, 100, -1, 102, 103, -1, -1, -1, -1, 108,
+ -1, 110, 111, 112, -1, -1, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, -1, 56, 57, 58, 59,
+ -1, 61, 62, 63, -1, -1, -1, -1, -1, -1,
+ 1, -1, -1, -1, -1, -1, -1, 77, 78, 79,
+ 11, 12, -1, 14, 15, -1, -1, 87, 88, 89,
+ 90, 91, 92, -1, -1, -1, 96, 97, 98, 99,
+ 100, -1, 102, 103, -1, -1, -1, -1, 108, -1,
+ 110, 111, 112, -1, -1, 46, 47, 48, 49, 50,
+ 51, 52, 53, 54, -1, 56, 57, 58, 59, -1,
+ 61, 62, 63, -1, -1, -1, -1, -1, 1, -1,
+ -1, -1, -1, -1, -1, -1, 77, 78, 79, 12,
+ -1, 14, 15, -1, -1, -1, 87, 88, 89, 90,
+ 91, 92, -1, -1, -1, 96, 97, 98, 99, 100,
+ -1, 102, 103, -1, -1, -1, -1, 108, -1, 110,
+ 111, 112, -1, 46, 47, -1, 49, -1, 51, -1,
+ -1, -1, -1, 56, 57, -1, 59, -1, 61, -1,
+ -1, -1, -1, -1, -1, -1, 1, -1, -1, -1,
+ -1, -1, -1, -1, 77, 78, 79, 12, -1, -1,
+ 15, 16, -1, -1, 87, 88, 89, 90, 91, 92,
+ -1, -1, -1, 96, 97, 98, -1, -1, -1, 102,
+ 103, -1, -1, -1, -1, 108, -1, 110, 111, 112,
+ -1, 46, 47, -1, 49, -1, 51, -1, -1, -1,
+ -1, 56, 57, -1, 59, -1, 61, -1, -1, -1,
+ 7, 8, -1, -1, 11, 12, -1, -1, 15, -1,
+ -1, -1, 77, 78, 79, -1, -1, -1, -1, -1,
+ -1, -1, 87, 88, 89, 90, 91, 92, -1, -1,
+ -1, 96, 97, 98, -1, -1, -1, 102, 103, 46,
+ 47, -1, 49, 108, -1, 110, 111, 112, 55, 56,
+ 57, -1, 59, -1, 61, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 79, -1, -1, -1, -1, -1, -1, -1,
+ 87, 88, 89, 90, 91, 92, -1, -1, -1, 96,
+ 97, 98, -1, -1, -1, 102, 103, -1, -1, -1,
+ -1, 108, -1, 110, 111, 112, 9, -1, -1, 12,
+ 13, -1, 15, 16, -1, -1, -1, -1, -1, -1,
+ 23, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 36, 37, -1, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, -1, 49, -1, -1, -1,
+ -1, -1, -1, 56, 57, -1, 59, -1, 61, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 79, -1, -1, -1,
+ -1, -1, -1, -1, 87, 88, 89, 90, 91, 92,
+ -1, 94, -1, 96, 97, 98, -1, -1, -1, 102,
+ 103, -1, -1, -1, -1, 108, -1, 110, 111, 112,
+ 9, -1, -1, 12, 13, -1, 15, 16, -1, -1,
+ -1, -1, -1, -1, 23, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 36, 37, -1,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, -1,
+ 49, -1, -1, -1, -1, -1, -1, 56, 57, -1,
+ 59, -1, 61, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 79, -1, -1, -1, -1, -1, -1, -1, 87, 88,
+ 89, 90, 91, 92, -1, 94, -1, 96, 97, 98,
+ -1, -1, -1, 102, 103, -1, -1, -1, -1, 108,
+ -1, 110, 111, 112, 9, -1, -1, 12, 13, -1,
+ 15, 16, -1, -1, -1, -1, -1, -1, 23, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 36, 37, -1, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, -1, 49, -1, -1, -1, -1, -1,
+ -1, 56, 57, -1, 59, -1, 61, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 79, -1, -1, -1, -1, -1,
+ -1, -1, 87, 88, 89, 90, 91, 92, -1, 94,
+ -1, 96, 97, 98, -1, -1, -1, 102, 103, -1,
+ -1, -1, -1, 108, -1, 110, 111, 112, 9, -1,
+ -1, 12, 13, -1, 15, 16, -1, -1, -1, -1,
+ -1, -1, 23, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 36, 37, -1, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, -1, 49, -1,
+ -1, -1, -1, -1, -1, 56, 57, -1, 59, -1,
+ 61, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 79, -1,
+ -1, -1, -1, -1, -1, -1, 87, 88, 89, 90,
+ 91, 92, -1, 94, -1, 96, 97, 98, -1, -1,
+ 9, 102, 103, 12, 13, -1, 15, 108, -1, 110,
+ 111, 112, -1, -1, 23, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 36, 37, -1,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, -1,
+ 49, -1, -1, -1, -1, -1, -1, 56, 57, -1,
+ 59, -1, 61, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 79, -1, -1, -1, -1, -1, -1, -1, 87, 88,
+ 89, 90, 91, 92, -1, 94, -1, 96, 97, 98,
+ -1, -1, -1, 102, 103, -1, -1, -1, -1, 108,
+ -1, 110, 111, 112, 10, -1, 12, 13, 14, 15,
+ -1, -1, -1, -1, -1, -1, -1, 23, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 36, 37, -1, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, -1, 49, -1, -1, -1, -1, -1, -1,
+ 56, 57, -1, 59, -1, 61, -1, -1, -1, -1,
+ -1, -1, 10, -1, 12, -1, 14, 15, -1, -1,
+ -1, -1, -1, 79, -1, -1, -1, -1, -1, -1,
+ -1, 87, 88, 89, 90, 91, 92, -1, 94, -1,
+ 96, 97, 98, -1, -1, -1, 102, 103, 46, 47,
+ -1, 49, 108, -1, 110, 111, 112, -1, 56, 57,
+ -1, 59, -1, 61, -1, -1, -1, -1, -1, -1,
+ 10, -1, 12, -1, -1, 15, -1, -1, -1, -1,
+ -1, 79, -1, -1, -1, -1, -1, -1, -1, 87,
+ 88, 89, 90, 91, 92, -1, -1, -1, 96, 97,
+ 98, -1, -1, -1, 102, 103, 46, 47, -1, 49,
+ 108, -1, 110, 111, 112, -1, 56, 57, -1, 59,
+ -1, 61, -1, -1, -1, -1, -1, -1, 10, -1,
+ 12, -1, -1, 15, -1, -1, -1, -1, -1, 79,
+ -1, -1, -1, -1, -1, -1, -1, 87, 88, 89,
+ 90, 91, 92, -1, -1, -1, 96, 97, 98, -1,
+ -1, -1, 102, 103, 46, 47, -1, 49, 108, -1,
+ 110, 111, 112, -1, 56, 57, -1, 59, -1, 61,
+ -1, -1, -1, -1, -1, -1, 10, -1, 12, -1,
+ -1, 15, -1, -1, -1, -1, -1, 79, -1, -1,
+ -1, -1, -1, -1, -1, 87, 88, 89, 90, 91,
+ 92, -1, -1, -1, 96, 97, 98, -1, -1, -1,
+ 102, 103, 46, 47, -1, 49, 108, -1, 110, 111,
+ 112, -1, 56, 57, -1, 59, -1, 61, -1, -1,
+ -1, -1, -1, -1, 10, -1, 12, -1, -1, 15,
+ -1, -1, -1, -1, -1, 79, -1, -1, -1, -1,
+ -1, -1, -1, 87, 88, 89, 90, 91, 92, -1,
+ -1, -1, 96, 97, 98, -1, -1, -1, 102, 103,
+ 46, 47, -1, 49, 108, -1, 110, 111, 112, -1,
+ 56, 57, -1, 59, -1, 61, -1, -1, -1, -1,
+ -1, -1, 10, -1, 12, -1, -1, 15, -1, -1,
+ -1, -1, -1, 79, -1, -1, -1, -1, -1, -1,
+ -1, 87, 88, 89, 90, 91, 92, -1, -1, -1,
+ 96, 97, 98, -1, -1, -1, 102, 103, 46, 47,
+ -1, 49, 108, -1, 110, 111, 112, -1, 56, 57,
+ -1, 59, -1, 61, -1, -1, -1, -1, -1, -1,
+ 10, -1, 12, -1, -1, 15, -1, -1, -1, -1,
+ -1, 79, -1, -1, -1, -1, -1, -1, -1, 87,
+ 88, 89, 90, 91, 92, -1, -1, -1, 96, 97,
+ 98, -1, -1, -1, 102, 103, 46, 47, -1, 49,
+ 108, -1, 110, 111, 112, -1, 56, 57, -1, 59,
+ -1, 61, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 79,
+ -1, -1, -1, -1, -1, -1, -1, 87, 88, 89,
+ 90, 91, 92, -1, -1, -1, 96, 97, 98, -1,
+ -1, -1, 102, 103, -1, -1, -1, -1, 108, -1,
+ 110, 111, 112, 12, 13, -1, 15, 16, -1, -1,
+ -1, -1, -1, -1, 23, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 36, 37, -1,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, -1,
+ 49, -1, -1, -1, -1, -1, -1, 56, 57, -1,
+ 59, -1, 61, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 79, -1, -1, -1, -1, -1, -1, -1, 87, 88,
+ 89, 90, 91, 92, -1, 94, -1, 96, 97, 98,
+ -1, -1, -1, 102, 103, 12, 13, -1, 15, 108,
+ -1, 110, 111, 112, -1, -1, 23, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 36,
+ 37, -1, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, -1, 49, -1, -1, -1, -1, -1, -1, 56,
+ 57, -1, 59, -1, 61, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 79, -1, -1, -1, -1, -1, -1, -1,
+ 87, 88, 89, 90, 91, 92, -1, 94, 95, 96,
+ 97, 98, -1, -1, -1, 102, 103, -1, -1, -1,
+ -1, 108, -1, 110, 111, 112, 12, 13, -1, 15,
+ 16, -1, -1, -1, -1, -1, -1, 23, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 36, 37, -1, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, -1, 49, -1, -1, -1, -1, -1, -1,
+ 56, 57, -1, 59, -1, 61, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 79, -1, -1, -1, -1, -1, -1,
+ -1, 87, 88, 89, 90, 91, 92, -1, 94, -1,
+ 96, 97, 98, -1, -1, -1, 102, 103, -1, -1,
+ -1, -1, 108, -1, 110, 111, 112, 12, 13, -1,
+ 15, 16, -1, -1, -1, -1, -1, -1, 23, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 36, 37, -1, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, -1, 49, -1, -1, -1, -1, -1,
+ -1, 56, 57, -1, 59, -1, 61, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 79, -1, -1, -1, -1, -1,
+ -1, -1, 87, 88, 89, 90, 91, 92, -1, 94,
+ -1, 96, 97, 98, -1, -1, -1, 102, 103, -1,
+ -1, -1, -1, 108, -1, 110, 111, 112, 12, 13,
+ -1, 15, 16, -1, -1, -1, -1, -1, -1, 23,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 36, 37, -1, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, -1, 49, -1, -1, -1, -1,
+ -1, -1, 56, 57, -1, 59, -1, 61, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 79, -1, -1, -1, -1,
+ -1, -1, -1, 87, 88, 89, 90, 91, 92, -1,
+ 94, -1, 96, 97, 98, -1, -1, -1, 102, 103,
+ -1, -1, -1, -1, 108, -1, 110, 111, 112, 12,
+ 13, -1, 15, 16, -1, -1, -1, -1, -1, -1,
+ 23, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 36, 37, -1, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, -1, 49, -1, -1, -1,
+ -1, -1, -1, 56, 57, -1, 59, -1, 61, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 79, -1, -1, -1,
+ -1, -1, -1, -1, 87, 88, 89, 90, 91, 92,
+ -1, 94, -1, 96, 97, 98, -1, -1, -1, 102,
+ 103, -1, -1, -1, -1, 108, -1, 110, 111, 112,
+ 12, 13, -1, 15, 16, -1, -1, -1, -1, -1,
+ -1, 23, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 36, 37, -1, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, -1, 49, -1, -1,
+ -1, -1, -1, -1, 56, 57, -1, 59, -1, 61,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 79, -1, -1,
+ -1, -1, -1, -1, -1, 87, 88, 89, 90, 91,
+ 92, -1, 94, -1, 96, 97, 98, -1, -1, -1,
+ 102, 103, 12, 13, 14, 15, 108, -1, 110, 111,
+ 112, -1, -1, 23, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 36, 37, -1, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, -1, 49,
+ -1, -1, -1, -1, -1, -1, 56, 57, -1, 59,
+ -1, 61, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 79,
+ -1, -1, -1, -1, -1, -1, -1, 87, 88, 89,
+ 90, 91, 92, -1, 94, -1, 96, 97, 98, -1,
+ -1, -1, 102, 103, -1, -1, -1, -1, 108, -1,
+ 110, 111, 112, 12, 13, -1, 15, 16, -1, -1,
+ -1, -1, -1, -1, 23, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 36, 37, -1,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, -1,
+ 49, -1, -1, -1, -1, -1, -1, 56, 57, -1,
+ 59, -1, 61, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 79, -1, -1, -1, -1, -1, -1, -1, 87, 88,
+ 89, 90, 91, 92, -1, 94, -1, 96, 97, 98,
+ -1, -1, -1, 102, 103, 12, 13, -1, 15, 108,
+ -1, 110, 111, 112, -1, -1, 23, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 36,
+ 37, -1, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, -1, 49, -1, -1, -1, -1, -1, -1, 56,
+ 57, -1, 59, -1, 61, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 79, -1, -1, -1, -1, -1, -1, -1,
+ 87, 88, 89, 90, 91, 92, -1, 94, -1, 96,
+ 97, 98, -1, -1, -1, 102, 103, 12, 13, -1,
+ 15, 108, -1, 110, 111, 112, -1, -1, 23, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 36, -1, -1, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, -1, 49, -1, -1, -1, -1, -1,
+ -1, 56, 57, -1, 59, -1, 61, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 79, -1, -1, -1, -1, -1,
+ -1, -1, 87, 88, 89, 90, 91, 92, -1, -1,
+ -1, 96, 97, 98, -1, -1, -1, 102, 103, 12,
+ 13, -1, 15, 108, -1, 110, 111, 112, -1, -1,
+ 23, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, -1, 49, -1, -1, -1,
+ -1, -1, -1, 56, 57, -1, 59, -1, 61, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 79, -1, -1, -1,
+ -1, -1, -1, -1, 87, 88, 89, 90, 91, 92,
+ -1, -1, -1, 96, 97, 98, -1, -1, -1, 102,
+ 103, 12, 13, -1, 15, 108, -1, 110, 111, 112,
+ -1, -1, 23, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, -1, 49, -1,
+ -1, -1, -1, -1, -1, 56, 57, -1, 59, -1,
+ 61, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 79, -1,
+ -1, 12, -1, -1, 15, -1, 87, 88, 89, 90,
+ 91, 92, 23, -1, -1, -1, 97, 98, -1, -1,
+ -1, 102, 103, -1, -1, 36, 37, 108, -1, 110,
+ 111, 112, -1, -1, 45, 46, 47, -1, 49, -1,
+ -1, -1, -1, -1, -1, 56, 57, -1, 59, -1,
+ 61, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 79, -1,
+ -1, 12, -1, -1, 15, -1, 87, 88, 89, 90,
+ 91, 92, 23, 94, 95, 96, 97, 98, -1, -1,
+ -1, 102, 103, -1, -1, 36, 37, 108, -1, 110,
+ 111, 112, -1, -1, 45, 46, 47, -1, 49, -1,
+ -1, -1, -1, -1, -1, 56, 57, -1, 59, -1,
+ 61, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 79, -1,
+ -1, 12, -1, -1, 15, -1, 87, 88, 89, 90,
+ 91, 92, 23, 94, -1, 96, 97, 98, -1, -1,
+ -1, 102, 103, -1, -1, 36, -1, 108, -1, 110,
+ 111, 112, -1, -1, 45, 46, 47, -1, 49, -1,
+ -1, -1, -1, -1, -1, 56, 57, -1, 59, -1,
+ 61, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 12, -1, -1, 15, -1, -1, -1, 79, -1,
+ -1, -1, 23, -1, -1, -1, 87, 88, 89, 90,
+ 91, 92, -1, -1, -1, 96, 97, 98, -1, -1,
+ -1, 102, 103, -1, 45, 46, 47, 108, 49, 110,
+ 111, 112, -1, -1, -1, 56, 57, -1, 59, -1,
+ 61, -1, -1, -1, -1, -1, -1, -1, -1, 12,
+ -1, -1, 15, 16, -1, -1, -1, -1, 79, -1,
+ -1, -1, -1, -1, -1, -1, 87, 88, 89, 90,
+ 91, 92, -1, -1, -1, 96, 97, 98, -1, -1,
+ -1, 102, 103, 46, 47, -1, 49, 108, -1, 110,
+ 111, 112, -1, 56, 57, -1, 59, -1, 61, -1,
+ -1, -1, -1, -1, -1, -1, -1, 12, -1, -1,
+ 15, 16, -1, -1, -1, -1, 79, -1, -1, -1,
+ -1, -1, -1, -1, 87, 88, 89, 90, 91, 92,
+ -1, -1, -1, 96, 97, 98, -1, -1, -1, 102,
+ 103, 46, 47, -1, 49, 108, -1, 110, 111, 112,
+ -1, 56, 57, -1, 59, -1, 61, -1, -1, -1,
+ -1, -1, -1, -1, -1, 12, -1, -1, 15, -1,
+ -1, -1, -1, -1, 79, -1, -1, -1, -1, -1,
+ -1, -1, 87, 88, 89, 90, 91, 92, -1, -1,
+ -1, 96, 97, 98, -1, -1, -1, 102, 103, 46,
+ 47, -1, 49, 108, -1, 110, 111, 112, -1, 56,
+ 57, -1, 59, -1, 61, -1, -1, -1, -1, -1,
+ -1, -1, -1, 70, -1, 12, -1, -1, 15, -1,
+ -1, -1, 79, -1, -1, -1, 23, -1, -1, -1,
+ 87, 88, 89, 90, 91, 92, -1, -1, -1, 96,
+ 97, 98, -1, -1, -1, 102, 103, -1, 45, 46,
+ 47, 108, 49, 110, 111, 112, -1, -1, -1, 56,
+ 57, -1, 59, -1, 61, -1, -1, -1, -1, -1,
+ -1, -1, -1, 12, -1, -1, 15, -1, -1, -1,
+ -1, -1, 79, -1, -1, -1, -1, -1, -1, -1,
+ 87, 88, 89, 90, 91, 92, -1, -1, -1, -1,
+ 97, 98, -1, -1, -1, 102, 103, 46, 47, -1,
+ 49, 108, -1, 110, 111, 112, -1, 56, 57, -1,
+ 59, -1, 61, -1, -1, -1, -1, -1, -1, -1,
+ -1, 12, -1, -1, 15, -1, -1, -1, -1, -1,
+ 79, -1, -1, -1, -1, -1, -1, -1, 87, 88,
+ 89, 90, 91, 92, -1, -1, -1, 96, 97, 98,
+ -1, -1, -1, 102, 103, 46, 47, -1, 49, 108,
+ -1, 110, 111, 112, -1, 56, 57, -1, 59, -1,
+ 61, -1, -1, -1, -1, -1, -1, -1, -1, 12,
+ -1, -1, 15, -1, -1, -1, -1, -1, 79, -1,
+ -1, -1, -1, -1, -1, -1, 87, 88, 89, 90,
+ 91, 92, -1, -1, -1, 96, 97, 98, -1, -1,
+ -1, 102, 103, 46, 47, -1, 49, 108, -1, 110,
+ 111, 112, -1, 56, 57, -1, 59, -1, 61, -1,
+ -1, -1, -1, -1, -1, -1, -1, 12, -1, -1,
+ 15, -1, -1, -1, -1, -1, 79, -1, -1, -1,
+ -1, -1, -1, -1, 87, 88, 89, 90, 91, 92,
+ -1, -1, -1, 96, 97, 98, -1, -1, -1, 102,
+ 103, 46, 47, -1, 49, 108, -1, 110, 111, 112,
+ -1, 56, 57, -1, 59, -1, 61, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 79, -1, -1, -1, -1, -1,
+ -1, -1, 87, 88, 89, 90, 91, 92, -1, -1,
+ -1, 96, 97, 98, -1, -1, -1, 102, 103, -1,
+ -1, -1, -1, 108, -1, 110, 111, 112
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
+{
+ 0, 1, 10, 14, 115, 130, 132, 144, 0, 7,
+ 8, 11, 12, 15, 46, 47, 49, 55, 56, 57,
+ 59, 61, 79, 87, 88, 89, 90, 91, 92, 96,
+ 97, 98, 102, 103, 108, 110, 111, 112, 127, 133,
+ 134, 136, 139, 146, 147, 157, 158, 159, 161, 10,
+ 14, 127, 127, 139, 140, 148, 12, 12, 146, 158,
+ 159, 87, 90, 125, 12, 12, 12, 12, 43, 159,
+ 12, 12, 158, 158, 146, 158, 159, 159, 158, 1,
+ 10, 14, 48, 50, 51, 52, 53, 54, 58, 62,
+ 63, 77, 78, 99, 100, 119, 121, 126, 127, 139,
+ 143, 150, 152, 156, 162, 9, 127, 130, 13, 23,
+ 36, 37, 39, 40, 41, 42, 43, 44, 45, 94,
+ 116, 117, 158, 15, 12, 15, 102, 103, 104, 105,
+ 109, 70, 110, 111, 18, 156, 156, 9, 16, 118,
+ 16, 118, 93, 16, 137, 139, 139, 12, 139, 139,
+ 137, 16, 137, 158, 43, 139, 139, 10, 128, 129,
+ 14, 128, 151, 151, 161, 139, 151, 12, 12, 151,
+ 151, 139, 151, 12, 10, 153, 152, 156, 12, 138,
+ 141, 142, 146, 158, 159, 151, 17, 152, 155, 133,
+ 156, 134, 96, 139, 147, 139, 139, 139, 139, 139,
+ 139, 161, 139, 10, 139, 10, 139, 158, 139, 147,
+ 70, 158, 158, 158, 158, 158, 158, 139, 137, 17,
+ 17, 10, 139, 45, 139, 15, 16, 118, 87, 160,
+ 118, 118, 16, 16, 158, 118, 118, 10, 129, 18,
+ 151, 131, 150, 161, 139, 151, 139, 152, 80, 120,
+ 17, 145, 140, 23, 45, 94, 116, 117, 158, 118,
+ 13, 38, 41, 70, 152, 127, 17, 159, 95, 118,
+ 118, 158, 19, 161, 139, 16, 118, 149, 139, 147,
+ 139, 147, 139, 161, 137, 14, 45, 149, 149, 154,
+ 10, 152, 10, 16, 12, 138, 147, 161, 138, 138,
+ 138, 138, 158, 158, 158, 138, 156, 139, 139, 139,
+ 87, 10, 135, 16, 16, 16, 16, 16, 118, 16,
+ 118, 19, 14, 129, 161, 100, 45, 140, 95, 17,
+ 16, 118, 16, 118, 127, 139, 139, 147, 129, 139,
+ 149, 12, 161, 16, 138, 159, 159, 156, 16, 16,
+ 16, 131, 14, 124, 139, 16, 16, 17, 149, 129,
+ 152, 16, 123, 131, 151, 152, 149, 122, 152
+};
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+
+#define YYFAIL goto yyerrlab
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (YYID (0))
+
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (thread_stderr, "%s ", Title); \
+ yy_symbol_print (thread_stderr, \
+ Type, Value); \
+ YYFPRINTF (thread_stderr, "\n"); \
+ } \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (!yyvaluep)
+ return;
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
+#else
+static void
+yy_stack_print (bottom, top)
+ yytype_int16 *bottom;
+ yytype_int16 *top;
+#endif
+{
+ YYFPRINTF (thread_stderr, "Stack now");
+ for (; bottom <= top; ++bottom)
+ YYFPRINTF (thread_stderr, " %d", *bottom);
+ YYFPRINTF (thread_stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule)
+ YYSTYPE *yyvsp;
+ int yyrule;
+#endif
+{
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (thread_stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ fprintf (thread_stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (thread_stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ );
+ fprintf (thread_stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyvsp, Rule); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+ const char *yystr;
+#endif
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+#endif
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+ int yyn = yypact[yystate];
+
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
+ else
+ {
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
+
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
+
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
+ }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ YYUSE (yyvaluep);
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
+
+
+/* Prevent warnings from -Wmissing-prototypes. */
+
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+/* The look-ahead symbol. */
+static int yychar;
+
+/* The semantic value of the look-ahead symbol. */
+__thread YYSTYPE yylval;
+
+/* Number of syntax errors so far. */
+static int yynerrs;
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+
+ int yystate;
+ int yyn;
+ int yyresult;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+ /* Look-ahead token as an internal (translated) token number. */
+ int yytoken = 0;
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+ /* Three stacks and their tools:
+ `yyss': related to states,
+ `yyvs': related to semantic values,
+ `yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss = yyssa;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
+ YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ YYSIZE_T yystacksize = YYINITDEPTH;
+
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ YYDPRINTF ((thread_stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss;
+ yyvsp = yyvs;
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss);
+ YYSTACK_RELOCATE (yyvs);
+
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+
+ YYDPRINTF ((thread_stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((thread_stderr, "Entering state %d\n", yystate));
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ look-ahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to look-ahead token. */
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a look-ahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((thread_stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((thread_stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the look-ahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ *++yyvsp = yylval;
+
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 2:
+#line 98 "awkgram.y"
+ { if (errorflag==0)
+ winner = (Node *)stat3(PROGRAM, beginloc, (yyvsp[(1) - (1)].p), endloc); }
+ break;
+
+ case 3:
+#line 100 "awkgram.y"
+ { yyclearin; bracecheck(); SYNTAX("bailing out"); }
+ break;
+
+ case 14:
+#line 124 "awkgram.y"
+ {inloop++;}
+ break;
+
+ case 15:
+#line 125 "awkgram.y"
+ { --inloop; (yyval.p) = stat4(FOR, (yyvsp[(3) - (12)].p), notnull((yyvsp[(6) - (12)].p)), (yyvsp[(9) - (12)].p), (yyvsp[(12) - (12)].p)); }
+ break;
+
+ case 16:
+#line 126 "awkgram.y"
+ {inloop++;}
+ break;
+
+ case 17:
+#line 127 "awkgram.y"
+ { --inloop; (yyval.p) = stat4(FOR, (yyvsp[(3) - (10)].p), NIL, (yyvsp[(7) - (10)].p), (yyvsp[(10) - (10)].p)); }
+ break;
+
+ case 18:
+#line 128 "awkgram.y"
+ {inloop++;}
+ break;
+
+ case 19:
+#line 129 "awkgram.y"
+ { --inloop; (yyval.p) = stat3(IN, (yyvsp[(3) - (8)].p), makearr((yyvsp[(5) - (8)].p)), (yyvsp[(8) - (8)].p)); }
+ break;
+
+ case 20:
+#line 133 "awkgram.y"
+ { setfname((yyvsp[(1) - (1)].cp)); }
+ break;
+
+ case 21:
+#line 134 "awkgram.y"
+ { setfname((yyvsp[(1) - (1)].cp)); }
+ break;
+
+ case 22:
+#line 138 "awkgram.y"
+ { (yyval.p) = notnull((yyvsp[(3) - (4)].p)); }
+ break;
+
+ case 27:
+#line 150 "awkgram.y"
+ { (yyval.i) = 0; }
+ break;
+
+ case 29:
+#line 155 "awkgram.y"
+ { (yyval.i) = 0; }
+ break;
+
+ case 31:
+#line 161 "awkgram.y"
+ { (yyval.p) = 0; }
+ break;
+
+ case 33:
+#line 166 "awkgram.y"
+ { (yyval.p) = 0; }
+ break;
+
+ case 34:
+#line 167 "awkgram.y"
+ { (yyval.p) = (yyvsp[(2) - (3)].p); }
+ break;
+
+ case 35:
+#line 171 "awkgram.y"
+ { (yyval.p) = notnull((yyvsp[(1) - (1)].p)); }
+ break;
+
+ case 36:
+#line 175 "awkgram.y"
+ { (yyval.p) = stat2(PASTAT, (yyvsp[(1) - (1)].p), stat2(PRINT, rectonode(), NIL)); }
+ break;
+
+ case 37:
+#line 176 "awkgram.y"
+ { (yyval.p) = stat2(PASTAT, (yyvsp[(1) - (4)].p), (yyvsp[(3) - (4)].p)); }
+ break;
+
+ case 38:
+#line 177 "awkgram.y"
+ { (yyval.p) = pa2stat((yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p), stat2(PRINT, rectonode(), NIL)); }
+ break;
+
+ case 39:
+#line 178 "awkgram.y"
+ { (yyval.p) = pa2stat((yyvsp[(1) - (6)].p), (yyvsp[(3) - (6)].p), (yyvsp[(5) - (6)].p)); }
+ break;
+
+ case 40:
+#line 179 "awkgram.y"
+ { (yyval.p) = stat2(PASTAT, NIL, (yyvsp[(2) - (3)].p)); }
+ break;
+
+ case 41:
+#line 181 "awkgram.y"
+ { beginloc = linkum(beginloc, (yyvsp[(3) - (4)].p)); (yyval.p) = 0; }
+ break;
+
+ case 42:
+#line 183 "awkgram.y"
+ { endloc = linkum(endloc, (yyvsp[(3) - (4)].p)); (yyval.p) = 0; }
+ break;
+
+ case 43:
+#line 184 "awkgram.y"
+ {infunc++;}
+ break;
+
+ case 44:
+#line 185 "awkgram.y"
+ { infunc--; curfname=0; defn((Cell *)(yyvsp[(2) - (9)].p), (yyvsp[(4) - (9)].p), (yyvsp[(8) - (9)].p)); (yyval.p) = 0; }
+ break;
+
+ case 46:
+#line 190 "awkgram.y"
+ { (yyval.p) = linkum((yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 48:
+#line 195 "awkgram.y"
+ { (yyval.p) = linkum((yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 49:
+#line 199 "awkgram.y"
+ { (yyval.p) = op2((yyvsp[(2) - (3)].i), (yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 50:
+#line 201 "awkgram.y"
+ { (yyval.p) = op3(CONDEXPR, notnull((yyvsp[(1) - (5)].p)), (yyvsp[(3) - (5)].p), (yyvsp[(5) - (5)].p)); }
+ break;
+
+ case 51:
+#line 203 "awkgram.y"
+ { (yyval.p) = op2(BOR, notnull((yyvsp[(1) - (3)].p)), notnull((yyvsp[(3) - (3)].p))); }
+ break;
+
+ case 52:
+#line 205 "awkgram.y"
+ { (yyval.p) = op2(AND, notnull((yyvsp[(1) - (3)].p)), notnull((yyvsp[(3) - (3)].p))); }
+ break;
+
+ case 53:
+#line 206 "awkgram.y"
+ { (yyval.p) = op3((yyvsp[(2) - (3)].i), NIL, (yyvsp[(1) - (3)].p), (Node*)makedfa((yyvsp[(3) - (3)].s), 0)); }
+ break;
+
+ case 54:
+#line 208 "awkgram.y"
+ { if (constnode((yyvsp[(3) - (3)].p)))
+ (yyval.p) = op3((yyvsp[(2) - (3)].i), NIL, (yyvsp[(1) - (3)].p), (Node*)makedfa(strnode((yyvsp[(3) - (3)].p)), 0));
+ else
+ (yyval.p) = op3((yyvsp[(2) - (3)].i), (Node *)1, (yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 55:
+#line 212 "awkgram.y"
+ { (yyval.p) = op2(INTEST, (yyvsp[(1) - (3)].p), makearr((yyvsp[(3) - (3)].p))); }
+ break;
+
+ case 56:
+#line 213 "awkgram.y"
+ { (yyval.p) = op2(INTEST, (yyvsp[(2) - (5)].p), makearr((yyvsp[(5) - (5)].p))); }
+ break;
+
+ case 57:
+#line 214 "awkgram.y"
+ { (yyval.p) = op2(CAT, (yyvsp[(1) - (2)].p), (yyvsp[(2) - (2)].p)); }
+ break;
+
+ case 60:
+#line 220 "awkgram.y"
+ { (yyval.p) = op2((yyvsp[(2) - (3)].i), (yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 61:
+#line 222 "awkgram.y"
+ { (yyval.p) = op3(CONDEXPR, notnull((yyvsp[(1) - (5)].p)), (yyvsp[(3) - (5)].p), (yyvsp[(5) - (5)].p)); }
+ break;
+
+ case 62:
+#line 224 "awkgram.y"
+ { (yyval.p) = op2(BOR, notnull((yyvsp[(1) - (3)].p)), notnull((yyvsp[(3) - (3)].p))); }
+ break;
+
+ case 63:
+#line 226 "awkgram.y"
+ { (yyval.p) = op2(AND, notnull((yyvsp[(1) - (3)].p)), notnull((yyvsp[(3) - (3)].p))); }
+ break;
+
+ case 64:
+#line 227 "awkgram.y"
+ { (yyval.p) = op2((yyvsp[(2) - (3)].i), (yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 65:
+#line 228 "awkgram.y"
+ { (yyval.p) = op2((yyvsp[(2) - (3)].i), (yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 66:
+#line 229 "awkgram.y"
+ { (yyval.p) = op2((yyvsp[(2) - (3)].i), (yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 67:
+#line 230 "awkgram.y"
+ { (yyval.p) = op2((yyvsp[(2) - (3)].i), (yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 68:
+#line 231 "awkgram.y"
+ { (yyval.p) = op2((yyvsp[(2) - (3)].i), (yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 69:
+#line 232 "awkgram.y"
+ { (yyval.p) = op2((yyvsp[(2) - (3)].i), (yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 70:
+#line 233 "awkgram.y"
+ { (yyval.p) = op3((yyvsp[(2) - (3)].i), NIL, (yyvsp[(1) - (3)].p), (Node*)makedfa((yyvsp[(3) - (3)].s), 0)); }
+ break;
+
+ case 71:
+#line 235 "awkgram.y"
+ { if (constnode((yyvsp[(3) - (3)].p)))
+ (yyval.p) = op3((yyvsp[(2) - (3)].i), NIL, (yyvsp[(1) - (3)].p), (Node*)makedfa(strnode((yyvsp[(3) - (3)].p)), 0));
+ else
+ (yyval.p) = op3((yyvsp[(2) - (3)].i), (Node *)1, (yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 72:
+#line 239 "awkgram.y"
+ { (yyval.p) = op2(INTEST, (yyvsp[(1) - (3)].p), makearr((yyvsp[(3) - (3)].p))); }
+ break;
+
+ case 73:
+#line 240 "awkgram.y"
+ { (yyval.p) = op2(INTEST, (yyvsp[(2) - (5)].p), makearr((yyvsp[(5) - (5)].p))); }
+ break;
+
+ case 74:
+#line 241 "awkgram.y"
+ {
+ if (safe) SYNTAX("cmd | getline is unsafe");
+ else (yyval.p) = op3(GETLINE, (yyvsp[(4) - (4)].p), itonp((yyvsp[(2) - (4)].i)), (yyvsp[(1) - (4)].p)); }
+ break;
+
+ case 75:
+#line 244 "awkgram.y"
+ {
+ if (safe) SYNTAX("cmd | getline is unsafe");
+ else (yyval.p) = op3(GETLINE, (Node*)0, itonp((yyvsp[(2) - (3)].i)), (yyvsp[(1) - (3)].p)); }
+ break;
+
+ case 76:
+#line 247 "awkgram.y"
+ { (yyval.p) = op2(CAT, (yyvsp[(1) - (2)].p), (yyvsp[(2) - (2)].p)); }
+ break;
+
+ case 79:
+#line 253 "awkgram.y"
+ { (yyval.p) = linkum((yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 80:
+#line 254 "awkgram.y"
+ { (yyval.p) = linkum((yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 82:
+#line 259 "awkgram.y"
+ { (yyval.p) = linkum((yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 83:
+#line 263 "awkgram.y"
+ { (yyval.p) = rectonode(); }
+ break;
+
+ case 85:
+#line 265 "awkgram.y"
+ { (yyval.p) = (yyvsp[(2) - (3)].p); }
+ break;
+
+ case 94:
+#line 282 "awkgram.y"
+ { (yyval.p) = op3(MATCH, NIL, rectonode(), (Node*)makedfa((yyvsp[(1) - (1)].s), 0)); }
+ break;
+
+ case 95:
+#line 283 "awkgram.y"
+ { (yyval.p) = op1(NOT, notnull((yyvsp[(2) - (2)].p))); }
+ break;
+
+ case 96:
+#line 287 "awkgram.y"
+ {startreg();}
+ break;
+
+ case 97:
+#line 287 "awkgram.y"
+ { (yyval.s) = (yyvsp[(3) - (4)].s); }
+ break;
+
+ case 100:
+#line 295 "awkgram.y"
+ {
+ if (safe) SYNTAX("print | is unsafe");
+ else (yyval.p) = stat3((yyvsp[(1) - (4)].i), (yyvsp[(2) - (4)].p), itonp((yyvsp[(3) - (4)].i)), (yyvsp[(4) - (4)].p)); }
+ break;
+
+ case 101:
+#line 298 "awkgram.y"
+ {
+ if (safe) SYNTAX("print >> is unsafe");
+ else (yyval.p) = stat3((yyvsp[(1) - (4)].i), (yyvsp[(2) - (4)].p), itonp((yyvsp[(3) - (4)].i)), (yyvsp[(4) - (4)].p)); }
+ break;
+
+ case 102:
+#line 301 "awkgram.y"
+ {
+ if (safe) SYNTAX("print > is unsafe");
+ else (yyval.p) = stat3((yyvsp[(1) - (4)].i), (yyvsp[(2) - (4)].p), itonp((yyvsp[(3) - (4)].i)), (yyvsp[(4) - (4)].p)); }
+ break;
+
+ case 103:
+#line 304 "awkgram.y"
+ { (yyval.p) = stat3((yyvsp[(1) - (2)].i), (yyvsp[(2) - (2)].p), NIL, NIL); }
+ break;
+
+ case 104:
+#line 305 "awkgram.y"
+ { (yyval.p) = stat2(DELETE, makearr((yyvsp[(2) - (5)].p)), (yyvsp[(4) - (5)].p)); }
+ break;
+
+ case 105:
+#line 306 "awkgram.y"
+ { (yyval.p) = stat2(DELETE, makearr((yyvsp[(2) - (2)].p)), 0); }
+ break;
+
+ case 106:
+#line 307 "awkgram.y"
+ { (yyval.p) = exptostat((yyvsp[(1) - (1)].p)); }
+ break;
+
+ case 107:
+#line 308 "awkgram.y"
+ { yyclearin; SYNTAX("illegal statement"); }
+ break;
+
+ case 110:
+#line 317 "awkgram.y"
+ { if (!inloop) SYNTAX("break illegal outside of loops");
+ (yyval.p) = stat1(BREAK, NIL); }
+ break;
+
+ case 111:
+#line 319 "awkgram.y"
+ { if (!inloop) SYNTAX("continue illegal outside of loops");
+ (yyval.p) = stat1(CONTINUE, NIL); }
+ break;
+
+ case 112:
+#line 321 "awkgram.y"
+ {inloop++;}
+ break;
+
+ case 113:
+#line 321 "awkgram.y"
+ {--inloop;}
+ break;
+
+ case 114:
+#line 322 "awkgram.y"
+ { (yyval.p) = stat2(DO, (yyvsp[(3) - (9)].p), notnull((yyvsp[(7) - (9)].p))); }
+ break;
+
+ case 115:
+#line 323 "awkgram.y"
+ { (yyval.p) = stat1(EXIT, (yyvsp[(2) - (3)].p)); }
+ break;
+
+ case 116:
+#line 324 "awkgram.y"
+ { (yyval.p) = stat1(EXIT, NIL); }
+ break;
+
+ case 118:
+#line 326 "awkgram.y"
+ { (yyval.p) = stat3(IF, (yyvsp[(1) - (4)].p), (yyvsp[(2) - (4)].p), (yyvsp[(4) - (4)].p)); }
+ break;
+
+ case 119:
+#line 327 "awkgram.y"
+ { (yyval.p) = stat3(IF, (yyvsp[(1) - (2)].p), (yyvsp[(2) - (2)].p), NIL); }
+ break;
+
+ case 120:
+#line 328 "awkgram.y"
+ { (yyval.p) = (yyvsp[(2) - (3)].p); }
+ break;
+
+ case 121:
+#line 329 "awkgram.y"
+ { if (infunc)
+ SYNTAX("next is illegal inside a function");
+ (yyval.p) = stat1(NEXT, NIL); }
+ break;
+
+ case 122:
+#line 332 "awkgram.y"
+ { if (infunc)
+ SYNTAX("nextfile is illegal inside a function");
+ (yyval.p) = stat1(NEXTFILE, NIL); }
+ break;
+
+ case 123:
+#line 335 "awkgram.y"
+ { (yyval.p) = stat1(RETURN, (yyvsp[(2) - (3)].p)); }
+ break;
+
+ case 124:
+#line 336 "awkgram.y"
+ { (yyval.p) = stat1(RETURN, NIL); }
+ break;
+
+ case 126:
+#line 338 "awkgram.y"
+ {inloop++;}
+ break;
+
+ case 127:
+#line 338 "awkgram.y"
+ { --inloop; (yyval.p) = stat2(WHILE, (yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 128:
+#line 339 "awkgram.y"
+ { (yyval.p) = 0; }
+ break;
+
+ case 130:
+#line 344 "awkgram.y"
+ { (yyval.p) = linkum((yyvsp[(1) - (2)].p), (yyvsp[(2) - (2)].p)); }
+ break;
+
+ case 133:
+#line 352 "awkgram.y"
+ { (yyval.p) = op2(DIVEQ, (yyvsp[(1) - (4)].p), (yyvsp[(4) - (4)].p)); }
+ break;
+
+ case 134:
+#line 353 "awkgram.y"
+ { (yyval.p) = op2(ADD, (yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 135:
+#line 354 "awkgram.y"
+ { (yyval.p) = op2(MINUS, (yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 136:
+#line 355 "awkgram.y"
+ { (yyval.p) = op2(MULT, (yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 137:
+#line 356 "awkgram.y"
+ { (yyval.p) = op2(DIVIDE, (yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 138:
+#line 357 "awkgram.y"
+ { (yyval.p) = op2(DIVIDE, (yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 139:
+#line 358 "awkgram.y"
+ { (yyval.p) = op2(MOD, (yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 140:
+#line 359 "awkgram.y"
+ { (yyval.p) = op2(POWER, (yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 141:
+#line 360 "awkgram.y"
+ { (yyval.p) = op1(UMINUS, (yyvsp[(2) - (2)].p)); }
+ break;
+
+ case 142:
+#line 361 "awkgram.y"
+ { (yyval.p) = op1(UPLUS, (yyvsp[(2) - (2)].p)); }
+ break;
+
+ case 143:
+#line 362 "awkgram.y"
+ { (yyval.p) = op1(NOT, notnull((yyvsp[(2) - (2)].p))); }
+ break;
+
+ case 144:
+#line 363 "awkgram.y"
+ { (yyval.p) = op2(BLTIN, itonp((yyvsp[(1) - (3)].i)), rectonode()); }
+ break;
+
+ case 145:
+#line 364 "awkgram.y"
+ { (yyval.p) = op2(BLTIN, itonp((yyvsp[(1) - (4)].i)), (yyvsp[(3) - (4)].p)); }
+ break;
+
+ case 146:
+#line 365 "awkgram.y"
+ { (yyval.p) = op2(BLTIN, itonp((yyvsp[(1) - (1)].i)), rectonode()); }
+ break;
+
+ case 147:
+#line 366 "awkgram.y"
+ { (yyval.p) = op2(CALL, celltonode((yyvsp[(1) - (3)].cp),CVAR), NIL); }
+ break;
+
+ case 148:
+#line 367 "awkgram.y"
+ { (yyval.p) = op2(CALL, celltonode((yyvsp[(1) - (4)].cp),CVAR), (yyvsp[(3) - (4)].p)); }
+ break;
+
+ case 149:
+#line 368 "awkgram.y"
+ { (yyval.p) = op1(CLOSE, (yyvsp[(2) - (2)].p)); }
+ break;
+
+ case 150:
+#line 369 "awkgram.y"
+ { (yyval.p) = op1(PREDECR, (yyvsp[(2) - (2)].p)); }
+ break;
+
+ case 151:
+#line 370 "awkgram.y"
+ { (yyval.p) = op1(PREINCR, (yyvsp[(2) - (2)].p)); }
+ break;
+
+ case 152:
+#line 371 "awkgram.y"
+ { (yyval.p) = op1(POSTDECR, (yyvsp[(1) - (2)].p)); }
+ break;
+
+ case 153:
+#line 372 "awkgram.y"
+ { (yyval.p) = op1(POSTINCR, (yyvsp[(1) - (2)].p)); }
+ break;
+
+ case 154:
+#line 373 "awkgram.y"
+ { (yyval.p) = op3(GETLINE, (yyvsp[(2) - (4)].p), itonp((yyvsp[(3) - (4)].i)), (yyvsp[(4) - (4)].p)); }
+ break;
+
+ case 155:
+#line 374 "awkgram.y"
+ { (yyval.p) = op3(GETLINE, NIL, itonp((yyvsp[(2) - (3)].i)), (yyvsp[(3) - (3)].p)); }
+ break;
+
+ case 156:
+#line 375 "awkgram.y"
+ { (yyval.p) = op3(GETLINE, (yyvsp[(2) - (2)].p), NIL, NIL); }
+ break;
+
+ case 157:
+#line 376 "awkgram.y"
+ { (yyval.p) = op3(GETLINE, NIL, NIL, NIL); }
+ break;
+
+ case 158:
+#line 378 "awkgram.y"
+ { (yyval.p) = op2(INDEX, (yyvsp[(3) - (6)].p), (yyvsp[(5) - (6)].p)); }
+ break;
+
+ case 159:
+#line 380 "awkgram.y"
+ { SYNTAX("index() doesn't permit regular expressions");
+ (yyval.p) = op2(INDEX, (yyvsp[(3) - (6)].p), (Node*)(yyvsp[(5) - (6)].s)); }
+ break;
+
+ case 160:
+#line 382 "awkgram.y"
+ { (yyval.p) = (yyvsp[(2) - (3)].p); }
+ break;
+
+ case 161:
+#line 384 "awkgram.y"
+ { (yyval.p) = op3(MATCHFCN, NIL, (yyvsp[(3) - (6)].p), (Node*)makedfa((yyvsp[(5) - (6)].s), 1)); }
+ break;
+
+ case 162:
+#line 386 "awkgram.y"
+ { if (constnode((yyvsp[(5) - (6)].p)))
+ (yyval.p) = op3(MATCHFCN, NIL, (yyvsp[(3) - (6)].p), (Node*)makedfa(strnode((yyvsp[(5) - (6)].p)), 1));
+ else
+ (yyval.p) = op3(MATCHFCN, (Node *)1, (yyvsp[(3) - (6)].p), (yyvsp[(5) - (6)].p)); }
+ break;
+
+ case 163:
+#line 390 "awkgram.y"
+ { (yyval.p) = celltonode((yyvsp[(1) - (1)].cp), CCON); }
+ break;
+
+ case 164:
+#line 392 "awkgram.y"
+ { (yyval.p) = op4(SPLIT, (yyvsp[(3) - (8)].p), makearr((yyvsp[(5) - (8)].p)), (yyvsp[(7) - (8)].p), (Node*)STRING); }
+ break;
+
+ case 165:
+#line 394 "awkgram.y"
+ { (yyval.p) = op4(SPLIT, (yyvsp[(3) - (8)].p), makearr((yyvsp[(5) - (8)].p)), (Node*)makedfa((yyvsp[(7) - (8)].s), 1), (Node *)REGEXPR); }
+ break;
+
+ case 166:
+#line 396 "awkgram.y"
+ { (yyval.p) = op4(SPLIT, (yyvsp[(3) - (6)].p), makearr((yyvsp[(5) - (6)].p)), NIL, (Node*)STRING); }
+ break;
+
+ case 167:
+#line 397 "awkgram.y"
+ { (yyval.p) = op1((yyvsp[(1) - (4)].i), (yyvsp[(3) - (4)].p)); }
+ break;
+
+ case 168:
+#line 398 "awkgram.y"
+ { (yyval.p) = celltonode((yyvsp[(1) - (1)].cp), CCON); }
+ break;
+
+ case 169:
+#line 400 "awkgram.y"
+ { (yyval.p) = op4((yyvsp[(1) - (6)].i), NIL, (Node*)makedfa((yyvsp[(3) - (6)].s), 1), (yyvsp[(5) - (6)].p), rectonode()); }
+ break;
+
+ case 170:
+#line 402 "awkgram.y"
+ { if (constnode((yyvsp[(3) - (6)].p)))
+ (yyval.p) = op4((yyvsp[(1) - (6)].i), NIL, (Node*)makedfa(strnode((yyvsp[(3) - (6)].p)), 1), (yyvsp[(5) - (6)].p), rectonode());
+ else
+ (yyval.p) = op4((yyvsp[(1) - (6)].i), (Node *)1, (yyvsp[(3) - (6)].p), (yyvsp[(5) - (6)].p), rectonode()); }
+ break;
+
+ case 171:
+#line 407 "awkgram.y"
+ { (yyval.p) = op4((yyvsp[(1) - (8)].i), NIL, (Node*)makedfa((yyvsp[(3) - (8)].s), 1), (yyvsp[(5) - (8)].p), (yyvsp[(7) - (8)].p)); }
+ break;
+
+ case 172:
+#line 409 "awkgram.y"
+ { if (constnode((yyvsp[(3) - (8)].p)))
+ (yyval.p) = op4((yyvsp[(1) - (8)].i), NIL, (Node*)makedfa(strnode((yyvsp[(3) - (8)].p)), 1), (yyvsp[(5) - (8)].p), (yyvsp[(7) - (8)].p));
+ else
+ (yyval.p) = op4((yyvsp[(1) - (8)].i), (Node *)1, (yyvsp[(3) - (8)].p), (yyvsp[(5) - (8)].p), (yyvsp[(7) - (8)].p)); }
+ break;
+
+ case 173:
+#line 414 "awkgram.y"
+ { (yyval.p) = op3(SUBSTR, (yyvsp[(3) - (8)].p), (yyvsp[(5) - (8)].p), (yyvsp[(7) - (8)].p)); }
+ break;
+
+ case 174:
+#line 416 "awkgram.y"
+ { (yyval.p) = op3(SUBSTR, (yyvsp[(3) - (6)].p), (yyvsp[(5) - (6)].p), NIL); }
+ break;
+
+ case 177:
+#line 422 "awkgram.y"
+ { (yyval.p) = op2(ARRAY, makearr((yyvsp[(1) - (4)].p)), (yyvsp[(3) - (4)].p)); }
+ break;
+
+ case 178:
+#line 423 "awkgram.y"
+ { (yyval.p) = op1(INDIRECT, celltonode((yyvsp[(1) - (1)].cp), CVAR)); }
+ break;
+
+ case 179:
+#line 424 "awkgram.y"
+ { (yyval.p) = op1(INDIRECT, (yyvsp[(2) - (2)].p)); }
+ break;
+
+ case 180:
+#line 428 "awkgram.y"
+ { arglist = (yyval.p) = 0; }
+ break;
+
+ case 181:
+#line 429 "awkgram.y"
+ { arglist = (yyval.p) = celltonode((yyvsp[(1) - (1)].cp),CVAR); }
+ break;
+
+ case 182:
+#line 430 "awkgram.y"
+ {
+ checkdup((yyvsp[(1) - (3)].p), (yyvsp[(3) - (3)].cp));
+ arglist = (yyval.p) = linkum((yyvsp[(1) - (3)].p),celltonode((yyvsp[(3) - (3)].cp),CVAR)); }
+ break;
+
+ case 183:
+#line 436 "awkgram.y"
+ { (yyval.p) = celltonode((yyvsp[(1) - (1)].cp), CVAR); }
+ break;
+
+ case 184:
+#line 437 "awkgram.y"
+ { (yyval.p) = op1(ARG, itonp((yyvsp[(1) - (1)].i))); }
+ break;
+
+ case 185:
+#line 438 "awkgram.y"
+ { (yyval.p) = op1(VARNF, (Node *) (yyvsp[(1) - (1)].cp)); }
+ break;
+
+ case 186:
+#line 443 "awkgram.y"
+ { (yyval.p) = notnull((yyvsp[(3) - (4)].p)); }
+ break;
+
+
+/* Line 1267 of yacc.c. */
+#line 3496 "y.tab.c"
+ default: break;
+ }
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (YY_("syntax error"));
+#else
+ {
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ }
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (yymsg);
+ }
+ else
+ {
+ yyerror (YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
+ }
+#endif
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse look-ahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse look-ahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ *++yyvsp = yylval;
+
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#ifndef yyoverflow
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEOF && yychar != YYEMPTY)
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval);
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
+}
+
+
+#line 446 "awkgram.y"
+
+
+void setfname(Cell *p)
+{
+ if (isarr(p))
+ SYNTAX("%s is an array, not a function", p->nval);
+ else if (isfcn(p))
+ SYNTAX("you can't define function %s more than once", p->nval);
+ curfname = p->nval;
+}
+
+int constnode(Node *p)
+{
+ return isvalue(p) && ((Cell *) (p->narg[0]))->csub == CCON;
+}
+
+char *strnode(Node *p)
+{
+ return ((Cell *)(p->narg[0]))->sval;
+}
+
+Node *notnull(Node *n)
+{
+ switch (n->nobj) {
+ case LE: case LT: case EQ: case NE: case GT: case GE:
+ case BOR: case AND: case NOT:
+ return n;
+ default:
+ return op2(NE, n, nullnode);
+ }
+}
+
+void checkdup(Node *vl, Cell *cp) /* check if name already in list */
+{
+ char *s = cp->nval;
+ for ( ; vl; vl = vl->nnext) {
+ if (strcmp(s, ((Cell *)(vl->narg[0]))->nval) == 0) {
+ SYNTAX("duplicate argument %s", s);
+ break;
+ }
+ }
+}
+
diff --git a/awk/Sources/awk/ytab.h b/awk/Sources/awk/ytab.h
new file mode 100644
index 00000000..be2f9c97
--- /dev/null
+++ b/awk/Sources/awk/ytab.h
@@ -0,0 +1,257 @@
+/* A Bison parser, made by GNU Bison 2.3. */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ FIRSTTOKEN = 258,
+ PROGRAM = 259,
+ PASTAT = 260,
+ PASTAT2 = 261,
+ XBEGIN = 262,
+ XEND = 263,
+ NL = 264,
+ ARRAY = 265,
+ MATCH = 266,
+ NOTMATCH = 267,
+ MATCHOP = 268,
+ FINAL = 269,
+ DOT = 270,
+ ALL = 271,
+ CCL = 272,
+ NCCL = 273,
+ CHAR = 274,
+ OR = 275,
+ STAR = 276,
+ QUEST = 277,
+ PLUS = 278,
+ EMPTYRE = 279,
+ IGNORE_PRIOR_ATOM = 280,
+ AND = 281,
+ BOR = 282,
+ APPEND = 283,
+ EQ = 284,
+ GE = 285,
+ GT = 286,
+ LE = 287,
+ LT = 288,
+ NE = 289,
+ IN = 290,
+ ARG = 291,
+ BLTIN = 292,
+ BREAK = 293,
+ CLOSE = 294,
+ CONTINUE = 295,
+ DELETE = 296,
+ DO = 297,
+ EXIT = 298,
+ FOR = 299,
+ FUNC = 300,
+ SUB = 301,
+ GSUB = 302,
+ IF = 303,
+ INDEX = 304,
+ LSUBSTR = 305,
+ MATCHFCN = 306,
+ NEXT = 307,
+ NEXTFILE = 308,
+ ADD = 309,
+ MINUS = 310,
+ MULT = 311,
+ DIVIDE = 312,
+ MOD = 313,
+ ASSIGN = 314,
+ ASGNOP = 315,
+ ADDEQ = 316,
+ SUBEQ = 317,
+ MULTEQ = 318,
+ DIVEQ = 319,
+ MODEQ = 320,
+ POWEQ = 321,
+ PRINT = 322,
+ PRINTF = 323,
+ SPRINTF = 324,
+ ELSE = 325,
+ INTEST = 326,
+ CONDEXPR = 327,
+ POSTINCR = 328,
+ PREINCR = 329,
+ POSTDECR = 330,
+ PREDECR = 331,
+ VAR = 332,
+ IVAR = 333,
+ VARNF = 334,
+ CALL = 335,
+ NUMBER = 336,
+ STRING = 337,
+ REGEXPR = 338,
+ GETLINE = 339,
+ SUBSTR = 340,
+ SPLIT = 341,
+ RETURN = 342,
+ WHILE = 343,
+ CAT = 344,
+ UPLUS = 345,
+ UMINUS = 346,
+ NOT = 347,
+ POWER = 348,
+ INCR = 349,
+ DECR = 350,
+ INDIRECT = 351,
+ LASTTOKEN = 352
+ };
+#endif
+/* Tokens. */
+#define FIRSTTOKEN 258
+#define PROGRAM 259
+#define PASTAT 260
+#define PASTAT2 261
+#define XBEGIN 262
+#define XEND 263
+#define NL 264
+#define ARRAY 265
+#define MATCH 266
+#define NOTMATCH 267
+#define MATCHOP 268
+#define FINAL 269
+#define DOT 270
+#define ALL 271
+#define CCL 272
+#define NCCL 273
+#define CHAR 274
+#define OR 275
+#define STAR 276
+#define QUEST 277
+#define PLUS 278
+#define EMPTYRE 279
+#define IGNORE_PRIOR_ATOM 280
+#define AND 281
+#define BOR 282
+#define APPEND 283
+#define EQ 284
+#define GE 285
+#define GT 286
+#define LE 287
+#define LT 288
+#define NE 289
+#define IN 290
+#define ARG 291
+#define BLTIN 292
+#define BREAK 293
+#define CLOSE 294
+#define CONTINUE 295
+#define DELETE 296
+#define DO 297
+#define EXIT 298
+#define FOR 299
+#define FUNC 300
+#define SUB 301
+#define GSUB 302
+#define IF 303
+#define INDEX 304
+#define LSUBSTR 305
+#define MATCHFCN 306
+#define NEXT 307
+#define NEXTFILE 308
+#define ADD 309
+#define MINUS 310
+#define MULT 311
+#define DIVIDE 312
+#define MOD 313
+#define ASSIGN 314
+#define ASGNOP 315
+#define ADDEQ 316
+#define SUBEQ 317
+#define MULTEQ 318
+#define DIVEQ 319
+#define MODEQ 320
+#define POWEQ 321
+#define PRINT 322
+#define PRINTF 323
+#define SPRINTF 324
+#define ELSE 325
+#define INTEST 326
+#define CONDEXPR 327
+#define POSTINCR 328
+#define PREINCR 329
+#define POSTDECR 330
+#define PREDECR 331
+#define VAR 332
+#define IVAR 333
+#define VARNF 334
+#define CALL 335
+#define NUMBER 336
+#define STRING 337
+#define REGEXPR 338
+#define GETLINE 339
+#define SUBSTR 340
+#define SPLIT 341
+#define RETURN 342
+#define WHILE 343
+#define CAT 344
+#define UPLUS 345
+#define UMINUS 346
+#define NOT 347
+#define POWER 348
+#define INCR 349
+#define DECR 350
+#define INDIRECT 351
+#define LASTTOKEN 352
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 41 "awkgram.y"
+{
+ Node *p;
+ Cell *cp;
+ int i;
+ char *s;
+}
+/* Line 1529 of yacc.c. */
+#line 250 "y.tab.h"
+ YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+extern __thread YYSTYPE yylval;
+
diff --git a/awk/Sources/ios_error.h b/awk/Sources/ios_error.h
new file mode 100644
index 00000000..a4490144
--- /dev/null
+++ b/awk/Sources/ios_error.h
@@ -0,0 +1,103 @@
+//
+// error.h
+// shell_cmds_ios
+//
+// Created by Nicolas Holzschuch on 16/06/2017.
+// Copyright © 2017 Nicolas Holzschuch. All rights reserved.
+//
+
+#ifndef ios_error_h
+#define ios_error_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#include
+
+/* #define errx compileError
+#define err compileError
+#define warn compileError
+#define warnx compileError
+#ifndef printf
+#define printf(...) fprintf (thread_stdout, ##__VA_ARGS__)
+#endif */
+
+#define putchar(a) fputc(a, thread_stdout)
+#define getchar() fgetc(thread_stdin)
+// these functions are defined differently in C++. The #define approach breaks things.
+#ifndef __cplusplus
+ #define getwchar() fgetwc(thread_stdin)
+ #define putwchar(a) fputwc(a, thread_stdout)
+ // iswprint depends on the given locale, and setlocale() fails on iOS:
+ #define iswprint(a) 1
+ #define write ios_write
+ #define fwrite ios_fwrite
+ #define puts ios_puts
+ #define fputs ios_fputs
+ #define fputc ios_fputc
+ #define putw ios_putw
+ #define fflush ios_fflush
+#endif
+
+// Thread-local input and output streams
+extern __thread FILE* thread_stdin;
+extern __thread FILE* thread_stdout;
+extern __thread FILE* thread_stderr;
+
+#define exit ios_exit
+#define abort() ios_exit(1)
+#define _exit ios_exit
+#define kill ios_killpid
+#define _kill ios_killpid
+#define killpg ios_killpid
+#define popen ios_popen
+#define pclose fclose
+#define system ios_system
+#define execv ios_execv
+#define execvp ios_execv
+#define execve ios_execve
+#define dup2 ios_dup2
+#define getenv ios_getenv
+
+extern int ios_executable(const char* cmd); // is this command part of the "shell" commands?
+extern int ios_system(const char* inputCmd); // execute this command (executable file or builtin command)
+extern FILE *ios_popen(const char *command, const char *type); // Execute this command and pipe the result
+extern int ios_kill(void); // kill the current running command
+extern int ios_killpid(pid_t pid, int sig); // kill the current running command
+
+extern void ios_exit(int errorCode) __dead2; // set error code and exits from the thread.
+extern int ios_execv(const char *path, char* const argv[]);
+extern int ios_execve(const char *path, char* const argv[], char** envlist);
+extern int ios_dup2(int fd1, int fd2);
+extern char * ios_getenv(const char *name);
+
+extern int ios_isatty(int fd);
+extern pthread_t ios_getLastThreadId(void); // deprecated
+extern pthread_t ios_getThreadId(pid_t pid);
+extern void ios_storeThreadId(pthread_t thread);
+extern void ios_releaseThread(pthread_t thread);
+extern void ios_releaseThreadId(pid_t pid);
+extern pid_t ios_currentPid(void);
+extern int ios_getCommandStatus(void);
+extern const char* ios_progname(void);
+extern pid_t ios_fork(void);
+extern void ios_waitpid(pid_t pid);
+extern void ios_signal(int signal);
+
+extern ssize_t ios_write(int fildes, const void *buf, size_t nbyte);
+extern size_t ios_fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream);
+extern int ios_puts(const char *s);
+extern int ios_fputs(const char* s, FILE *stream);
+extern int ios_fputc(int c, FILE *stream);
+extern int ios_putw(int w, FILE *stream);
+extern int ios_fflush(FILE *stream);
+extern int ios_gettty(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* ios_error_h */
diff --git a/awk/Tests/LinuxMain.swift b/awk/Tests/LinuxMain.swift
new file mode 100644
index 00000000..acc48e88
--- /dev/null
+++ b/awk/Tests/LinuxMain.swift
@@ -0,0 +1,7 @@
+import XCTest
+
+import awkTests
+
+var tests = [XCTestCaseEntry]()
+tests += awkTests.allTests()
+XCTMain(tests)
diff --git a/awk/Tests/awkTests/XCTestManifests.swift b/awk/Tests/awkTests/XCTestManifests.swift
new file mode 100644
index 00000000..eab6d697
--- /dev/null
+++ b/awk/Tests/awkTests/XCTestManifests.swift
@@ -0,0 +1,9 @@
+import XCTest
+
+#if !canImport(ObjectiveC)
+public func allTests() -> [XCTestCaseEntry] {
+ return [
+ testCase(awkTests.allTests),
+ ]
+}
+#endif
diff --git a/awk/Tests/awkTests/awkTests.swift b/awk/Tests/awkTests/awkTests.swift
new file mode 100644
index 00000000..f695f0d8
--- /dev/null
+++ b/awk/Tests/awkTests/awkTests.swift
@@ -0,0 +1,15 @@
+import XCTest
+@testable import awk
+
+final class awkTests: XCTestCase {
+ func testExample() {
+ // This is an example of a functional test case.
+ // Use XCTAssert and related functions to verify your tests produce the correct
+ // results.
+ XCTAssertEqual(awk().text, "Hello, World!")
+ }
+
+ static var allTests = [
+ ("testExample", testExample),
+ ]
+}
diff --git a/awk/awk.h b/awk/awk.h
deleted file mode 100644
index cfd092e4..00000000
--- a/awk/awk.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// awk.h
-// awk
-//
-// Created by Nicolas Holzschuch on 25/03/2018.
-// Copyright © 2018 Nicolas Holzschuch. All rights reserved.
-//
-
-#import
-
-//! Project version number for awk.
-FOUNDATION_EXPORT double awkVersionNumber;
-
-//! Project version string for awk.
-FOUNDATION_EXPORT const unsigned char awkVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/curl_ios_static.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/curl_ios_static.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 00000000..18d98100
--- /dev/null
+++ b/curl_ios_static.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/curl_ios_static.xcodeproj/xcuserdata/holzschu.xcuserdatad/xcschemes/xcschememanagement.plist b/curl_ios_static.xcodeproj/xcuserdata/holzschu.xcuserdatad/xcschemes/xcschememanagement.plist
index 3a332fc4..fdb1e399 100644
--- a/curl_ios_static.xcodeproj/xcuserdata/holzschu.xcuserdatad/xcschemes/xcschememanagement.plist
+++ b/curl_ios_static.xcodeproj/xcuserdata/holzschu.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -14,6 +14,11 @@
orderHint
7
+ curl_ios_static.xcscheme_^#shared#^_
+
+ orderHint
+ 7
+
diff --git a/files/.gitignore b/files/.gitignore
new file mode 100644
index 00000000..95c43209
--- /dev/null
+++ b/files/.gitignore
@@ -0,0 +1,5 @@
+.DS_Store
+/.build
+/Packages
+/*.xcodeproj
+xcuserdata/
diff --git a/files/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/files/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 00000000..919434a6
--- /dev/null
+++ b/files/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/files/.swiftpm/xcode/xcshareddata/xcschemes/files.xcscheme b/files/.swiftpm/xcode/xcshareddata/xcschemes/files.xcscheme
new file mode 100644
index 00000000..352da58d
--- /dev/null
+++ b/files/.swiftpm/xcode/xcshareddata/xcschemes/files.xcscheme
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/files/Package.swift b/files/Package.swift
new file mode 100644
index 00000000..495bdad3
--- /dev/null
+++ b/files/Package.swift
@@ -0,0 +1,36 @@
+// swift-tools-version:5.2
+// The swift-tools-version declares the minimum version of Swift required to build this package.
+
+import PackageDescription
+
+let package = Package(
+ name: "files",
+ // thread-local variables are only available with iOS 11+. This setting is required for compilation.
+ platforms: [.iOS(.v11)],
+ products: [
+ // Products define the executables and libraries produced by a package, and make them visible to other packages.
+ .library(
+ name: "files",
+ targets: ["files"]),
+ ],
+ dependencies: [
+ // Dependencies declare other packages that this package depends on.
+ // .package(url: /* package url */, from: "1.0.0"),
+ // Depends on the local package, ios_system:
+ .package(path: "../ios_system")
+ ],
+ targets: [
+ // Targets are the basic building blocks of a package. A target can define a module or a test suite.
+ // Targets can depend on other targets in this package, and on products in packages which this package depends on.
+ .target(
+ name: "files",
+ dependencies: ["ios_system"],
+ exclude: ["gzip/unbzip2.c", "gzip/zuncompress.c", "gzip/unpack.c"],
+ cSettings: [.define("COLORLS", to: "1"),
+ .headerSearchPath("./"),
+ .headerSearchPath("../"),
+ .unsafeFlags([""])],
+ linkerSettings: [.linkedLibrary("libz2"), .linkedLibrary("libncurses")]
+ ),
+ ]
+)
diff --git a/files/README.md b/files/README.md
new file mode 100644
index 00000000..3de1e0a3
--- /dev/null
+++ b/files/README.md
@@ -0,0 +1,8 @@
+# files: command for processing files
+
+Swift package for all commands for processing files: chflags, chmod, chown, cksum, compress, cp, df, du, gzip, less, ln, ls, mkdir, mv, rm, rmdir, stat, touch.
+
+This package depends on the `ios_system` package (also included in this repository).
+
+The `ios_error.h` file was copied from `ios_system` (because C compilers have issues with loading files from inside a package).
+TODO: make it a resource downloaded from the repository (will require the next version of Xcode, currently in beta).
diff --git a/files/Sources/files/chflags/chflags.1 b/files/Sources/files/chflags/chflags.1
new file mode 100644
index 00000000..5eb3dfc8
--- /dev/null
+++ b/files/Sources/files/chflags/chflags.1
@@ -0,0 +1,193 @@
+.\"-
+.\" Copyright (c) 1989, 1990, 1993, 1994
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the Institute of Electrical and Electronics Engineers, Inc.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)chflags.1 8.4 (Berkeley) 5/2/95
+.\" $FreeBSD: src/bin/chflags/chflags.1,v 1.30.2.1.2.1 2009/10/25 01:10:29 kensmith Exp $
+.\"
+.Dd March 3, 2006
+.Dt CHFLAGS 1
+.Os
+.Sh NAME
+.Nm chflags
+.Nd change file flags
+.Sh SYNOPSIS
+.Nm
+.Op Fl fhv
+.Oo
+.Fl R
+.Op Fl H | Fl L | Fl P
+.Oc
+.Ar flags
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility modifies the file flags of the listed files
+as specified by the
+.Ar flags
+operand.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl f
+Do not display a diagnostic message if
+.Nm
+could not modify the flags for
+.Va file ,
+nor modify the exit status to reflect such failures.
+.It Fl H
+If the
+.Fl R
+option is specified, symbolic links on the command line are followed.
+(Symbolic links encountered in the tree traversal are not followed.)
+.It Fl h
+If the
+.Ar file
+is a symbolic link,
+change the file flags of the link itself rather than the file to which it points.
+.It Fl L
+If the
+.Fl R
+option is specified, all symbolic links are followed.
+.It Fl P
+If the
+.Fl R
+option is specified, no symbolic links are followed.
+This is the default.
+.It Fl R
+Change the file flags for the file hierarchies rooted
+in the files instead of just the files themselves.
+.It Fl v
+Cause
+.Nm
+to be verbose, showing filenames as the flags are modified.
+If the
+.Fl v
+option is specified more than once, the old and new flags of the file
+will also be printed, in octal notation.
+.El
+.Pp
+The flags are specified as an octal number or a comma separated list
+of keywords.
+The following keywords are currently defined:
+.Pp
+.Bl -tag -offset indent -width ".Cm opaque"
+.It Cm arch , archived
+set the archived flag (super-user only)
+.It Cm opaque
+set the opaque flag (owner or super-user only).
+[Directory is opaque when viewed through a union mount]
+.It Cm nodump
+set the nodump flag (owner or super-user only)
+.It Cm sappnd , sappend
+set the system append-only flag (super-user only)
+.It Cm schg , schange , simmutable
+set the system immutable flag (super-user only)
+.It Cm uappnd , uappend
+set the user append-only flag (owner or super-user only)
+.It Cm uchg , uchange , uimmutable
+set the user immutable flag (owner or super-user only)
+.It Cm hidden
+set the hidden flag
+[Hide item from GUI]
+.El
+.Pp
+As discussed in
+.Xr chflags 2 ,
+the
+.Ar sappnd
+and
+.Ar schg
+flags may only be unset when the system is in single-user mode.
+.Pp
+Putting the letters
+.Dq Ar no
+before or removing the letters
+.Dq Ar no
+from a keyword causes the flag to be cleared.
+For example:
+.Pp
+.Bl -tag -offset indent -width "nouchg" -compact
+.It Ar nouchg
+clear the user immutable flag (owner or super-user only)
+.It Ar dump
+clear the nodump flag (owner or super-user only)
+.El
+.Pp
+Unless the
+.Fl H
+or
+.Fl L
+options are given,
+.Nm
+on a symbolic link always succeeds and has no effect.
+The
+.Fl H ,
+.Fl L
+and
+.Fl P
+options are ignored unless the
+.Fl R
+option is specified.
+In addition, these options override each other and the
+command's actions are determined by the last one specified.
+.Pp
+You can use "ls -lO" to see the flags of existing files.
+.Sh EXIT STATUS
+.Ex -std
+.Sh SEE ALSO
+.Xr ls 1 ,
+.Xr chflags 2 ,
+.Xr stat 2 ,
+.Xr fts 3 ,
+.Xr symlink 7
+.Sh HISTORY
+The
+.Nm
+command first appeared in
+.Bx 4.4 .
+.Sh BUGS
+Only a limited number of utilities are
+.Nm
+aware.
+Some of these tools include
+.Xr ls 1 ,
+.Xr cp 1 ,
+.Xr find 1 ,
+.Xr install 1 ,
+.Xr dump 8 ,
+and
+.Xr restore 8 .
+In particular a tool which is not currently
+.Nm
+aware is the
+.Xr pax 1
+utility.
diff --git a/files/Sources/files/chflags/chflags.c b/files/Sources/files/chflags/chflags.c
new file mode 100644
index 00000000..8f5d478c
--- /dev/null
+++ b/files/Sources/files/chflags/chflags.c
@@ -0,0 +1,214 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1992, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif
+
+#ifndef lint
+static char sccsid[] = "@(#)chflags.c 8.5 (Berkeley) 4/1/94";
+#endif
+#endif
+
+#include
+__FBSDID("$FreeBSD: src/bin/chflags/chflags.c,v 1.26.2.1.2.1 2009/10/25 01:10:29 kensmith Exp $");
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "ios_error.h"
+
+
+static void usage(void);
+
+int
+chflags_main(int argc, char *argv[])
+{
+ FTS *ftsp;
+ FTSENT *p;
+ u_long clear, newflags, set;
+ long val;
+ int Hflag, Lflag, Rflag, fflag, hflag, vflag;
+ int ch, fts_options, oct, rval;
+ char *flags, *ep;
+ int (*change_flags)(const char *, u_int);
+
+ Hflag = Lflag = Rflag = fflag = hflag = vflag = 0;
+ optind = 1; opterr = 1; optreset = 1;
+
+ while ((ch = getopt(argc, argv, "HLPRfhv")) != -1)
+ switch (ch) {
+ case 'H':
+ Hflag = 1;
+ Lflag = 0;
+ break;
+ case 'L':
+ Lflag = 1;
+ Hflag = 0;
+ break;
+ case 'P':
+ Hflag = Lflag = 0;
+ break;
+ case 'R':
+ Rflag = 1;
+ break;
+ case 'f':
+ fflag = 1;
+ break;
+ case 'h':
+ hflag = 1;
+ break;
+ case 'v':
+ vflag++;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argv += optind;
+ argc -= optind;
+
+ if (argc < 2)
+ usage();
+
+ if (Rflag) {
+ fts_options = FTS_PHYSICAL;
+ if (hflag) {
+ errx(1, "the -R and -h options "
+ "may not be specified together");
+ }
+ if (Hflag)
+ fts_options |= FTS_COMFOLLOW;
+ if (Lflag) {
+ fts_options &= ~FTS_PHYSICAL;
+ fts_options |= FTS_LOGICAL;
+ }
+ } else
+ fts_options = hflag ? FTS_PHYSICAL : FTS_LOGICAL;
+
+ if (hflag)
+ change_flags = lchflags;
+ else
+ change_flags = chflags;
+
+ flags = *argv;
+ if (*flags >= '0' && *flags <= '7') {
+ errno = 0;
+ val = strtol(flags, &ep, 8);
+ if (val < 0)
+ errno = ERANGE;
+ if (errno) {
+ err(1, "invalid flags: %s", flags);
+ }
+ if (*ep) {
+ errx(1, "invalid flags: %s", flags);
+ }
+ set = val;
+ oct = 1;
+ } else {
+ if (strtofflags(&flags, &set, &clear)) {
+ errx(1, "invalid flag: %s", flags);
+ }
+ clear = ~clear;
+ oct = 0;
+ }
+
+ if ((ftsp = fts_open(++argv, fts_options , 0)) == NULL) {
+ err(1, NULL);
+ }
+
+ for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
+ switch (p->fts_info) {
+ case FTS_D: /* Change it at FTS_DP if we're recursive. */
+ if (!Rflag)
+ fts_set(ftsp, p, FTS_SKIP);
+ continue;
+ case FTS_DNR: /* Warn, chflag, continue. */
+ warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
+ rval = 1;
+ break;
+ case FTS_ERR: /* Warn, continue. */
+ case FTS_NS:
+ warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
+ rval = 1;
+ continue;
+ case FTS_SL: /* Ignore. */
+ case FTS_SLNONE:
+ /*
+ * The only symlinks that end up here are ones that
+ * don't point to anything and ones that we found
+ * doing a physical walk.
+ */
+ if (!hflag)
+ continue;
+ /* FALLTHROUGH */
+ default:
+ break;
+ }
+ if (oct)
+ newflags = set;
+ else
+ newflags = (p->fts_statp->st_flags | set) & clear;
+ if (newflags == p->fts_statp->st_flags)
+ continue;
+ if ((*change_flags)(p->fts_accpath, (u_int)newflags) && !fflag) {
+ warn("%s", p->fts_path);
+ rval = 1;
+ } else if (vflag) {
+ (void)fprintf(thread_stdout, "%s", p->fts_path);
+ if (vflag > 1)
+ (void)fprintf(thread_stdout, ": 0%lo -> 0%lo",
+ (u_long)p->fts_statp->st_flags,
+ newflags);
+ (void)fprintf(thread_stdout, "\n");
+ }
+ }
+ if (errno) {
+ err(1, "fts_read");
+ }
+ exit(rval);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "usage: chflags [-fhv] [-R [-H | -L | -P]] flags file ...\n");
+ exit(1);
+}
diff --git a/files/Sources/files/chmod/chmod.1 b/files/Sources/files/chmod/chmod.1
new file mode 100644
index 00000000..dccb9539
--- /dev/null
+++ b/files/Sources/files/chmod/chmod.1
@@ -0,0 +1,583 @@
+.\" Copyright (c) 1989, 1990, 1993, 1994
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the Institute of Electrical and Electronics Engineers, Inc.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)chmod.1 8.4 (Berkeley) 3/31/94
+.\" $FreeBSD: src/bin/chmod/chmod.1,v 1.33 2002/10/01 20:32:59 trhodes Exp $
+.\"
+.Dd July 08, 2004
+.Dt CHMOD 1
+.Os
+.Sh NAME
+.Nm chmod
+.Nd change file modes or Access Control Lists
+.Sh SYNOPSIS
+.Nm chmod
+.Op Fl fv
+.Op Fl R Op Fl H | L | P
+.Ar mode
+.Ar
+.Nm chmod
+.Op Fl fv
+.Op Fl R Op Fl H | L | P
+.Op -a | +a | =a
+.Ar ACE
+.Ar
+.Nm chmod
+.Op Fl fhv
+.Op Fl R Op Fl H | L | P
+.Op Fl E
+.Ar
+.Nm chmod
+.Op Fl fhv
+.Op Fl R Op Fl H | L | P
+.Op Fl C
+.Ar
+.Nm chmod
+.Op Fl fhv
+.Op Fl R Op Fl H | L | P
+.Op Fl N
+.Ar
+.Sh DESCRIPTION
+The
+.Nm chmod
+utility modifies the file mode bits of the listed files
+as specified by the
+.Ar mode
+operand. It may also be used to modify the Access Control
+Lists (ACLs) associated with the listed files.
+.Pp
+The generic options are as follows:
+.Bl -tag -width Ds
+.It Fl f
+Do not display a diagnostic message if
+.Nm chmod
+could not modify the mode for
+.Va file .
+.It Fl H
+If the
+.Fl R
+option is specified, symbolic links on the command line are followed.
+(Symbolic links encountered in the tree traversal are not followed by
+default.)
+.It Fl h
+If the file is a symbolic link, change the mode of the link itself
+rather than the file that the link points to.
+.It Fl L
+If the
+.Fl R
+option is specified, all symbolic links are followed.
+.It Fl P
+If the
+.Fl R
+option is specified, no symbolic links are followed.
+This is the default.
+.It Fl R
+Change the modes of the file hierarchies rooted in the files
+instead of just the files themselves.
+.It Fl v
+Cause
+.Nm chmod
+to be verbose, showing filenames as the mode is modified.
+If the
+.Fl v
+flag is specified more than once, the old and new modes of the file
+will also be printed, in both octal and symbolic notation.
+.El
+.Pp
+The
+.Fl H ,
+.Fl L
+and
+.Fl P
+options are ignored unless the
+.Fl R
+option is specified.
+In addition, these options override each other and the
+command's actions are determined by the last one specified.
+.Pp
+Only the owner of a file or the super-user is permitted to change
+the mode of a file.
+.Sh DIAGNOSTICS
+.Ex -std
+.Sh MODES
+Modes may be absolute or symbolic.
+An absolute mode is an octal number constructed from the sum of
+one or more of the following values:
+.Pp
+.Bl -tag -width 6n -compact -offset indent
+.It Li 4000
+(the set-user-ID-on-execution bit) Executable files with this bit set
+will run with effective uid set to the uid of the file owner.
+Directories with the set-user-id bit set will force all files and
+sub-directories created in them to be owned by the directory owner
+and not by the uid of the creating process, if the underlying file
+system supports this feature: see
+.Xr chmod 2
+and the
+.Ar suiddir
+option to
+.Xr mount 8 .
+.It Li 2000
+(the set-group-ID-on-execution bit) Executable files with this bit set
+will run with effective gid set to the gid of the file owner.
+.It Li 1000
+(the sticky bit)
+See
+.Xr chmod 2
+and
+.Xr sticky 8 .
+.It Li 0400
+Allow read by owner.
+.It Li 0200
+Allow write by owner.
+.It Li 0100
+For files, allow execution by owner.
+For directories, allow the owner to
+search in the directory.
+.It Li 0040
+Allow read by group members.
+.It Li 0020
+Allow write by group members.
+.It Li 0010
+For files, allow execution by group members.
+For directories, allow
+group members to search in the directory.
+.It Li 0004
+Allow read by others.
+.It Li 0002
+Allow write by others.
+.It Li 0001
+For files, allow execution by others.
+For directories allow others to
+search in the directory.
+.El
+.Pp
+For example, the absolute mode that permits read, write and execute by
+the owner, read and execute by group members, read and execute by
+others, and no set-uid or set-gid behaviour is 755
+(400+200+100+040+010+004+001).
+.Pp
+The symbolic mode is described by the following grammar:
+.Bd -literal -offset indent
+mode ::= clause [, clause ...]
+clause ::= [who ...] [action ...] action
+action ::= op [perm ...]
+who ::= a | u | g | o
+op ::= + | \- | =
+perm ::= r | s | t | w | x | X | u | g | o
+.Ed
+.Pp
+The
+.Ar who
+symbols ``u'', ``g'', and ``o'' specify the user, group, and other parts
+of the mode bits, respectively.
+The
+.Ar who
+symbol ``a'' is equivalent to ``ugo''.
+.Pp
+The
+.Ar perm
+symbols represent the portions of the mode bits as follows:
+.Pp
+.Bl -tag -width Ds -compact -offset indent
+.It r
+The read bits.
+.It s
+The set-user-ID-on-execution and set-group-ID-on-execution bits.
+.It t
+The sticky bit.
+.It w
+The write bits.
+.It x
+The execute/search bits.
+.It X
+The execute/search bits if the file is a directory or any of the
+execute/search bits are set in the original (unmodified) mode.
+Operations with the
+.Ar perm
+symbol ``X'' are only meaningful in conjunction with the
+.Ar op
+symbol ``+'', and are ignored in all other cases.
+.It u
+The user permission bits in the original mode of the file.
+.It g
+The group permission bits in the original mode of the file.
+.It o
+The other permission bits in the original mode of the file.
+.El
+.Pp
+The
+.Ar op
+symbols represent the operation performed, as follows:
+.Bl -tag -width 4n
+.It +
+If no value is supplied for
+.Ar perm ,
+the ``+'' operation has no effect.
+If no value is supplied for
+.Ar who ,
+each permission bit specified in
+.Ar perm ,
+for which the corresponding bit in the file mode creation mask
+is clear, is set.
+Otherwise, the mode bits represented by the specified
+.Ar who
+and
+.Ar perm
+values are set.
+.It \&\-
+If no value is supplied for
+.Ar perm ,
+the ``\-'' operation has no effect.
+If no value is supplied for
+.Ar who ,
+each permission bit specified in
+.Ar perm ,
+for which the corresponding bit in the file mode creation mask
+is clear, is cleared.
+Otherwise, the mode bits represented by the specified
+.Ar who
+and
+.Ar perm
+values are cleared.
+.It =
+The mode bits specified by the
+.Ar who
+value are cleared, or, if no who value is specified, the owner, group
+and other mode bits are cleared.
+Then, if no value is supplied for
+.Ar who ,
+each permission bit specified in
+.Ar perm ,
+for which the corresponding bit in the file mode creation mask
+is clear, is set.
+Otherwise, the mode bits represented by the specified
+.Ar who
+and
+.Ar perm
+values are set.
+.El
+.Pp
+Each
+.Ar clause
+specifies one or more operations to be performed on the mode
+bits, and each operation is applied to the mode bits in the
+order specified.
+.Pp
+Operations upon the other permissions only (specified by the symbol
+``o'' by itself), in combination with the
+.Ar perm
+symbols ``s'' or ``t'', are ignored.
+.Sh EXAMPLES OF VALID MODES
+.Bl -tag -width "u=rwx,go=u-w" -compact
+.It Li 644
+make a file readable by anyone and writable by the owner only.
+.Pp
+.It Li go-w
+deny write permission to group and others.
+.Pp
+.It Li =rw,+X
+set the read and write permissions to the usual defaults, but
+retain any execute permissions that are currently set.
+.Pp
+.It Li +X
+make a directory or file searchable/executable by everyone if it is
+already searchable/executable by anyone.
+.Pp
+.It Li 755
+.It Li u=rwx,go=rx
+.It Li u=rwx,go=u-w
+make a file readable/executable by everyone and writable by the owner only.
+.Pp
+.It Li go=
+clear all mode bits for group and others.
+.Pp
+.It Li g=u-w
+set the group bits equal to the user bits, but clear the group write bit.
+.El
+.Sh ACL MANIPULATION OPTIONS
+ACLs are manipulated using extensions to the symbolic mode
+grammar. Each file has one ACL, containing an ordered list of entries.
+Each entry refers to a user or group, and grants or denies a set of
+permissions.
+In cases where a user and a group exist with the same name, the
+user/group name can be prefixed with "user:" or "group:" in order to
+specify the type of name.
+.Pp
+If the user or group name contains spaces you can use ':' as the delimiter
+between name and permission.
+.Pp
+The following permissions are applicable to all filesystem objects:
+.Bl -tag -width 6n -compact -offset indent
+.It delete
+Delete the item. Deletion may be granted by either this permission
+on an object or the delete_child right on the containing directory.
+.It readattr
+Read an objects basic attributes. This is implicitly granted if
+the object can be looked up and not explicitly denied.
+.It writeattr
+Write an object's basic attributes.
+.It readextattr
+Read extended attributes.
+.It writeextattr
+Write extended attributes.
+.It readsecurity
+Read an object's extended security information (ACL).
+.It writesecurity
+Write an object's security information (ownership, mode, ACL).
+.It chown
+Change an object's ownership.
+.El
+.Pp
+The following permissions are applicable to directories:
+.Bl -tag -width 6n -compact -offset indent
+.It list
+List entries.
+.It search
+Look up files by name.
+.It add_file
+Add a file.
+.It add_subdirectory
+Add a subdirectory.
+.It delete_child
+Delete a contained object. See the file delete permission above.
+.El
+.Pp
+The following permissions are applicable to non-directory filesystem objects:
+.Bl -tag -width 6n -compact -offset indent
+.It read
+Open for reading.
+.It write
+Open for writing.
+.It append
+Open for writing, but in a fashion that only allows writes into areas of
+the file not previously written.
+.It execute
+Execute the file as a script or program.
+.El
+.Pp
+ACL inheritance is controlled with the following permissions words, which
+may only be applied to directories:
+.Bl -tag -width 6n -compact -offset indent
+.It file_inherit
+Inherit to files.
+.It directory_inherit
+Inherit to directories.
+.It limit_inherit
+This flag is only relevant to entries inherited by subdirectories; it
+causes the directory_inherit flag to be cleared in the entry that is
+inherited, preventing further nested subdirectories from also
+inheriting the entry.
+.It only_inherit
+The entry is inherited by created items but not considered when processing
+the ACL.
+.El
+.Pp
+The ACL manipulation options are as follows:
+.Bl -tag -width Ds
+.It \fB+a\fR
+The +a mode parses a new ACL entry from the next argument on
+the commandline and inserts it into the canonical location in the
+ACL. If the supplied entry refers to an identity already listed, the
+two entries are combined.
+.Pp
+\fBExamples\fR
+ # ls -le
+ -rw-r--r--+ 1 juser wheel 0 Apr 28 14:06 file1
+ # chmod +a "admin allow write" file1
+ # ls -le
+ -rw-r--r--+ 1 juser wheel 0 Apr 28 14:06 file1
+ owner: juser
+ 1: admin allow write
+ # chmod +a "guest deny read" file1
+ # ls -le
+ -rw-r--r--+ 1 juser wheel 0 Apr 28 14:06 file1
+ owner: juser
+ 1: guest deny read
+ 2: admin allow write
+ # chmod +a "admin allow delete" file1
+ # ls -le
+ -rw-r--r--+ 1 juser wheel 0 Apr 28 14:06 file1
+ owner: juser
+ 1: guest deny read
+ 2: admin allow write,delete
+ # chmod +a "User 1:allow:read" file
+ # ls -le
+ -rw-r--r--+ 1 juser wheel 0 Apr 28 14:06 file1
+ owner: juser
+ 1: guest deny read
+ 2: User 1 allow read
+ 3: admin allow write,delete
+.Pp
+The +a mode strives to maintain correct canonical form for the ACL.
+ local deny
+ local allow
+ inherited deny
+ inherited allow
+.Pp
+By default, chmod adds entries to the top of the local deny and local
+allow lists. Inherited entries are added by using the +ai mode.
+.Pp
+\fBExamples\fR
+ # ls -le
+ -rw-r--r--+ 1 juser wheel 0 Apr 28 14:06 file1
+ owner: juser
+ 1: guest deny read
+ 2: admin allow write,delete
+ 3: juser inherited deny delete
+ 4: admin inherited allow delete
+ 5: backup inherited deny read
+ 6: admin inherited allow write-security
+ # chmod +ai "others allow read" file1
+ # ls -le
+ -rw-r--r--+ 1 juser wheel 0 Apr 28 14:06 file1
+ owner: juser
+ 1: guest deny read
+ 2: admin allow write,delete
+ 3: juser inherited deny delete
+ 4: others inherited allow read
+ 5: admin inherited allow delete
+ 6: backup inherited deny read
+ 7: admin inherited allow write-security
+.It \fB+a#\fR
+When a specific ordering is required, the exact location at which an
+entry will be inserted is specified with the +a# mode.
+.Pp
+\fBExamples\fR
+ # ls -le
+ -rw-r--r--+ 1 juser wheel 0 Apr 28 14:06 file1
+ owner: juser
+ 1: guest deny read
+ 2: admin allow write
+ # chmod +a# 2 "others deny read" file1
+ # ls -le
+ -rw-r--r--+ 1 juser wheel 0 Apr 28 14:06 file1
+ owner: juser
+ 1: guest deny read
+ 2: others deny read
+ 3: admin allow write
+.Pp
+The +ai# mode may be used to insert inherited entries at a specific
+location. Note that these modes allow non-canonical ACL ordering to
+be constructed.
+.It Fl a
+The -a mode is used to delete ACL entries. All entries exactly
+matching the supplied entry will be deleted. If the entry lists a
+subset of rights granted by an entry, only the rights listed are
+removed. Entries may also be deleted by index using the -a# mode.
+.Pp
+\fBExamples\fR
+ # ls -le
+ -rw-r--r--+ 1 juser wheel 0 Apr 28 14:06 file1
+ owner: juser
+ 1: guest deny read
+ 2: admin allow write,delete
+ # chmod -a# 1 file1
+ # ls -le
+ -rw-r--r--+ 1 juser wheel 0 Apr 28 14:06 file1
+ owner: juser
+ 1: admin allow write,delete
+ # chmod -a "admin allow write" file1
+ # ls -le
+ -rw-r--r--+ 1 juser wheel 0 Apr 28 14:06 file1
+ owner: juser
+ 1: admin allow delete
+.Pp
+Inheritance is not considered when processing the -a mode; rights and
+entries will be removed regardless of their inherited state.
+.Pp
+If the user or group name contains spaces you can use ':' as the delimiter
+.Pp
+\fBExample\fR
+ # chmod +a "User 1:allow:read" file
+.It \fB=a#\fR
+Individual entries are rewritten using the =a# mode.
+.Pp
+\fBExamples\fR
+ # ls -le
+ -rw-r--r--+ 1 juser wheel 0 Apr 28 14:06 file1
+ owner: juser
+ 1: admin allow delete
+ # chmod =a# 1 "admin allow write,chown"
+ # ls -le
+ -rw-r--r--+ 1 juser wheel 0 Apr 28 14:06 file1
+ owner: juser
+ 1: admin allow write,chown
+.Pp
+This mode may not be used to add new entries.
+.It Fl E
+Reads the ACL information from stdin, as a sequential list
+of ACEs, separated by newlines. If the information parses correctly,
+the existing information is replaced.
+.It Fl C
+Returns false if any of the named files have ACLs in non-canonical order.
+.It Fl i
+Removes the 'inherited' bit from all entries in the named file(s) ACLs.
+.It Fl I
+Removes all inherited entries from the named file(s) ACL(s).
+.It Fl N
+Removes the ACL from the named file(s).
+.El
+.Sh COMPATIBILITY
+The
+.Fl v
+option is non-standard and its use in scripts is not recommended.
+.Sh SEE ALSO
+.Xr chflags 1 ,
+.Xr fsaclctl 1 ,
+.Xr install 1 ,
+.Xr chmod 2 ,
+.Xr stat 2 ,
+.Xr umask 2 ,
+.Xr fts 3 ,
+.Xr setmode 3 ,
+.Xr symlink 7 ,
+.Xr chown 8 ,
+.Xr mount 8 ,
+.Xr sticky 8
+.Sh STANDARDS
+The
+.Nm chmod
+utility is expected to be
+.St -p1003.2
+compatible with the exception of the
+.Ar perm
+symbol
+.Dq t
+which is not included in that standard.
+.Sh HISTORY
+A
+.Nm chmod
+command appeared in
+.At v1 .
diff --git a/files/Sources/files/chmod/chmod.c b/files/Sources/files/chmod/chmod.c
new file mode 100644
index 00000000..92a2ed9c
--- /dev/null
+++ b/files/Sources/files/chmod/chmod.c
@@ -0,0 +1,469 @@
+/*
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include
+#ifndef lint
+__used static char const copyright[] =
+"@(#) Copyright (c) 1989, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)chmod.c 8.8 (Berkeley) 4/1/94";
+#endif
+#endif /* not lint */
+#include
+__RCSID("$FreeBSD: src/bin/chmod/chmod.c,v 1.27 2002/08/04 05:29:13 obrien Exp $");
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef __APPLE__
+#include "chmod_acl.h"
+#include "ios_error.h" // remap exit to pthread_exit
+
+#endif /*__APPLE__*/
+
+__thread int chmod_fflag = 0;
+
+int chmod_main(int, char *[]);
+void chmod_usage(void);
+
+int
+chmod_main(int argc, char *argv[])
+{
+ chmod_fflag = 0;
+ FTS *ftsp = NULL;
+ FTSENT *p = NULL;
+ mode_t *set = NULL;
+ long val = 0;
+ int oct = 0;
+ int Hflag, Lflag, Pflag, Rflag, ch, fts_options, hflag, rval;
+ int vflag;
+ char *ep, *mode;
+ mode_t newmode, omode;
+#ifdef __APPLE__
+ unsigned int acloptflags = 0;
+ long aclpos = -1;
+ int inheritance_level = 0;
+ int index = 0;
+ size_t acloptlen = 0;
+ int ace_arg_not_required = 0;
+ acl_t acl_input = NULL;
+ optind = 1; opterr = 1; optreset = 1;
+#endif /* __APPLE__*/
+ int (*change_mode)(const char *, mode_t);
+
+ set = NULL;
+ omode = 0;
+ Hflag = Lflag = Pflag = Rflag = chmod_fflag = hflag = vflag = 0;
+#ifndef __APPLE__
+ while ((ch = getopt(argc, argv, "HLPRXfghorstuvwx")) != -1)
+#else
+ while ((ch = getopt(argc, argv, "ACEHILNPRVXafghinorstuvwx")) != -1)
+#endif
+ switch (ch) {
+ case 'H':
+ Hflag = 1;
+ Lflag = 0;
+ Pflag = 0;
+ break;
+ case 'L':
+ Lflag = 1;
+ Hflag = 0;
+ Pflag = 0;
+ break;
+ case 'P':
+ Hflag = Lflag = 0;
+ Pflag = 1;
+ break;
+ case 'R':
+ Rflag = 1;
+ break;
+ case 'f':
+ chmod_fflag = 1;
+ break;
+ case 'h':
+ /*
+ * In System V (and probably POSIX.2) the -h option
+ * causes chmod to change the mode of the symbolic
+ * link. 4.4BSD's symbolic links didn't have modes,
+ * so it was an undocumented noop. In FreeBSD 3.0,
+ * lchmod(2) is introduced and this option does real
+ * work.
+ */
+ hflag = 1;
+ break;
+#ifdef __APPLE__
+ case 'a':
+ if (argv[optind - 1][0] == '-' &&
+ argv[optind - 1][1] == ch)
+ --optind;
+ goto done;
+ case 'A':
+// acloptflags |= ACL_FLAG | ACL_TO_STDOUT;
+// ace_arg_not_required = 1;
+ errx(1, "-A not implemented");
+ goto done;
+ case 'E':
+ acloptflags |= ACL_FLAG | ACL_FROM_STDIN;
+ goto done;
+ case 'C':
+ acloptflags |= ACL_FLAG | ACL_CHECK_CANONICITY;
+ ace_arg_not_required = 1;
+ goto done;
+ case 'i':
+ acloptflags |= ACL_FLAG | ACL_REMOVE_INHERIT_FLAG;
+ ace_arg_not_required = 1;
+ goto done;
+ case 'I':
+ acloptflags |= ACL_FLAG | ACL_REMOVE_INHERITED_ENTRIES;
+ ace_arg_not_required = 1;
+ goto done;
+ case 'n':
+ acloptflags |= ACL_FLAG | ACL_NO_TRANSLATE;
+ break;
+ case 'N':
+ acloptflags |= ACL_FLAG | ACL_CLEAR_FLAG;
+ ace_arg_not_required = 1;
+ goto done;
+ case 'V':
+// acloptflags |= ACL_FLAG | ACL_INVOKE_EDITOR;
+// ace_arg_not_required = 1;
+ errx(1, "-V not implemented");
+ goto done;
+#endif /* __APPLE__ */
+ /*
+ * XXX
+ * "-[rwx]" are valid mode commands. If they are the entire
+ * argument, getopt has moved past them, so decrement optind.
+ * Regardless, we're done argument processing.
+ */
+ case 'g': case 'o': case 'r': case 's':
+ case 't': case 'u': case 'w': case 'X': case 'x':
+ if (argv[optind - 1][0] == '-' &&
+ argv[optind - 1][1] == ch &&
+ argv[optind - 1][2] == '\0')
+ --optind;
+ goto done;
+ case 'v':
+ vflag++;
+ break;
+ case '?':
+ default:
+ chmod_usage();
+ }
+done: argv += optind;
+ argc -= optind;
+
+#ifdef __APPLE__
+ if (argc < ((acloptflags & ACL_FLAG) ? 1 : 2))
+ chmod_usage();
+ if (!Rflag && (Hflag || Lflag || Pflag))
+ warnx("options -H, -L, -P only useful with -R");
+#else /* !__APPLE__ */
+ if (argc < 2)
+ chmod_usage();
+#endif /* __APPLE__ */
+
+#ifdef __APPLE__
+ if (!(acloptflags & ACL_FLAG) && ((acloptlen = strlen(argv[0])) > 1) && (argv[0][1] == 'a')) {
+ acloptflags |= ACL_FLAG;
+ switch (argv[0][0]) {
+ case '+':
+ acloptflags |= ACL_SET_FLAG;
+ break;
+ case '-':
+ acloptflags |= ACL_DELETE_FLAG;
+ break;
+ case '=':
+ acloptflags |= ACL_REWRITE_FLAG;
+ break;
+ default:
+ acloptflags &= ~ACL_FLAG;
+ goto apnoacl;
+ }
+
+ if (argc < 3)
+ chmod_usage();
+
+ if (acloptlen > 2) {
+ for (index = 2; index < acloptlen; index++) {
+ switch (argv[0][index]) {
+ case '#':
+ acloptflags |= ACL_ORDER_FLAG;
+
+ if (argc < ((acloptflags & ACL_DELETE_FLAG)
+ ? 3 : 4))
+ chmod_usage();
+ argv++;
+ argc--;
+ errno = 0;
+ aclpos = strtol(argv[0], &ep, 0);
+
+ if (aclpos > ACL_MAX_ENTRIES
+ || aclpos < 0)
+ errno = ERANGE;
+ if (errno || *ep) {
+ errx(1, "Invalid ACL entry number: %ld", aclpos);
+ }
+ if (acloptflags & ACL_DELETE_FLAG)
+ ace_arg_not_required = 1;
+
+ goto apdone;
+ case 'i':
+ acloptflags |= ACL_INHERIT_FLAG;
+ /* The +aii.. syntax to specify
+ * inheritance level is rather unwieldy,
+ * find an alternative.
+ */
+ inheritance_level++;
+ if (inheritance_level > 1)
+ warnx("Inheritance across more than one generation is not currently supported");
+ if (inheritance_level >= MAX_INHERITANCE_LEVEL)
+ goto apdone;
+ break;
+ default:
+ errno = EINVAL;
+ chmod_usage();
+ }
+ }
+ }
+apdone:
+ argv++;
+ argc--;
+ }
+apnoacl:
+#endif /*__APPLE__*/
+
+ if (Rflag) {
+ fts_options = FTS_PHYSICAL;
+ if (hflag) {
+ errx(1, "the -R and -h options may not be specified together.");
+ }
+ if (Hflag)
+ fts_options |= FTS_COMFOLLOW;
+ if (Lflag) {
+ fts_options &= ~FTS_PHYSICAL;
+ fts_options |= FTS_LOGICAL;
+ }
+ } else
+ fts_options = hflag ? FTS_PHYSICAL : FTS_LOGICAL;
+
+ if (hflag)
+ change_mode = lchmod;
+ else
+ change_mode = chmod;
+#ifdef __APPLE__
+ if (acloptflags & ACL_FROM_STDIN) {
+ ssize_t readval = 0;
+ size_t readtotal = 0;
+
+ mode = (char *) malloc(MAX_ACL_TEXT_SIZE);
+
+ if (mode == NULL) {
+ err(1, "Unable to allocate mode string");
+ }
+ /* Read the ACEs from STDIN */
+ do {
+ readtotal += readval;
+ readval = read(fileno(thread_stdin), mode + readtotal,
+ MAX_ACL_TEXT_SIZE);
+ } while ((readval > 0) && (readtotal <= MAX_ACL_TEXT_SIZE));
+
+ if (0 == readtotal) {
+ errx(1, "-E specified, but read from STDIN failed");
+ }
+ else
+ mode[readtotal - 1] = '\0';
+ --argv;
+ }
+ else
+#endif /* __APPLE */
+ mode = *argv;
+
+#ifdef __APPLE__
+ if ((acloptflags & ACL_FLAG)) {
+
+ /* Are we deleting by entry number, verifying
+ * canonicity or performing some other operation that
+ * does not require an input entry? If so, there's no
+ * entry to convert.
+ */
+ if (ace_arg_not_required) {
+ --argv;
+ }
+ else {
+ /* Parse the text into an ACL*/
+ acl_input = parse_acl_entries(mode);
+ if (acl_input == NULL) {
+ errx(1, "Invalid ACL specification: %s", mode);
+ }
+ }
+ }
+ else {
+#endif /* __APPLE__*/
+ if (*mode >= '0' && *mode <= '7') {
+ errno = 0;
+ val = strtol(mode, &ep, 8);
+ if (val > USHRT_MAX || val < 0)
+ errno = ERANGE;
+ if (errno) {
+ err(1, "Invalid file mode: %s", mode);
+ }
+ if (*ep) {
+ errx(1, "Invalid file mode: %s", mode);
+ }
+ omode = (mode_t)val;
+ oct = 1;
+ } else {
+ if ((set = setmode(mode)) == NULL) {
+ errx(1, "Invalid file mode: %s", mode);
+ }
+ oct = 0;
+ }
+#ifdef __APPLE__
+ }
+#endif /* __APPLE__*/
+ if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL) {
+ err(1, "fts_open");
+ }
+ for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
+ switch (p->fts_info) {
+ case FTS_D:
+ if (!Rflag)
+ (void)fts_set(ftsp, p, FTS_SKIP);
+ break;
+ case FTS_DNR: /* Warn, chmod, continue. */
+ warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
+ rval = 1;
+ break;
+ case FTS_DP: /* Already changed at FTS_D. */
+ continue;
+ case FTS_NS:
+ if (acloptflags & ACL_FLAG) /* don't need stat for -N */
+ break;
+ case FTS_ERR: /* Warn, continue. */
+ warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
+ rval = 1;
+ continue;
+ case FTS_SL: /* Ignore. */
+ case FTS_SLNONE:
+ /*
+ * The only symlinks that end up here are ones that
+ * don't point to anything and ones that we found
+ * doing a physical walk.
+ */
+ if (!hflag)
+ continue;
+ /* else */
+ /* FALLTHROUGH */
+ default:
+ break;
+ }
+#ifdef __APPLE__
+/* If an ACL manipulation option was specified, manipulate */
+ if (acloptflags & ACL_FLAG) {
+ if (0 != modify_file_acl(acloptflags, p->fts_accpath, acl_input, (int)aclpos, inheritance_level, !hflag))
+ rval = 1;
+ }
+ else {
+#endif /* __APPLE__ */
+ newmode = oct ? omode : getmode(set, p->fts_statp->st_mode);
+ if ((newmode & ALLPERMS) == (p->fts_statp->st_mode & ALLPERMS))
+ continue;
+ if ((*change_mode)(p->fts_accpath, newmode) && !chmod_fflag) {
+ warn("Unable to change file mode on %s", p->fts_path);
+ rval = 1;
+ } else {
+ if (vflag) {
+ (void)fprintf(thread_stdout, "%s", p->fts_accpath);
+
+ if (vflag > 1) {
+ char m1[12], m2[12];
+
+ strmode(p->fts_statp->st_mode, m1);
+ strmode((p->fts_statp->st_mode &
+ S_IFMT) | newmode, m2);
+
+ (void)fprintf(thread_stdout, ": 0%o [%s] -> 0%o [%s]",
+ p->fts_statp->st_mode, m1,
+ (p->fts_statp->st_mode & S_IFMT) |
+ newmode, m2);
+ }
+ (void)fprintf(thread_stdout, "\n");
+ }
+
+ }
+#ifdef __APPLE__
+ }
+#endif /* __APPLE__*/
+ }
+ if (errno) {
+ err(1, "fts_read");
+ }
+#ifdef __APPLE__
+ if (acl_input)
+ acl_free(acl_input);
+ if (mode && (acloptflags & ACL_FROM_STDIN))
+ free(mode);
+
+#endif /* __APPLE__ */
+ if (set)
+ free(set);
+ exit(rval);
+}
+
+void
+chmod_usage(void)
+{
+#ifdef __APPLE__
+ (void)fprintf(stderr,
+ "usage:\tchmod [-fhv] [-R [-H | -L | -P]] [-a | +a | =a [i][# [ n]]] mode|entry file ...\n"
+ "\tchmod [-fhv] [-R [-H | -L | -P]] [-E | -C | -N | -i | -I] file ...\n"); /* add -A and -V when implemented */
+#else
+ (void)fprintf(stderr,
+ "usage: chmod [-fhv] [-R [-H | -L | -P]] mode file ...\n");
+#endif /* __APPLE__ */
+ exit(1);
+}
diff --git a/files/Sources/files/chmod/chmod_acl.c b/files/Sources/files/chmod/chmod_acl.c
new file mode 100644
index 00000000..a2b77a9d
--- /dev/null
+++ b/files/Sources/files/chmod/chmod_acl.c
@@ -0,0 +1,881 @@
+/*
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include "chmod_acl.h"
+#include "ios_error.h"
+
+extern void chmod_usage(void);
+
+#ifdef __APPLE__
+static struct {
+ acl_perm_t perm;
+ char *name;
+ int flags;
+#define ACL_PERM_DIR (1<<0)
+#define ACL_PERM_FILE (1<<1)
+} acl_perms[] = {
+ {ACL_READ_DATA, "read", ACL_PERM_FILE},
+ {ACL_LIST_DIRECTORY, "list", ACL_PERM_DIR},
+ {ACL_WRITE_DATA, "write", ACL_PERM_FILE},
+ {ACL_ADD_FILE, "add_file", ACL_PERM_DIR},
+ {ACL_EXECUTE, "execute", ACL_PERM_FILE},
+ {ACL_SEARCH, "search", ACL_PERM_DIR},
+ {ACL_DELETE, "delete", ACL_PERM_FILE | ACL_PERM_DIR},
+ {ACL_APPEND_DATA, "append", ACL_PERM_FILE},
+ {ACL_ADD_SUBDIRECTORY, "add_subdirectory", ACL_PERM_DIR},
+ {ACL_DELETE_CHILD, "delete_child", ACL_PERM_DIR},
+ {ACL_READ_ATTRIBUTES, "readattr", ACL_PERM_FILE | ACL_PERM_DIR},
+ {ACL_WRITE_ATTRIBUTES, "writeattr", ACL_PERM_FILE | ACL_PERM_DIR},
+ {ACL_READ_EXTATTRIBUTES, "readextattr", ACL_PERM_FILE | ACL_PERM_DIR},
+ {ACL_WRITE_EXTATTRIBUTES, "writeextattr", ACL_PERM_FILE | ACL_PERM_DIR},
+ {ACL_READ_SECURITY, "readsecurity", ACL_PERM_FILE | ACL_PERM_DIR},
+ {ACL_WRITE_SECURITY, "writesecurity", ACL_PERM_FILE | ACL_PERM_DIR},
+ {ACL_CHANGE_OWNER, "chown", ACL_PERM_FILE | ACL_PERM_DIR},
+ {0, NULL, 0}
+};
+
+static struct {
+ acl_flag_t flag;
+ char *name;
+ int flags;
+} acl_flags[] = {
+ {ACL_ENTRY_INHERITED, "inherited", ACL_PERM_FILE | ACL_PERM_DIR},
+ {ACL_ENTRY_FILE_INHERIT, "file_inherit", ACL_PERM_DIR},
+ {ACL_ENTRY_DIRECTORY_INHERIT, "directory_inherit", ACL_PERM_DIR},
+ {ACL_ENTRY_LIMIT_INHERIT, "limit_inherit", ACL_PERM_FILE | ACL_PERM_DIR},
+ {ACL_ENTRY_ONLY_INHERIT, "only_inherit", ACL_PERM_DIR},
+ {0, NULL, 0}
+};
+
+/* TBD - Many of these routines could potentially be considered for
+ * inclusion in a library. If that is done, either avoid use of "err"
+ * and implement a better fall-through strategy in case of errors,
+ * or use err_set_exit() and make various structures globals.
+ */
+
+#define NAME_USER (1)
+#define NAME_GROUP (2)
+#define NAME_EITHER (NAME_USER | NAME_GROUP)
+
+/* Perform a name to uuid mapping - calls through to memberd */
+
+uuid_t *
+name_to_uuid(char *tok, int nametype) {
+ uuid_t *entryg = NULL;
+ size_t len = strlen(tok);
+
+ if ((entryg = (uuid_t *) calloc(1, sizeof(uuid_t))) == NULL) {
+ errx(1, "Unable to allocate a uuid");
+ }
+
+ if ((nametype & NAME_USER) && mbr_identifier_to_uuid(ID_TYPE_USERNAME, tok, len, *entryg) == 0) {
+ return entryg;
+ }
+
+ if ((nametype & NAME_GROUP) && mbr_identifier_to_uuid(ID_TYPE_GROUPNAME, tok, len, *entryg) == 0) {
+ return entryg;
+ }
+
+ free(entryg);
+ errx(1, "Unable to translate '%s' to a UUID", tok);
+ return NULL; // never reached
+}
+
+/* Convert an acl entry in string form to an acl_entry_t */
+int
+parse_entry(char *entrybuf, acl_entry_t newent) {
+ char *tok;
+ char *pebuf;
+ uuid_t *entryg;
+
+ acl_tag_t tag;
+ acl_permset_t perms;
+ acl_flagset_t flags;
+ unsigned permcount = 0;
+ unsigned pindex = 0;
+ char *delimiter = " ";
+ int nametype = NAME_EITHER;
+
+ acl_get_permset(newent, &perms);
+ acl_get_flagset_np(newent, &flags);
+
+ pebuf = entrybuf;
+
+ if (0 == strncmp(entrybuf, "user:", 5)) {
+ nametype = NAME_USER;
+ pebuf += 5;
+ } else if (0 == strncmp(entrybuf, "group:", 6)) {
+ nametype = NAME_GROUP;
+ pebuf += 6;
+ }
+
+ if (strchr(pebuf, ':')) /* User/Group names can have spaces */
+ delimiter = ":";
+ tok = strsep(&pebuf, delimiter);
+
+ if ((tok == NULL) || *tok == '\0') {
+ errx(1, "Invalid entry format -- expected user or group name");
+ }
+
+ /* parse the name into a qualifier */
+ entryg = name_to_uuid(tok, nametype);
+
+ tok = strsep(&pebuf, ": "); /* Stick with delimiter? */
+ if ((tok == NULL) || *tok == '\0') {
+ errx(1, "Invalid entry format -- expected allow or deny");
+ }
+
+ /* is the verb 'allow' or 'deny'? */
+ if (!strcmp(tok, "allow")) {
+ tag = ACL_EXTENDED_ALLOW;
+ } else if (!strcmp(tok, "deny")) {
+ tag = ACL_EXTENDED_DENY;
+ } else {
+ errx(1, "Unknown tag type '%s'", tok);
+ }
+
+ /* parse permissions */
+ for (; (tok = strsep(&pebuf, ",")) != NULL;) {
+ if (*tok != '\0') {
+ /* is it a permission? */
+ for (pindex = 0; acl_perms[pindex].name != NULL; pindex++) {
+ if (!strcmp(acl_perms[pindex].name, tok)) {
+ /* got one */
+ acl_add_perm(perms, acl_perms[pindex].perm);
+ permcount++;
+ goto found;
+ }
+ }
+ /* is it a flag? */
+ for (pindex = 0; acl_flags[pindex].name != NULL; pindex++) {
+ if (!strcmp(acl_flags[pindex].name, tok)) {
+ /* got one */
+ acl_add_flag_np(flags, acl_flags[pindex].flag);
+ permcount++;
+ goto found;
+ }
+ }
+ errx(1,"Invalid permission type '%s'", tok);
+ found:
+ continue;
+ }
+ }
+ if (0 == permcount) {
+ errx(1, "No permissions specified");
+ }
+ acl_set_tag_type(newent, tag);
+ acl_set_qualifier(newent, entryg);
+ acl_set_permset(newent, perms);
+ acl_set_flagset_np(newent, flags);
+ free(entryg);
+ entryg = NULL;
+
+ return(0);
+}
+
+/* Convert one or more acl entries in string form to an acl_t */
+acl_t
+parse_acl_entries(const char *input) {
+ acl_t acl_input;
+ acl_entry_t newent;
+ char *inbuf;
+ char *oinbuf;
+
+ char **bufp, *entryv[ACL_MAX_ENTRIES];
+#if 0
+/* XXX acl_from_text(), when implemented, will presumably use the canonical
+ * text representation format, which is what chmod should be using
+ * We may need to add an entry number to the input
+ */
+ /* Translate the user supplied ACL entry */
+ /* acl_input = acl_from_text(input); */
+#else
+ inbuf = malloc(MAX_ACL_TEXT_SIZE);
+
+ if (inbuf == NULL) {
+ err(1, "malloc() failed");
+ }
+ strncpy(inbuf, input, MAX_ACL_TEXT_SIZE);
+ inbuf[MAX_ACL_TEXT_SIZE - 1] = '\0';
+
+ if ((acl_input = acl_init(1)) == NULL) {
+ err(1, "acl_init() failed");
+ }
+
+ oinbuf = inbuf;
+
+ for (bufp = entryv; (*bufp = strsep(&oinbuf, "\n")) != NULL;)
+ if (**bufp != '\0') {
+ if (0 != acl_create_entry(&acl_input, &newent)) {
+ err(1, "acl_create_entry() failed");
+ }
+ if (0 != parse_entry(*bufp, newent)) {
+ errx(1, "Failed parsing entry '%s'", *bufp);
+ }
+ if (++bufp >= &entryv[ACL_MAX_ENTRIES - 1]) {
+ errx(1, "Too many entries");
+ }
+ }
+
+ free(inbuf);
+ return acl_input;
+#endif /* #if 0 */
+}
+
+/* XXX No Libc support for inherited entries and generation determination yet */
+unsigned
+get_inheritance_level(acl_entry_t entry) {
+/* XXX to be implemented */
+ return 1;
+}
+
+/* Determine a "score" for an acl entry. The entry scores higher if it's
+ * tagged ACL_EXTENDED_DENY, and non-inherited entries are ranked higher
+ * than inherited entries.
+ */
+
+int
+score_acl_entry(acl_entry_t entry) {
+
+ acl_tag_t tag;
+ acl_flagset_t flags;
+ acl_permset_t perms;
+
+ int score = 0;
+
+ if (entry == NULL)
+ return (MINIMUM_TIER);
+
+ if (acl_get_tag_type(entry, &tag) != 0) {
+ err(1, "Malformed ACL entry, no tag present");
+ }
+ if (acl_get_flagset_np(entry, &flags) != 0){
+ err(1, "Unable to obtain flagset");
+ }
+ if (acl_get_permset(entry, &perms) != 0) {
+ err(1, "Malformed ACL entry, no permt present");
+ }
+
+ switch(tag) {
+ case ACL_EXTENDED_ALLOW:
+ break;
+ case ACL_EXTENDED_DENY:
+ score++;
+ break;
+ default:
+ errx(1, "Unknown tag type %d present in ACL entry", tag);
+ /* NOTREACHED */
+ }
+
+ if (acl_get_flag_np(flags, ACL_ENTRY_INHERITED))
+ score += get_inheritance_level(entry) * INHERITANCE_TIER;
+
+ return score;
+}
+
+int
+compare_acl_qualifiers(uuid_t *qa, uuid_t *qb) {
+ return bcmp(qa, qb, sizeof(uuid_t));
+}
+
+/* Compare two ACL permsets.
+ * Returns :
+ * MATCH_SUBSET if bperms is a subset of aperms
+ * MATCH_SUPERSET if bperms is a superset of aperms
+ * MATCH_PARTIAL if the two permsets have a common subset
+ * MATCH_EXACT if the two permsets are identical
+ * MATCH_NONE if they are disjoint
+ */
+
+int
+compare_acl_permsets(acl_permset_t aperms, acl_permset_t bperms)
+{
+ int i;
+/* TBD Implement other match levels as needed */
+ for (i = 0; acl_perms[i].name != NULL; i++) {
+ if (acl_get_perm_np(aperms, acl_perms[i].perm) !=
+ acl_get_perm_np(bperms, acl_perms[i].perm))
+ return MATCH_NONE;
+ }
+ return MATCH_EXACT;
+}
+
+static int
+compare_acl_flagsets(acl_flagset_t aflags, acl_flagset_t bflags)
+{
+ int i;
+/* TBD Implement other match levels as needed */
+ for (i = 0; acl_flags[i].name != NULL; i++) {
+ if (acl_get_flag_np(aflags, acl_flags[i].flag) !=
+ acl_get_flag_np(bflags, acl_flags[i].flag))
+ return MATCH_NONE;
+ }
+ return MATCH_EXACT;
+}
+
+/* Compares two ACL entries for equality */
+int
+compare_acl_entries(acl_entry_t a, acl_entry_t b)
+{
+ acl_tag_t atag, btag;
+ acl_permset_t aperms, bperms;
+ acl_flagset_t aflags, bflags;
+ int pcmp = 0, fcmp = 0;
+ void *aqual, *bqual;
+
+ aqual = acl_get_qualifier(a);
+ bqual = acl_get_qualifier(b);
+
+ int compare = compare_acl_qualifiers(aqual, bqual);
+ acl_free(aqual);
+ acl_free(bqual);
+
+ if (compare != 0)
+ return MATCH_NONE;
+
+ if (0 != acl_get_tag_type(a, &atag)) {
+ err(1, "No tag type present in entry");
+ }
+ if (0!= acl_get_tag_type(b, &btag)) {
+ err(1, "No tag type present in entry");
+ }
+
+ if (atag != btag)
+ return MATCH_NONE;
+
+ if ((acl_get_permset(a, &aperms) != 0) ||
+ (acl_get_flagset_np(a, &aflags) != 0) ||
+ (acl_get_permset(b, &bperms) != 0) ||
+ (acl_get_flagset_np(b, &bflags) != 0)) {
+ err(1, "error fetching permissions");
+ }
+
+ pcmp = compare_acl_permsets(aperms, bperms);
+ fcmp = compare_acl_flagsets(aflags, bflags);
+
+ if ((pcmp == MATCH_NONE) || (fcmp == MATCH_NONE))
+ return(MATCH_PARTIAL);
+ else
+ return(MATCH_EXACT);
+}
+
+/* Verify that an ACL is in canonical order. Currently, the canonical
+ * form is:
+ * local deny
+ * local allow
+ * inherited deny (parent)
+ * inherited allow (parent)
+ * inherited deny (grandparent)
+ * inherited allow (grandparent)
+ * ...
+ */
+unsigned int
+is_canonical(acl_t acl) {
+
+ unsigned aindex;
+ acl_entry_t entry;
+ int score = 0, next_score = 0;
+
+/* XXX - is a zero entry ACL in canonical form? */
+ if (0 != acl_get_entry(acl, ACL_FIRST_ENTRY, &entry))
+ return 1;
+
+ score = score_acl_entry(entry);
+
+ for (aindex = 0; acl_get_entry(acl, ACL_NEXT_ENTRY, &entry) == 0;
+ aindex++) {
+ if (score < (next_score = score_acl_entry(entry)))
+ return 0;
+ score = next_score;
+ }
+ return 1;
+}
+
+
+/* Iterate through an ACL, and find the canonical position for the
+ * specified entry
+ */
+unsigned int
+find_canonical_position(acl_t acl, acl_entry_t modifier) {
+
+ acl_entry_t entry;
+ int mscore = 0;
+ unsigned mpos = 0;
+
+ /* Check if there's an entry with the same qualifier
+ * and tag type; if not, find the appropriate slot
+ * for the score.
+ */
+
+ if (0 != acl_get_entry(acl, ACL_FIRST_ENTRY, &entry))
+ return 0;
+
+ mscore = score_acl_entry(modifier);
+
+ while (mscore < score_acl_entry(entry)) {
+
+ mpos++;
+
+ if (0 != acl_get_entry(acl, ACL_NEXT_ENTRY, &entry))
+ break;
+
+ }
+ return mpos;
+}
+
+int canonicalize_acl_entries(acl_t acl);
+
+/* For a given acl_entry_t "modifier", find the first exact or
+ * partially matching entry from the specified acl_t acl
+ */
+
+int
+find_matching_entry (acl_t acl, acl_entry_t modifier, acl_entry_t *rentryp,
+ unsigned match_inherited) {
+
+ acl_entry_t entry = NULL;
+
+ unsigned aindex;
+ int cmp, fcmp = MATCH_NONE;
+
+ for (aindex = 0;
+ acl_get_entry(acl, entry == NULL ? ACL_FIRST_ENTRY :
+ ACL_NEXT_ENTRY, &entry) == 0;
+ aindex++) {
+ cmp = compare_acl_entries(entry, modifier);
+ if ((cmp == MATCH_EXACT) || (cmp == MATCH_PARTIAL)) {
+ if (match_inherited) {
+ acl_flagset_t eflags, mflags;
+
+ if (0 != acl_get_flagset_np(modifier, &mflags)) {
+ err(1, "Unable to get flagset");
+ }
+
+ if (0 != acl_get_flagset_np(entry, &eflags)) {
+ err(1, "Unable to get flagset");
+ }
+
+ if (compare_acl_flagsets(mflags, eflags) == MATCH_EXACT) {
+ *rentryp = entry;
+ fcmp = cmp;
+ }
+ }
+ else {
+ *rentryp = entry;
+ fcmp = cmp;
+ }
+ }
+ if (fcmp == MATCH_EXACT)
+ break;
+ }
+ return fcmp;
+}
+
+/* Remove all perms specified in modifier from rentry*/
+int
+subtract_from_entry(acl_entry_t rentry, acl_entry_t modifier, int* valid_perms)
+{
+ acl_permset_t rperms, mperms;
+ acl_flagset_t rflags, mflags;
+ if (valid_perms)
+ *valid_perms = 0;
+ int i;
+
+ if ((acl_get_permset(rentry, &rperms) != 0) ||
+ (acl_get_flagset_np(rentry, &rflags) != 0) ||
+ (acl_get_permset(modifier, &mperms) != 0) ||
+ (acl_get_flagset_np(modifier, &mflags) != 0)) {
+ err(1, "error computing ACL modification");
+ }
+
+ for (i = 0; acl_perms[i].name != NULL; i++) {
+ if (acl_get_perm_np(mperms, acl_perms[i].perm))
+ acl_delete_perm(rperms, acl_perms[i].perm);
+ else if (valid_perms && acl_get_perm_np(rperms, acl_perms[i].perm))
+ (*valid_perms)++;
+ }
+ for (i = 0; acl_flags[i].name != NULL; i++) {
+ if (acl_get_flag_np(mflags, acl_flags[i].flag))
+ acl_delete_flag_np(rflags, acl_flags[i].flag);
+ }
+ acl_set_permset(rentry, rperms);
+ acl_set_flagset_np(rentry, rflags);
+ return 0;
+}
+/* Add the perms specified in modifier to rentry */
+static int
+merge_entry_perms(acl_entry_t rentry, acl_entry_t modifier)
+{
+ acl_permset_t rperms, mperms;
+ acl_flagset_t rflags, mflags;
+ int i;
+
+ if ((acl_get_permset(rentry, &rperms) != 0) ||
+ (acl_get_flagset_np(rentry, &rflags) != 0) ||
+ (acl_get_permset(modifier, &mperms) != 0) ||
+ (acl_get_flagset_np(modifier, &mflags) != 0)) {
+ err(1, "error computing ACL modification");
+ }
+
+ for (i = 0; acl_perms[i].name != NULL; i++) {
+ if (acl_get_perm_np(mperms, acl_perms[i].perm))
+ acl_add_perm(rperms, acl_perms[i].perm);
+ }
+ for (i = 0; acl_flags[i].name != NULL; i++) {
+ if (acl_get_flag_np(mflags, acl_flags[i].flag))
+ acl_add_flag_np(rflags, acl_flags[i].flag);
+ }
+ acl_set_permset(rentry, rperms);
+ acl_set_flagset_np(rentry, rflags);
+ return 0;
+}
+
+int
+modify_acl(acl_t *oaclp, acl_entry_t modifier, unsigned int optflags,
+ int position, int inheritance_level,
+ unsigned flag_new_acl, const char* path) {
+
+ unsigned cpos = 0;
+ acl_entry_t newent = NULL;
+ int dmatch = 0;
+ acl_entry_t rentry = NULL;
+ unsigned retval = 0;
+ acl_t oacl = *oaclp;
+
+/* Add the inherited flag if requested by the user*/
+ if (modifier && (optflags & ACL_INHERIT_FLAG)) {
+ acl_flagset_t mflags;
+
+ acl_get_flagset_np(modifier, &mflags);
+ acl_add_flag_np(mflags, ACL_ENTRY_INHERITED);
+ acl_set_flagset_np(modifier, mflags);
+ }
+
+ if (optflags & ACL_SET_FLAG) {
+ if (position != -1) {
+ if (0 != acl_create_entry_np(&oacl, &newent, position)) {
+ err(1, "acl_create_entry() failed");
+ }
+ acl_copy_entry(newent, modifier);
+ } else {
+/* If an entry exists, add the new permissions to it, else add an
+ * entry in the canonical position.
+ */
+
+/* First, check for a matching entry - if one exists, merge flags */
+ dmatch = find_matching_entry(oacl, modifier, &rentry, 1);
+
+ if (dmatch != MATCH_NONE) {
+ if (dmatch == MATCH_EXACT)
+/* Nothing to be done */
+ goto ma_exit;
+
+ if (dmatch == MATCH_PARTIAL) {
+ merge_entry_perms(rentry, modifier);
+ goto ma_exit;
+ }
+ }
+/* Insert the entry in canonical order */
+ cpos = find_canonical_position(oacl, modifier);
+ if (0!= acl_create_entry_np(&oacl, &newent, cpos)) {
+ err(1, "acl_create_entry() failed");
+ }
+ acl_copy_entry(newent, modifier);
+ }
+ } else if (optflags & ACL_DELETE_FLAG) {
+ if (flag_new_acl) {
+ warnx("No ACL present '%s'", path);
+ retval = 1;
+ } else if (position != -1 ) {
+ if (0 != acl_get_entry(oacl, position, &rentry)) {
+ warnx("Invalid entry number '%s'", path);
+ retval = 1;
+ } else {
+ acl_delete_entry(oacl, rentry);
+ }
+ } else {
+ unsigned match_found = 0, aindex;
+ for (aindex = 0;
+ acl_get_entry(oacl, rentry == NULL ?
+ ACL_FIRST_ENTRY :
+ ACL_NEXT_ENTRY, &rentry) == 0;
+ aindex++) {
+ unsigned cmp;
+ cmp = compare_acl_entries(rentry, modifier);
+ if ((cmp == MATCH_EXACT) ||
+ (cmp == MATCH_PARTIAL)) {
+ match_found++;
+ if (cmp == MATCH_EXACT)
+ acl_delete_entry(oacl, rentry);
+ else {
+ int valid_perms;
+/* In the event of a partial match, remove the specified perms from the
+ * entry */
+ subtract_from_entry(rentry, modifier, &valid_perms);
+ /* if no perms survived then delete the entry */
+ if (valid_perms == 0)
+ acl_delete_entry(oacl, rentry);
+ }
+ }
+ }
+ if (0 == match_found) {
+ warnx("Entry not found when attempting delete '%s'",path);
+ retval = 1;
+ }
+ }
+ } else if (optflags & ACL_REWRITE_FLAG) {
+ acl_entry_t rentry;
+
+ if (-1 == position) {
+ chmod_usage();
+ }
+ if (0 == flag_new_acl) {
+ if (0 != acl_get_entry(oacl, position,
+ &rentry)) {
+ err(1, "Invalid entry number '%s'", path);
+ }
+
+ if (0 != acl_delete_entry(oacl, rentry)) {
+ err(1, "Unable to delete entry '%s'", path);
+ }
+ }
+ if (0!= acl_create_entry_np(&oacl, &newent, position)) {
+ err(1, "acl_create_entry() failed");
+ }
+ acl_copy_entry(newent, modifier);
+ }
+ma_exit:
+ *oaclp = oacl;
+ return retval;
+}
+
+int
+modify_file_acl(unsigned int optflags, const char *path, acl_t modifier, int position, int inheritance_level, int follow) {
+
+ acl_t oacl = NULL;
+ unsigned aindex = 0, flag_new_acl = 0;
+ acl_entry_t newent = NULL;
+ acl_entry_t entry = NULL;
+ unsigned retval = 0;
+
+ extern __thread int chmod_fflag;
+
+/* XXX acl_get_file() returns a zero entry ACL if an ACL was previously
+ * associated with the file, and has had its entries removed.
+ * However, POSIX 1003.1e states that a zero entry ACL should be
+ * returned if the caller asks for ACL_TYPE_DEFAULT, and no ACL is
+ * associated with the path; it
+ * does not specifically state that a request for ACL_TYPE_EXTENDED
+ * should not return a zero entry ACL, however.
+ */
+
+/* Determine if we've been given a zero entry ACL, or create an ACL if
+ * none exists. There are some issues to consider here: Should we create
+ * a zero-entry ACL for a delete or check canonicity operation?
+ */
+
+ if (path == NULL)
+ chmod_usage();
+
+ if (optflags & ACL_CLEAR_FLAG) {
+ filesec_t fsec = filesec_init();
+ if (fsec == NULL) {
+ err(1, "filesec_init() failed");
+ }
+ if (filesec_set_property(fsec, FILESEC_ACL, _FILESEC_REMOVE_ACL) != 0) {
+ err(1, "filesec_set_property() failed");
+ }
+ if (follow) {
+ if (chmodx_np(path, fsec) != 0) {
+ if (!chmod_fflag) {
+ warn("Failed to clear ACL on file %s", path);
+ }
+ retval = 1;
+ }
+ } else {
+ int fd = open(path, O_SYMLINK);
+ if (fd != -1) {
+ if (fchmodx_np(fd, fsec) != 0) {
+ if (!chmod_fflag) {
+ warn("Failed to clear ACL on file %s", path);
+ }
+ retval = 1;
+ }
+ close(fd);
+ } else {
+ if (!chmod_fflag) {
+ warn("Failed to open file %s", path);
+ }
+ retval = 1;
+ }
+ }
+ filesec_free(fsec);
+ return (retval);
+ }
+
+ if (optflags & ACL_FROM_STDIN) {
+ oacl = acl_dup(modifier);
+ } else {
+ if (follow) {
+ oacl = acl_get_file(path, ACL_TYPE_EXTENDED);
+ } else {
+ int fd = open(path, O_SYMLINK);
+ if (fd != -1) {
+ oacl = acl_get_fd_np(fd, ACL_TYPE_EXTENDED);
+ close(fd);
+ }
+ }
+ if ((oacl == NULL) ||
+ (acl_get_entry(oacl,ACL_FIRST_ENTRY, &newent) != 0)) {
+ if ((oacl = acl_init(1)) == NULL) {
+ err(1, "acl_init() failed");
+ }
+ flag_new_acl = 1;
+ position = 0;
+ }
+
+ if ((0 == flag_new_acl) && (optflags & (ACL_REMOVE_INHERIT_FLAG |
+ ACL_REMOVE_INHERITED_ENTRIES))) {
+ acl_t facl = NULL;
+ if ((facl = acl_init(1)) == NULL) {
+ err(1, "acl_init() failed");
+ }
+ for (aindex = 0;
+ acl_get_entry(oacl,
+ (entry == NULL ? ACL_FIRST_ENTRY :
+ ACL_NEXT_ENTRY), &entry) == 0;
+ aindex++) {
+ acl_flagset_t eflags;
+ acl_entry_t fent = NULL;
+ if (acl_get_flagset_np(entry, &eflags) != 0) {
+ err(1, "Unable to obtain flagset");
+ }
+
+ if (acl_get_flag_np(eflags, ACL_ENTRY_INHERITED)) {
+ if (optflags & ACL_REMOVE_INHERIT_FLAG) {
+ acl_delete_flag_np(eflags, ACL_ENTRY_INHERITED);
+ acl_set_flagset_np(entry, eflags);
+ acl_create_entry(&facl, &fent);
+ acl_copy_entry(fent, entry);
+ }
+ }
+ else {
+ acl_create_entry(&facl, &fent);
+ acl_copy_entry(fent, entry);
+ }
+ }
+ if (oacl)
+ acl_free(oacl);
+ oacl = facl;
+ } else if (optflags & ACL_TO_STDOUT) {
+ ssize_t len; /* need to get printacl() from ls(1) */
+ char *text = acl_to_text(oacl, &len);
+ puts(text);
+ acl_free(text);
+ } else if (optflags & ACL_CHECK_CANONICITY) {
+ if (flag_new_acl) {
+ warnx("No ACL currently associated with file '%s'", path);
+ }
+ retval = is_canonical(oacl);
+ } else if ((optflags & ACL_SET_FLAG) && (position == -1) &&
+ (!is_canonical(oacl))) {
+ warnx("The specified file '%s' does not have an ACL in canonical order, please specify a position with +a# ", path);
+ retval = 1;
+ } else if (((optflags & ACL_DELETE_FLAG) && (position != -1))
+ || (optflags & ACL_CHECK_CANONICITY)) {
+ retval = modify_acl(&oacl, NULL, optflags, position,
+ inheritance_level, flag_new_acl, path);
+ } else if ((optflags & (ACL_REMOVE_INHERIT_FLAG|ACL_REMOVE_INHERITED_ENTRIES)) && flag_new_acl) {
+ warnx("No ACL currently associated with file '%s'", path);
+ retval = 1;
+ } else {
+ if (!modifier) { /* avoid bus error in acl_get_entry */
+ errx(1, "Internal error: modifier should not be NULL");
+ }
+ for (aindex = 0;
+ acl_get_entry(modifier,
+ (entry == NULL ? ACL_FIRST_ENTRY :
+ ACL_NEXT_ENTRY), &entry) == 0;
+ aindex++) {
+
+ retval += modify_acl(&oacl, entry, optflags,
+ position, inheritance_level,
+ flag_new_acl, path);
+ }
+ }
+ }
+
+/* XXX Potential race here, since someone else could've modified or
+ * read the ACL on this file (with the intention of modifying it) in
+ * the interval from acl_get_file() to acl_set_file(); we can
+ * minimize one aspect of this window by comparing the original acl
+ * to a fresh one from acl_get_file() but we could consider a
+ * "changeset" mechanism, common locking strategy, or kernel
+ * supplied reservation mechanism to prevent this race.
+ */
+ if (!(optflags & (ACL_TO_STDOUT|ACL_CHECK_CANONICITY))) {
+ int status = -1;
+ if (follow) {
+ status = acl_set_file(path, ACL_TYPE_EXTENDED, oacl);
+ } else {
+ int fd = open(path, O_SYMLINK);
+ if (fd != -1) {
+ status = acl_set_fd_np(fd, oacl,
+ ACL_TYPE_EXTENDED);
+ close(fd);
+ }
+ }
+ if (status != 0) {
+ if (!chmod_fflag)
+ warn("Failed to set ACL on file '%s'", path);
+ retval = 1;
+ }
+ }
+
+ if (oacl)
+ acl_free(oacl);
+
+ return retval;
+}
+
+#endif /*__APPLE__*/
diff --git a/files/Sources/files/chmod/chmod_acl.h b/files/Sources/files/chmod/chmod_acl.h
new file mode 100644
index 00000000..c76d076d
--- /dev/null
+++ b/files/Sources/files/chmod/chmod_acl.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef __APPLE__
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define ACL_FLAG (1<<0)
+#define ACL_SET_FLAG (1<<1)
+#define ACL_DELETE_FLAG (1<<2)
+#define ACL_REWRITE_FLAG (1<<3)
+#define ACL_ORDER_FLAG (1<<4)
+#define ACL_INHERIT_FLAG (1<<5)
+#define ACL_FOLLOW_LINK (1<<6)
+#define ACL_FROM_STDIN (1<<7)
+#define ACL_CHECK_CANONICITY (1<<8)
+#define ACL_REMOVE_INHERIT_FLAG (1<<9)
+#define ACL_REMOVE_INHERITED_ENTRIES (1<<10)
+#define ACL_NO_TRANSLATE (1<<11)
+#define ACL_INVOKE_EDITOR (1<<12)
+#define ACL_TO_STDOUT (1<<13)
+#define ACL_CLEAR_FLAG (1<<14)
+
+#define INHERITANCE_TIER (-5)
+#define MINIMUM_TIER (-1000)
+
+#define MATCH_EXACT (2)
+#define MATCH_PARTIAL (1)
+#define MATCH_NONE (-1)
+#define MATCH_SUBSET (-2)
+#define MATCH_SUPERSET (-3)
+
+#define MAX_ACL_TEXT_SIZE 4096
+#define MAX_INHERITANCE_LEVEL 1024
+
+extern int search_acl_block(char *tok);
+extern int parse_entry(char *entrybuf, acl_entry_t newent);
+extern acl_t parse_acl_entries(const char *input);
+extern int score_acl_entry(acl_entry_t entry);
+extern unsigned get_inheritance_level(acl_entry_t entry);
+extern int compare_acl_qualifiers(uuid_t *qa, uuid_t *qb);
+extern int compare_acl_permsets(acl_permset_t aperms, acl_permset_t bperms);
+extern int compare_acl_entries(acl_entry_t a, acl_entry_t b);
+extern unsigned is_canonical(acl_t acl);
+extern int find_matching_entry (acl_t acl, acl_entry_t modifier, acl_entry_t *rentry, unsigned match_inherited);
+extern unsigned find_canonical_position(acl_t acl, acl_entry_t modifier);
+extern int subtract_from_entry(acl_entry_t rentry, acl_entry_t modifier, int *valid_perms);
+extern int modify_acl(acl_t *oaclp, acl_entry_t modifier, unsigned int optflags, int position, int inheritance_level, unsigned flag_new_acl, const char* path);
+extern int modify_file_acl(unsigned int optflags, const char *path, acl_t modifier, int position, int inheritance_level, int follow);
+extern uuid_t *name_to_uuid(char *tok, int nametype);
+#endif /* __APPLE__*/
diff --git a/files/Sources/files/chown/chgrp.1 b/files/Sources/files/chown/chgrp.1
new file mode 100644
index 00000000..769c3d55
--- /dev/null
+++ b/files/Sources/files/chown/chgrp.1
@@ -0,0 +1,142 @@
+.\" Copyright (c) 1983, 1990, 1993, 1994
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the Institute of Electrical and Electronics Engineers, Inc.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)chgrp.1 8.3 (Berkeley) 3/31/94
+.\" $FreeBSD: src/usr.sbin/chown/chgrp.1,v 1.13 2001/08/15 09:09:46 ru Exp $
+.\"
+.Dd March 31, 1994
+.Dt CHGRP 1
+.Os
+.Sh NAME
+.Nm chgrp
+.Nd change group
+.Sh SYNOPSIS
+.Nm chgrp
+.Op Fl fhv
+.Oo
+.Fl R
+.Op Fl H | Fl L | Fl P
+.Oc
+.Ar group
+.Ar
+.Sh DESCRIPTION
+The
+.Nm chgrp
+utility sets the group ID of the file named by each
+.Ar file
+operand to the
+.Ar group
+ID specified by the group operand.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl f
+The force option ignores errors, except for usage errors and doesn't
+query about strange modes (unless the user does not have proper permissions).
+.It Fl H
+If the
+.Fl R
+option is specified, symbolic links on the command line are followed.
+(Symbolic links encountered in the tree traversal are not followed).
+.It Fl h
+If the file is a symbolic link, the group ID of the link itself is changed
+rather than the file that is pointed to.
+.It Fl L
+If the
+.Fl R
+option is specified, all symbolic links are followed.
+.It Fl P
+If the
+.Fl R
+option is specified, no symbolic links are followed.
+This is the default. Use
+.Fl h
+to change the group ID of a symbolic link.
+.It Fl R
+Change the group ID for the file hierarchies rooted
+in the files instead of just the files themselves.
+.It Fl v
+Cause
+.Nm chgrp
+to be verbose, showing files as the group is modified.
+.El
+.Pp
+The
+.Fl H ,
+.Fl L
+and
+.Fl P
+options are ignored unless the
+.Fl R
+option is specified.
+In addition, these options override each other and the
+command's actions are determined by the last one specified.
+.Pp
+The
+.Ar group
+operand can be either a group name from the group database,
+or a numeric group ID.
+If a group name is also a numeric group ID, the operand is used as a
+group name.
+.Pp
+The user invoking
+.Nm chgrp
+must belong to the specified group and be the owner of the file,
+or be the super-user.
+.Sh DIAGNOSTICS
+.Ex -std
+.Sh COMPATIBILITY
+In previous versions of this system, symbolic links did not have groups.
+.Pp
+The
+.Fl v
+option is non-standard and its use in scripts is not recommended.
+.Sh FILES
+.Bl -tag -width /etc/group -compact
+.It Pa /etc/group
+group ID file
+.El
+.Sh SEE ALSO
+.Xr chown 2 ,
+.Xr fts 3 ,
+.Xr group 5 ,
+.Xr passwd 5 ,
+.Xr symlink 7 ,
+.Xr chown 8
+.Sh STANDARDS
+The
+.Nm chgrp
+utility is expected to be
+.St -p1003.2
+compatible.
diff --git a/files/Sources/files/chown/chown.8 b/files/Sources/files/chown/chown.8
new file mode 100644
index 00000000..a3ffa093
--- /dev/null
+++ b/files/Sources/files/chown/chown.8
@@ -0,0 +1,175 @@
+.\" Copyright (c) 1990, 1991, 1993, 1994
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)chown.8 8.3 (Berkeley) 3/31/94
+.\" $FreeBSD: src/usr.sbin/chown/chown.8,v 1.20 2002/07/14 14:42:43 charnier Exp $
+.\"
+.Dd March 31, 1994
+.Dt CHOWN 8
+.Os
+.Sh NAME
+.Nm chown
+.Nd change file owner and group
+.Sh SYNOPSIS
+.Nm chown
+.Op Fl fhv
+.Oo
+.Fl R
+.Op Fl H | Fl L | Fl P
+.Oc
+.Ar owner Ns Op : Ns Ar group
+.Ar
+.Nm chown
+.Op Fl fhv
+.Oo
+.Fl R
+.Op Fl H | Fl L | Fl P
+.Oc
+.No : Ns Ar group
+.Ar
+.Sh DESCRIPTION
+The
+.Nm chown
+utility changes the user ID and/or the group ID of the specified files.
+Symbolic links named by arguments are silently left unchanged unless
+.Fl h
+is used.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl f
+Don't report any failure to change file owner or group, nor modify
+the exit status to reflect such failures.
+.It Fl H
+If the
+.Fl R
+option is specified, symbolic links on the command line are followed.
+(Symbolic links encountered in the tree traversal are not followed.)
+.It Fl h
+If the file is a symbolic link, change the user ID and/or the
+group ID of the link itself.
+.It Fl L
+If the
+.Fl R
+option is specified, all symbolic links are followed.
+.It Fl P
+If the
+.Fl R
+option is specified, no symbolic links are followed.
+Instead, the user and/or group ID of the link itself are modified.
+This is the default. Use
+.Fl h
+to change the user ID and/or the group of symbolic links.
+.It Fl R
+Change the user ID and/or the group ID for the file hierarchies rooted
+in the files instead of just the files themselves.
+.It Fl v
+Cause
+.Nm chown
+to be verbose, showing files as the owner is modified.
+.El
+.Pp
+The
+.Fl H ,
+.Fl L
+and
+.Fl P
+options are ignored unless the
+.Fl R
+option is specified.
+In addition, these options override each other and the
+command's actions are determined by the last one specified.
+.Pp
+The
+.Ar owner
+and
+.Ar group
+operands are both optional;
+however, at least one must be specified.
+If the
+.Ar group
+operand is specified, it must be preceded by a colon (``:'') character.
+.Pp
+The
+.Ar owner
+may be either a numeric user ID or a user name.
+If a user name is also a numeric user ID, the operand is used as a
+user name.
+The
+.Ar group
+may be either a numeric group ID or a group name.
+If a group name is also a numeric group ID, the operand is used as a
+group name.
+.Pp
+For obvious security reasons,
+the ownership of a file may only be altered by a super-user.
+Similarly, only a member of a group can change a file's group ID
+to that group.
+.Sh DIAGNOSTICS
+.Ex -std
+.Sh COMPATIBILITY
+Previous versions of the
+.Nm chown
+utility used the dot (``.'') character to distinguish the group name.
+This has been changed to be a colon (``:'') character,
+so that user and group names may contain the dot character.
+.Pp
+On previous versions of this system,
+symbolic links did not have owners.
+.Pp
+The
+.Fl v
+option is non-standard and its use in scripts is not recommended.
+.Sh LEGACY DESCRIPTION
+In legacy mode, the
+.Fl R
+and
+.Fl RP
+options do not change the user ID
+or the group ID of symbolic links.
+.Sh SEE ALSO
+.Xr chgrp 1 ,
+.Xr find 1 ,
+.Xr chown 2 ,
+.Xr fts 3 ,
+.Xr compat 5 ,
+.Xr symlink 7
+.Sh STANDARDS
+The
+.Nm chown
+utility is expected to be
+.St -p1003.2
+compliant.
+.Sh HISTORY
+A
+.Nm chown
+utility appeared in
+.At v1 .
diff --git a/files/Sources/files/chown/chown.c b/files/Sources/files/chown/chown.c
new file mode 100644
index 00000000..9b7db8cf
--- /dev/null
+++ b/files/Sources/files/chown/chown.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright (c) 1988, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include
+#ifndef lint
+__used static const char copyright[] =
+"@(#) Copyright (c) 1988, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)chown.c 8.8 (Berkeley) 4/4/94";
+#endif
+#endif /* not lint */
+
+#include
+__RCSID("$FreeBSD: src/usr.sbin/chown/chown.c,v 1.24 2002/07/17 16:22:24 dwmalone Exp $");
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "ios_error.h"
+
+#ifdef __APPLE__
+// #include
+// #else
+#define COMPAT_MODE(a,b) (1)
+#endif /* __APPLE__ */
+
+static void a_gid(const char *);
+static void a_uid(const char *);
+static void chownerr(const char *);
+static uid_t id(const char *, const char *);
+static void usage(void);
+
+static uid_t uid;
+static gid_t gid;
+static int ischown;
+static const char *gname;
+
+int
+chown_main(int argc, char **argv)
+{
+ FTS *ftsp;
+ FTSENT *p;
+ int Hflag, Lflag, Pflag, Rflag, fflag, hflag, vflag;
+ int ch, fts_options, rval;
+ char *cp;
+ int unix2003_compat = 0;
+ int symlink_found = 0;
+
+ if (argc < 1)
+ usage();
+ cp = strrchr(argv[0], '/');
+ cp = (cp != NULL) ? cp + 1 : argv[0];
+ ischown = (strcmp(cp, "chown") == 0);
+
+ Hflag = Lflag = Pflag = Rflag = fflag = hflag = vflag = 0;
+ optind = 1; opterr = 1; optreset = 1;
+ while ((ch = getopt(argc, argv, "HLPRfhv")) != -1)
+ switch (ch) {
+ case 'H':
+ Hflag = 1;
+ Lflag = Pflag = 0;
+ break;
+ case 'L':
+ Lflag = 1;
+ Hflag = Pflag = 0;
+ break;
+ case 'P':
+ Pflag = 1;
+ Hflag = Lflag = 0;
+ break;
+ case 'R':
+ Rflag = 1;
+ break;
+ case 'f':
+ fflag = 1;
+ break;
+ case 'h':
+ hflag = 1;
+ break;
+ case 'v':
+ vflag = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argv += optind;
+ argc -= optind;
+
+ if (argc < 2)
+ usage();
+ if (!Rflag && (Hflag || Lflag || Pflag))
+ warnx("options -H, -L, -P only useful with -R");
+
+ if (Rflag) {
+ fts_options = FTS_PHYSICAL;
+ if (hflag && (Hflag || Lflag)) {
+ errx(1, "the -R%c and -h options may not be "
+ "specified together\n", Hflag ? 'H' : 'L');
+ }
+ if (Hflag)
+ fts_options |= FTS_COMFOLLOW;
+ else if (Lflag) {
+ fts_options &= ~FTS_PHYSICAL;
+ fts_options |= FTS_LOGICAL;
+ }
+ } else
+ fts_options = hflag ? FTS_PHYSICAL : FTS_LOGICAL;
+
+ uid = (uid_t)-1;
+ gid = (gid_t)-1;
+ if (ischown) {
+ unix2003_compat = COMPAT_MODE("bin/chown", "Unix2003");
+ if ((cp = strchr(*argv, ':')) != NULL) {
+ *cp++ = '\0';
+ a_gid(cp);
+ }
+#ifdef SUPPORT_DOT
+ else if ((cp = strchr(*argv, '.')) != NULL) {
+ warnx("separation of user and group with a period is deprecated");
+ *cp++ = '\0';
+ a_gid(cp);
+ }
+#endif
+ a_uid(*argv);
+ } else {
+ unix2003_compat = COMPAT_MODE("bin/chgrp", "Unix2003");
+ a_gid(*argv);
+ }
+
+ if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL) {
+ err(1, NULL);
+ }
+
+ for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
+ symlink_found = 0;
+ switch (p->fts_info) {
+ case FTS_D: /* Change it at FTS_DP. */
+ if (!Rflag)
+ fts_set(ftsp, p, FTS_SKIP);
+ continue;
+ case FTS_DNR: /* Warn, chown. */
+ warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
+ rval = 1;
+ break;
+ case FTS_ERR: /* Warn, continue. */
+ case FTS_NS:
+ warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
+ rval = 1;
+ continue;
+ case FTS_SL:
+ case FTS_SLNONE:
+ /*
+ * The only symlinks that end up here are ones that
+ * don't point to anything and ones that we found
+ * doing a physical walk.
+ */
+ if (hflag)
+ break;
+ else {
+ symlink_found = 1;
+ if (unix2003_compat) {
+ if (Hflag || Lflag) { /* -H or -L was specified */
+ if (p->fts_errno) {
+ warnx("%s: %s", p->fts_name, strerror(p->fts_errno));
+ rval = 1;
+ continue;
+ }
+ }
+ break; /* Otherwise symlinks keep going */
+ }
+ continue;
+ }
+ default:
+ break;
+ }
+ if (unix2003_compat) {
+ /* Can only avoid updating times if both uid and gid are -1 */
+ if ((uid == (uid_t)-1) && (gid == (gid_t)-1))
+ continue;
+ } else {
+ if ((uid == (uid_t)-1 || uid == p->fts_statp->st_uid) &&
+ (gid == (gid_t)-1 || gid == p->fts_statp->st_gid))
+ continue;
+ }
+ if (((hflag || symlink_found) ? lchown : chown)(p->fts_accpath, uid, gid) == -1) {
+ if (!fflag) {
+ chownerr(p->fts_path);
+ rval = 1;
+ }
+ } else {
+ if (vflag)
+ fprintf(thread_stdout, "%s\n", p->fts_path);
+ }
+ }
+ if (errno) {
+ err(1, "fts_read");
+ }
+ exit(rval);
+}
+
+void
+a_gid(const char *s)
+{
+ struct group *gr;
+
+ if (*s == '\0') /* Argument was "uid[:.]". */
+ return;
+ gname = s;
+ gid = ((gr = getgrnam(s)) != NULL) ? gr->gr_gid : id(s, "group");
+}
+
+void
+a_uid(const char *s)
+{
+ struct passwd *pw;
+
+ if (*s == '\0') /* Argument was "[:.]gid". */
+ return;
+ uid = ((pw = getpwnam(s)) != NULL) ? pw->pw_uid : id(s, "user");
+}
+
+static uid_t
+id(const char *name, const char *type)
+{
+ unsigned long val;
+ char *ep;
+
+ errno = 0;
+ val = strtoul(name, &ep, 10);
+ if (errno || *ep != '\0' || val > UID_MAX) {
+ errx(1, "%s: illegal %s name", name, type);
+ }
+ return (uid_t)val;
+}
+
+void
+chownerr(const char *file)
+{
+ static uid_t euid = -1;
+ static int ngroups = -1;
+ gid_t groups[NGROUPS_MAX];
+
+ /* Check for chown without being root. */
+ if (errno != EPERM || (uid != (uid_t)-1 &&
+ euid == (uid_t)-1 && (euid = geteuid()) != 0)) {
+ warn("%s", file);
+ return;
+ }
+
+ /* Check group membership; kernel just returns EPERM. */
+ if (gid != (gid_t)-1 && ngroups == -1 &&
+ euid == (uid_t)-1 && (euid = geteuid()) != 0) {
+ ngroups = getgroups(NGROUPS_MAX, groups);
+ while (--ngroups >= 0 && gid != groups[ngroups]);
+ if (ngroups < 0) {
+ warnx("you are not a member of group %s", gname);
+ return;
+ }
+ }
+ warn("%s", file);
+}
+
+void
+usage(void)
+{
+
+ if (ischown)
+ (void)fprintf(stderr, "%s\n%s\n",
+ "usage: chown [-fhv] [-R [-H | -L | -P]] owner[:group]"
+ " file ...",
+ " chown [-fhv] [-R [-H | -L | -P]] :group file ...");
+ else
+ (void)fprintf(stderr, "%s\n",
+ "usage: chgrp [-fhv] [-R [-H | -L | -P]] group file ...");
+ exit(1);
+}
diff --git a/files/Sources/files/cksum/cksum.1 b/files/Sources/files/cksum/cksum.1
new file mode 100644
index 00000000..b4161fee
--- /dev/null
+++ b/files/Sources/files/cksum/cksum.1
@@ -0,0 +1,182 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the Institute of Electrical and Electronics Engineers, Inc.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)cksum.1 8.2 (Berkeley) 4/28/95
+.\" $FreeBSD: src/usr.bin/cksum/cksum.1,v 1.19 2005/01/17 07:44:13 ru Exp $
+.\"
+.Dd April 28, 1995
+.Dt CKSUM 1
+.Os
+.Sh NAME
+.Nm cksum ,
+.Nm sum
+.Nd display file checksums and block counts
+.Sh SYNOPSIS
+.Nm
+.Op Fl o Ar 1 | 2 | 3
+.Op Ar
+.Nm sum
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility writes to the standard output three whitespace separated
+fields for each input file.
+These fields are a checksum
+.Tn CRC ,
+the total number of octets in the file and the file name.
+If no file name is specified, the standard input is used and no file name
+is written.
+.Pp
+The
+.Nm sum
+utility is identical to the
+.Nm
+utility, except that it defaults to using historic algorithm 1, as
+described below.
+It is provided for compatibility only.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl o
+Use historic algorithms instead of the (superior) default one.
+.Pp
+Algorithm 1 is the algorithm used by historic
+.Bx
+systems as the
+.Xr sum 1
+algorithm and by historic
+.At V
+systems as the
+.Xr sum 1
+algorithm when using the
+.Fl r
+option.
+This is a 16-bit checksum, with a right rotation before each addition;
+overflow is discarded.
+.Pp
+Algorithm 2 is the algorithm used by historic
+.At V
+systems as the
+default
+.Xr sum 1
+algorithm.
+This is a 32-bit checksum, and is defined as follows:
+.Bd -unfilled -offset indent
+s = sum of all bytes;
+r = s % 2^16 + (s % 2^32) / 2^16;
+cksum = (r % 2^16) + r / 2^16;
+.Ed
+.Pp
+Algorithm 3 is what is commonly called the
+.Ql 32bit CRC
+algorithm.
+This is a 32-bit checksum.
+.Pp
+Both algorithm 1 and 2 write to the standard output the same fields as
+the default algorithm except that the size of the file in bytes is
+replaced with the size of the file in blocks.
+For historic reasons, the block size is 1024 for algorithm 1 and 512
+for algorithm 2.
+Partial blocks are rounded up.
+.El
+.Pp
+The default
+.Tn CRC
+used is based on the polynomial used for
+.Tn CRC
+error checking
+in the networking standard
+.St -iso8802-3 .
+The
+.Tn CRC
+checksum encoding is defined by the generating polynomial:
+.Pp
+.Bd -unfilled -offset indent
+G(x) = x^32 + x^26 + x^23 + x^22 + x^16 + x^12 +
+ x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
+.Ed
+.Pp
+Mathematically, the
+.Tn CRC
+value corresponding to a given file is defined by
+the following procedure:
+.Bd -ragged -offset indent
+The
+.Ar n
+bits to be evaluated are considered to be the coefficients of a mod 2
+polynomial M(x) of degree
+.Ar n Ns \-1 .
+These
+.Ar n
+bits are the bits from the file, with the most significant bit being the most
+significant bit of the first octet of the file and the last bit being the least
+significant bit of the last octet, padded with zero bits (if necessary) to
+achieve an integral number of octets, followed by one or more octets
+representing the length of the file as a binary value, least significant octet
+first.
+The smallest number of octets capable of representing this integer are used.
+.Pp
+M(x) is multiplied by x^32 (i.e., shifted left 32 bits) and divided by
+G(x) using mod 2 division, producing a remainder R(x) of degree <= 31.
+.Pp
+The coefficients of R(x) are considered to be a 32-bit sequence.
+.Pp
+The bit sequence is complemented and the result is the CRC.
+.Ed
+.Sh EXIT STATUS
+.Ex -std cksum sum
+.Sh SEE ALSO
+.Xr md5 1
+.Pp
+The default calculation is identical to that given in pseudo-code
+in the following
+.Tn ACM
+article.
+.Rs
+.%T "Computation of Cyclic Redundancy Checks Via Table Lookup"
+.%A Dilip V. Sarwate
+.%J "Communications of the" Tn ACM
+.%D "August 1988"
+.Re
+.Sh STANDARDS
+The
+.Nm
+utility is expected to conform to
+.St -p1003.2-92 .
+.Sh HISTORY
+The
+.Nm
+utility appeared in
+.Bx 4.4 .
diff --git a/files/Sources/files/cksum/cksum.c b/files/Sources/files/cksum/cksum.c
new file mode 100644
index 00000000..82015913
--- /dev/null
+++ b/files/Sources/files/cksum/cksum.c
@@ -0,0 +1,151 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James W. Williams of NASA Goddard Space Flight Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include
+#ifndef lint
+__used static const char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)cksum.c 8.2 (Berkeley) 4/28/95";
+#endif
+#endif /* not lint */
+
+#include
+__FBSDID("$FreeBSD: src/usr.bin/cksum/cksum.c,v 1.17 2003/03/13 23:32:28 robert Exp $");
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "extern.h"
+#include
+#include "ios_error.h" // remap exit to pthread_exit
+
+static void usage(void);
+
+int
+chksum_main(int argc, char **argv)
+{
+ uint32_t val;
+ int ch, fd, rval;
+ off_t len;
+ char *fn, *p;
+ int (*cfncn)(int, uint32_t *, off_t *);
+ void (*pfncn)(char *, u_int32_t, off_t);
+
+ cfncn=NULL;
+ optind = 1; opterr = 1; optreset = 1;
+
+ if(*argv) {
+ if ((p = rindex(argv[0], '/')) == NULL)
+ p = argv[0];
+ else
+ ++p;
+ if (!strcmp(p, "sum")) {
+ cfncn = csum1;
+ pfncn = psum1;
+ ++argv;
+ }
+ }
+
+ if(!cfncn) {
+ cfncn = crc;
+ pfncn = pcrc;
+
+ while ((ch = getopt(argc, argv, "o:")) != -1)
+ switch (ch) {
+ case 'o':
+ if (!strcmp(optarg, "1")) {
+ cfncn = csum1;
+ pfncn = psum1;
+ } else if (!strcmp(optarg, "2")) {
+ cfncn = csum2;
+ pfncn = psum2;
+ } else if (!strcmp(optarg, "3")) {
+ cfncn = chksum_crc32;
+ pfncn = pcrc;
+ } else {
+ warnx("illegal argument to -o option");
+ usage();
+ }
+ break;
+ case '?':
+ default:
+ usage();
+ }
+// argc -= optind;
+ argv += optind;
+ }
+
+ fd = fileno(thread_stdin);
+ fn = NULL;
+ rval = 0;
+ do {
+ if (*argv) {
+ fn = *argv++;
+ if ((fd = open(fn, O_RDONLY, 0)) < 0) {
+ warn("%s", fn);
+ rval = 1;
+ continue;
+ }
+ }
+ if (cfncn(fd, &val, &len)) {
+ warn("%s", fn ? fn : "stdin");
+ rval = 1;
+ } else
+ pfncn(fn, val, len);
+ (void)close(fd);
+ } while (*argv);
+ exit(rval);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: cksum [-o 1 | 2 | 3] [file ...]\n");
+ (void)fprintf(stderr, " sum [file ...]\n");
+ exit(1);
+}
diff --git a/files/Sources/files/cksum/crc.c b/files/Sources/files/cksum/crc.c
new file mode 100644
index 00000000..57179d5d
--- /dev/null
+++ b/files/Sources/files/cksum/crc.c
@@ -0,0 +1,148 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James W. Williams of NASA Goddard Space Flight Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)crc.c 8.1 (Berkeley) 6/17/93";
+#endif
+#endif /* not lint */
+#include
+__FBSDID("$FreeBSD: src/usr.bin/cksum/crc.c,v 1.8 2003/03/13 23:32:28 robert Exp $");
+
+#include
+
+#include
+#include
+
+#include "extern.h"
+
+static const uint32_t crctab[] = {
+ 0x0,
+ 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
+ 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
+ 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
+ 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
+ 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
+ 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
+ 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+ 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
+ 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
+ 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
+ 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
+ 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
+ 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
+ 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
+ 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
+ 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
+ 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
+ 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
+ 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+ 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
+ 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
+ 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
+ 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
+ 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
+ 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
+ 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
+ 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
+ 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
+ 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
+ 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
+ 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
+ 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
+ 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
+ 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
+ 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
+ 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
+ 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
+ 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
+ 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
+ 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
+ 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
+ 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
+ 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
+ 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
+ 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
+ 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
+ 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
+ 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
+ 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
+ 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
+ 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
+};
+
+/*
+ * Compute a POSIX 1003.2 checksum. This routine has been broken out so that
+ * other programs can use it. It takes a file descriptor to read from and
+ * locations to store the crc and the number of bytes read. It returns 0 on
+ * success and 1 on failure. Errno is set on failure.
+ */
+uint32_t crc_total = ~0; /* The crc over a number of files. */
+
+int
+crc(int fd, uint32_t *cval, off_t *clen)
+{
+ uint32_t lcrc;
+ ssize_t nr;
+ off_t len;
+ u_char *p;
+ u_char buf[16 * 1024];
+
+#define COMPUTE(var, ch) (var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)]
+
+ lcrc = 0;
+ len = 0;
+ crc_total = ~crc_total;
+ while ((nr = read(fd, buf, sizeof(buf))) > 0)
+ for (len += nr, p = buf; nr--; ++p) {
+ COMPUTE(lcrc, *p);
+ COMPUTE(crc_total, *p);
+ }
+ if (nr < 0)
+ return (1);
+
+ *clen = len;
+
+ /* Include the length of the file. */
+ for (; len != 0; len >>= 8) {
+ COMPUTE(lcrc, len & 0xff);
+ COMPUTE(crc_total, len & 0xff);
+ }
+
+ *cval = ~lcrc;
+ crc_total = ~crc_total;
+ return (0);
+}
diff --git a/files/Sources/files/cksum/crc32.c b/files/Sources/files/cksum/crc32.c
new file mode 100644
index 00000000..0dfc89f5
--- /dev/null
+++ b/files/Sources/files/cksum/crc32.c
@@ -0,0 +1,122 @@
+/*
+ * This code implements the AUTODIN II polynomial used by Ethernet,
+ * and can be used to calculate multicast address hash indices.
+ * It assumes that the low order bits will be transmitted first,
+ * and consequently the low byte should be sent first when
+ * the crc computation is finished. The crc should be complemented
+ * before transmission.
+ * The variable corresponding to the macro argument "crc" should
+ * be an unsigned long and should be preset to all ones for Ethernet
+ * use. An error-free packet will leave 0xDEBB20E3 in the crc.
+ * Spencer Garrett
+ */
+
+#include
+__FBSDID("$FreeBSD: src/usr.bin/cksum/crc32.c,v 1.9 2003/03/13 23:32:28 robert Exp $");
+
+#include
+
+#include
+#include
+#include
+
+#include "extern.h"
+
+#define CRC(crc, ch) (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff])
+
+/* generated using the AUTODIN II polynomial
+ * x^32 + x^26 + x^23 + x^22 + x^16 +
+ * x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
+ */
+static const uint32_t crctab[256] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+};
+
+uint32_t crc32_total = 0;
+
+int
+chksum_crc32(int fd, uint32_t *cval, off_t *clen)
+{
+ uint32_t lcrc = ~0;
+ ssize_t nr;
+ off_t len ;
+ char buf[BUFSIZ], *p ;
+
+ len = 0 ;
+ crc32_total = ~crc32_total ;
+ while ((nr = read(fd, buf, sizeof(buf))) > 0)
+ for (len += nr, p = buf; nr--; ++p) {
+ CRC(lcrc, *p) ;
+ CRC(crc32_total, *p) ;
+ }
+ if (nr < 0)
+ return 1 ;
+
+ *clen = len ;
+ *cval = ~lcrc ;
+ crc32_total = ~crc32_total ;
+ return 0 ;
+}
diff --git a/files/Sources/files/cksum/extern.h b/files/Sources/files/cksum/extern.h
new file mode 100644
index 00000000..addf8b48
--- /dev/null
+++ b/files/Sources/files/cksum/extern.h
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)extern.h 8.1 (Berkeley) 6/6/93
+ * $FreeBSD: src/usr.bin/cksum/extern.h,v 1.6 2003/03/13 23:32:28 robert Exp $
+ */
+
+#include
+
+__BEGIN_DECLS
+int crc(int, uint32_t *, off_t *);
+void pcrc(char *, uint32_t, off_t);
+void psum1(char *, uint32_t, off_t);
+void psum2(char *, uint32_t, off_t);
+int csum1(int, uint32_t *, off_t *);
+int csum2(int, uint32_t *, off_t *);
+int chksum_crc32(int, uint32_t *, off_t *);
+__END_DECLS
diff --git a/files/Sources/files/cksum/print.c b/files/Sources/files/cksum/print.c
new file mode 100644
index 00000000..8b9c99c5
--- /dev/null
+++ b/files/Sources/files/cksum/print.c
@@ -0,0 +1,76 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)print.c 8.1 (Berkeley) 6/6/93";
+#endif
+#endif /* not lint */
+
+#include
+__FBSDID("$FreeBSD: src/usr.bin/cksum/print.c,v 1.7 2003/03/13 23:32:28 robert Exp $");
+
+#include
+
+#include
+#include
+
+#include "extern.h"
+#include "ios_error.h"
+
+void
+pcrc(char *fn, uint32_t val, off_t len)
+{
+ (void)fprintf(thread_stdout, "%lu %jd", (u_long)val, (intmax_t)len);
+ if (fn != NULL)
+ (void)fprintf(thread_stdout, " %s", fn);
+ (void)fprintf(thread_stdout, "\n");
+}
+
+void
+psum1(char *fn, uint32_t val, off_t len)
+{
+ (void)fprintf(thread_stdout, "%lu %jd", (u_long)val, (intmax_t)(len + 1023) / 1024);
+ if (fn != NULL)
+ (void)fprintf(thread_stdout, " %s", fn);
+ (void)fprintf(thread_stdout, "\n");
+}
+
+void
+psum2(char *fn, uint32_t val, off_t len)
+{
+ (void)fprintf(thread_stdout, "%lu %jd", (u_long)val, (intmax_t)(len + 511) / 512);
+ if (fn != NULL)
+ (void)fprintf(thread_stdout, " %s", fn);
+ (void)fprintf(thread_stdout, "\n");
+}
diff --git a/files/Sources/files/cksum/sum.1 b/files/Sources/files/cksum/sum.1
new file mode 100644
index 00000000..db048008
--- /dev/null
+++ b/files/Sources/files/cksum/sum.1
@@ -0,0 +1 @@
+.so man1/cksum.1
diff --git a/files/Sources/files/cksum/sum1.c b/files/Sources/files/cksum/sum1.c
new file mode 100644
index 00000000..fa016ce2
--- /dev/null
+++ b/files/Sources/files/cksum/sum1.c
@@ -0,0 +1,77 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)sum1.c 8.1 (Berkeley) 6/6/93";
+#endif
+#endif /* not lint */
+
+#include
+__FBSDID("$FreeBSD: src/usr.bin/cksum/sum1.c,v 1.8 2003/03/13 23:32:28 robert Exp $");
+
+#include
+
+#include
+#include
+
+#include "extern.h"
+
+int
+csum1(int fd, uint32_t *cval, off_t *clen)
+{
+ ssize_t nr;
+ u_int lcrc;
+ off_t total;
+ u_char *p;
+ u_char buf[8192];
+
+ /*
+ * 16-bit checksum, rotating right before each addition;
+ * overflow is discarded.
+ */
+ lcrc = 0;
+ total = 0;
+ while ((nr = read(fd, buf, sizeof(buf))) > 0)
+ for (total += nr, p = buf; nr--; ++p) {
+ if (lcrc & 1)
+ lcrc |= 0x10000;
+ lcrc = ((lcrc >> 1) + *p) & 0xffff;
+ }
+ if (nr < 0)
+ return (1);
+
+ *cval = lcrc;
+ *clen = total;
+ return (0);
+}
diff --git a/files/Sources/files/cksum/sum2.c b/files/Sources/files/cksum/sum2.c
new file mode 100644
index 00000000..126b4280
--- /dev/null
+++ b/files/Sources/files/cksum/sum2.c
@@ -0,0 +1,79 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)sum2.c 8.1 (Berkeley) 6/6/93";
+#endif
+#endif /* not lint */
+#include
+__FBSDID("$FreeBSD: src/usr.bin/cksum/sum2.c,v 1.8 2003/03/13 23:32:28 robert Exp $");
+
+#include
+
+#include
+#include
+
+#include "extern.h"
+
+int
+csum2(int fd, uint32_t *cval, off_t *clen)
+{
+ uint32_t lcrc;
+ ssize_t nr;
+ off_t total;
+ u_char *p;
+ u_char buf[8192];
+
+ /*
+ * Draft 8 POSIX 1003.2:
+ *
+ * s = sum of all bytes
+ * r = s % 2^16 + (s % 2^32) / 2^16
+ * lcrc = (r % 2^16) + r / 2^16
+ */
+ lcrc = 0;
+ total = 0;
+ while ((nr = read(fd, buf, sizeof(buf))) > 0)
+ for (total += nr, p = buf; nr--; ++p)
+ lcrc += *p;
+ if (nr < 0)
+ return (1);
+
+ lcrc = (lcrc & 0xffff) + (lcrc >> 16);
+ lcrc = (lcrc & 0xffff) + (lcrc >> 16);
+
+ *cval = lcrc;
+ *clen = total;
+ return (0);
+}
diff --git a/files/Sources/files/compress/compress.1 b/files/Sources/files/compress/compress.1
new file mode 100644
index 00000000..a353c19a
--- /dev/null
+++ b/files/Sources/files/compress/compress.1
@@ -0,0 +1,253 @@
+.\" Copyright (c) 1986, 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" James A. Woods, derived from original work by Spencer Thomas
+.\" and Joseph Orost.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)compress.1 8.2 (Berkeley) 4/18/94
+.\" $FreeBSD: src/usr.bin/compress/compress.1,v 1.23 2010/12/11 08:32:16 joel Exp $
+.\"
+.Dd May 17, 2002
+.Dt COMPRESS 1
+.Os
+.Sh NAME
+.Nm compress ,
+.Nm uncompress
+.Nd compress and expand data
+.Sh SYNOPSIS
+.Nm
+.Op Fl fv
+.Op Fl b Ar bits
+.Op Ar
+.Nm
+.Fl c
+.Op Fl b Ar bits
+.Op Ar file
+.Nm uncompress
+.Op Fl fv
+.Op Ar
+.Nm uncompress
+.Fl c
+.Op Ar file
+.Sh DESCRIPTION
+The
+.Nm
+utility reduces the size of files using adaptive Lempel-Ziv coding.
+Each
+.Ar file
+is renamed to the same name plus the extension
+.Pa .Z .
+A
+.Ar file
+argument with a
+.Pa .Z
+extension will be ignored except it will cause an
+error exit after other arguments are processed.
+If compression would not reduce the size of a
+.Ar file ,
+the file is ignored.
+.Pp
+The
+.Nm uncompress
+utility restores compressed files to their original form, renaming the
+files by deleting the
+.Pa .Z
+extensions.
+A file specification need not include the file's
+.Pa .Z
+extension.
+If a file's name in its file system does not have a
+.Pa .Z
+extension, it will not be uncompressed and it will cause
+an error exit after other arguments are processed.
+.Pp
+If renaming the files would cause files to be overwritten and the standard
+input device is a terminal, the user is prompted (on the standard error
+output) for confirmation.
+If prompting is not possible or confirmation is not received, the files
+are not overwritten.
+.Pp
+As many of the modification time, access time, file flags, file mode,
+user ID, and group ID as allowed by permissions are retained in the
+new file.
+.Pp
+If no files are specified or a
+.Ar file
+argument is a single dash
+.Pq Sq Fl ,
+the standard input is compressed or uncompressed to the standard output.
+If either the input and output files are not regular files, the checks for
+reduction in size and file overwriting are not performed, the input file is
+not removed, and the attributes of the input file are not retained
+in the output file.
+.Pp
+The options are as follows:
+.Bl -tag -width ".Fl b Ar bits"
+.It Fl b Ar bits
+The code size (see below) is limited to
+.Ar bits ,
+which must be in the range 9..16.
+The default is 16.
+.It Fl c
+Compressed or uncompressed output is written to the standard output.
+No files are modified.
+The
+.Fl v
+option is ignored.
+Compression is attempted even if the results will be larger than the
+original.
+.It Fl f
+Files are overwritten without prompting for confirmation.
+Also, for
+.Nm compress ,
+files are compressed even if they are not actually reduced in size.
+.It Fl v
+Print the percentage reduction of each file.
+Ignored by
+.Nm uncompress
+or if the
+.Fl c
+option is also used.
+.El
+.Pp
+The
+.Nm
+utility uses a modified Lempel-Ziv algorithm.
+Common substrings in the file are first replaced by 9-bit codes 257 and up.
+When code 512 is reached, the algorithm switches to 10-bit codes and
+continues to use more bits until the
+limit specified by the
+.Fl b
+option or its default is reached.
+.Pp
+After the limit is reached,
+.Nm
+periodically checks the compression ratio.
+If it is increasing,
+.Nm
+continues to use the existing code dictionary.
+However, if the compression ratio decreases,
+.Nm
+discards the table of substrings and rebuilds it from scratch.
+This allows
+the algorithm to adapt to the next "block" of the file.
+.Pp
+The
+.Fl b
+option is unavailable for
+.Nm uncompress
+since the
+.Ar bits
+parameter specified during compression
+is encoded within the output, along with
+a magic number to ensure that neither decompression of random data nor
+recompression of compressed data is attempted.
+.Pp
+The amount of compression obtained depends on the size of the
+input, the number of
+.Ar bits
+per code, and the distribution of common substrings.
+Typically, text such as source code or English is reduced by 50\-60%.
+Compression is generally much better than that achieved by Huffman
+coding (as used in the historical command pack), or adaptive Huffman
+coding (as used in the historical command compact), and takes less
+time to compute.
+.Sh EXIT STATUS
+.Ex -std compress uncompress
+.Pp
+The
+.Nm compress
+utility exits 2 if attempting to compress a file would not reduce its size
+and the
+.Fl f
+option was not specified and if no other error occurs.
+.Sh SEE ALSO
+.Xr gunzip 1 ,
+.Xr gzexe 1 ,
+.Xr gzip 1 ,
+.Xr zcat 1 ,
+.Xr zmore 1 ,
+.Xr znew 1
+.Rs
+.%A Welch, Terry A.
+.%D June, 1984
+.%T "A Technique for High Performance Data Compression"
+.%J "IEEE Computer"
+.%V 17:6
+.%P pp. 8-19
+.Re
+.Sh STANDARDS
+The
+.Nm compress
+and
+.Nm uncompress
+utilities conform to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 .
+.Sh BUGS
+Some of these might be considered otherwise-undocumented features.
+.Pp
+.Nm compress :
+If the utility does not compress a file because doing so would not
+reduce its size, and a file of the same name except with an
+.Pa .Z
+extension exists, the named file is not really ignored as stated above;
+it causes a prompt to confirm the overwriting of the file with the extension.
+If the operation is confirmed, that file is deleted.
+.Pp
+.Nm uncompress :
+If an empty file is compressed (using
+.Fl f ) ,
+the resulting
+.Pa .Z
+file is also empty.
+That seems right, but if
+.Nm uncompress
+is then used on that file, an error will occur.
+.Pp
+Both utilities: If a
+.Sq Fl
+argument is used and the utility prompts the user, the standard input
+is taken as the user's reply to the prompt.
+.Pp
+Both utilities:
+If the specified file does not exist, but a similarly-named one with (for
+.Nm compress )
+or without (for
+.Nm uncompress )
+a
+.Pa .Z
+extension does exist, the utility will waste the user's time by not
+immediately emitting an error message about the missing file and
+continuing.
+Instead, it first asks for confirmation to overwrite
+the existing file and then does not overwrite it.
diff --git a/files/Sources/files/compress/compress.c b/files/Sources/files/compress/compress.c
new file mode 100644
index 00000000..e83cd1a9
--- /dev/null
+++ b/files/Sources/files/compress/compress.c
@@ -0,0 +1,465 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include
+#ifndef lint
+__used static const char copyright[] =
+"@(#) Copyright (c) 1992, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)compress.c 8.2 (Berkeley) 1/7/94";
+#endif
+#endif
+
+#include
+__FBSDID("$FreeBSD: src/usr.bin/compress/compress.c,v 1.23 2010/12/11 08:32:16 joel Exp $");
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "zopen.h"
+#include "ios_error.h"
+
+static void compress(const char *, const char *, int);
+static void cwarn(const char *, ...) __printflike(1, 2);
+static void cwarnx(const char *, ...) __printflike(1, 2);
+static void decompress(const char *, const char *, int);
+static int permission(const char *);
+static void setfile(const char *, struct stat *);
+static void usage(int);
+
+static int eval, force, verbose, cat;
+
+int
+compress_main(int argc, char *argv[])
+{
+ enum {COMPRESS, DECOMPRESS} style = 0;
+ size_t len;
+ int bits, ch;
+ char *p, newname[MAXPATHLEN];
+
+ if (argc < 1)
+ usage(1);
+ // init all flags
+ eval = force = verbose = cat = 0;
+ optind = 1; opterr = 1; optreset = 1;
+ if ((p = rindex(argv[0], '/')) == NULL)
+ p = argv[0];
+ else
+ ++p;
+ if (!strcmp(p, "uncompress"))
+ style = DECOMPRESS;
+ else if (!strcmp(p, "compress"))
+ style = COMPRESS;
+ else if (!strcmp(p, "zcat")) {
+ cat = 1;
+ style = DECOMPRESS;
+ } else {
+ // errx(1, "unknown program name");
+ fprintf(thread_stderr, "unknown program name: %s\n", p);
+ ios_exit(1);
+ }
+
+ bits = 0;
+ while ((ch = getopt(argc, argv, "b:cdfv")) != -1)
+ switch(ch) {
+ case 'b':
+ bits = strtol(optarg, &p, 10);
+ if (*p) {
+ errx(1, "illegal bit count -- %s", optarg);
+ }
+ break;
+ case 'c':
+ cat = 1;
+ break;
+ case 'd': /* Backward compatible. */
+ style = DECOMPRESS;
+ break;
+ case 'f':
+ force = 1;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case '?':
+ default:
+ usage(style == COMPRESS);
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0) {
+ cat = 1;
+ switch(style) {
+ case COMPRESS:
+ (void)compress("/dev/stdin", "/dev/stdout", bits);
+ break;
+ case DECOMPRESS:
+ (void)decompress("/dev/stdin", "/dev/stdout", bits);
+ break;
+ }
+ exit (eval);
+ }
+
+ if (cat == 1 && argc > 1) {
+ errx(1, "the -c option permits only a single file argument");
+ }
+
+ for (; *argv; ++argv)
+ switch(style) {
+ case COMPRESS:
+ if (strcmp(*argv, "-") == 0) {
+ cat = 1;
+ compress("/dev/stdin", "/dev/stdout", bits);
+ break;
+ } else if (cat) {
+ compress(*argv, "/dev/stdout", bits);
+ break;
+ }
+ if ((p = rindex(*argv, '.')) != NULL &&
+ !strcmp(p, ".Z")) {
+ cwarnx("%s: name already has trailing .Z",
+ *argv);
+ break;
+ }
+ len = strlen(*argv);
+ if (len > sizeof(newname) - 3) {
+ cwarnx("%s: name too long", *argv);
+ break;
+ }
+ memmove(newname, *argv, len);
+ newname[len] = '.';
+ newname[len + 1] = 'Z';
+ newname[len + 2] = '\0';
+ compress(*argv, newname, bits);
+ break;
+ case DECOMPRESS:
+ if (strcmp(*argv, "-") == 0) {
+ cat = 1;
+ decompress("/dev/stdin", "/dev/stdout", bits);
+ break;
+ }
+ len = strlen(*argv);
+ if ((p = rindex(*argv, '.')) == NULL ||
+ strcmp(p, ".Z")) {
+ if (len > sizeof(newname) - 3) {
+ cwarnx("%s: name too long", *argv);
+ break;
+ }
+ memmove(newname, *argv, len);
+ newname[len] = '.';
+ newname[len + 1] = 'Z';
+ newname[len + 2] = '\0';
+ decompress(newname,
+ cat ? "/dev/stdout" : *argv, bits);
+ } else {
+ if (len - 2 > sizeof(newname) - 1) {
+ cwarnx("%s: name too long", *argv);
+ break;
+ }
+ memmove(newname, *argv, len - 2);
+ newname[len - 2] = '\0';
+ decompress(*argv,
+ cat ? "/dev/stdout" : newname, bits);
+ }
+ break;
+ }
+ exit (eval);
+}
+
+void
+compress(const char *in, const char *out, int bits)
+{
+ size_t nr;
+ struct stat isb, sb;
+ FILE *ifp = NULL, *ofp = NULL;
+ int exists, isreg, oreg;
+ u_char buf[1024];
+
+ exists = !stat(out, &sb);
+ if (!force && exists && S_ISREG(sb.st_mode) && !cat && !permission(out)) {
+ cwarnx("%s already exists", out);
+ return;
+ }
+ isreg = oreg = !exists || S_ISREG(sb.st_mode);
+
+ if ((ifp = fopen(in, "r")) == NULL) {
+ cwarn("%s", in);
+ return;
+ }
+ if (stat(in, &isb)) { /* DON'T FSTAT! */
+ cwarn("%s", in);
+ goto err;
+ }
+ if (!S_ISREG(isb.st_mode))
+ isreg = 0;
+
+ if ((ofp = zopen(out, "w", bits)) == NULL) {
+ cwarn("%s", out);
+ goto err;
+ }
+ while ((nr = fread(buf, 1, sizeof(buf), ifp)) != 0)
+ if (fwrite(buf, 1, nr, ofp) != nr) {
+ cwarn("%s", out);
+ goto err;
+ }
+
+ if (ferror(ifp) || fclose(ifp)) {
+ cwarn("%s", in);
+ goto err;
+ }
+ ifp = NULL;
+
+ if (fclose(ofp)) {
+ cwarn("%s", out);
+ goto err;
+ }
+ ofp = NULL;
+
+ if (!cat && isreg) {
+ if (stat(out, &sb)) {
+ cwarn("%s", out);
+ goto err;
+ }
+
+ if (!force && sb.st_size >= isb.st_size) {
+ if (verbose)
+ (void)fprintf(stderr, "compress: %s: file would grow; left unmodified\n",
+ in);
+ eval = 2;
+ if (unlink(out))
+ cwarn("%s", out);
+ goto err;
+ }
+
+ setfile(out, &isb);
+
+ if (unlink(in))
+ cwarn("%s", in);
+
+ if (verbose) {
+ (void)fprintf(stderr, "%s: ", out);
+ if (isb.st_size > sb.st_size)
+ (void)fprintf(stderr, "%.0f%% compression\n",
+ ((float)sb.st_size / isb.st_size) * 100.0);
+ else
+ (void)fprintf(stderr, "%.0f%% expansion\n",
+ ((float)isb.st_size / sb.st_size) * 100.0);
+ }
+ }
+ return;
+
+err: if (ofp) {
+ if (!cat && oreg)
+ (void)unlink(out);
+ (void)fclose(ofp);
+ }
+ if (ifp)
+ (void)fclose(ifp);
+}
+
+void
+decompress(const char *in, const char *out, int bits)
+{
+ size_t nr;
+ struct stat sb;
+ FILE *ifp, *ofp;
+ int exists, isreg, oreg;
+ u_char buf[1024];
+
+ exists = !stat(out, &sb);
+ if (!force && exists && S_ISREG(sb.st_mode) && !cat && !permission(out)) {
+ cwarnx("%s already exists", out);
+ return;
+ }
+ isreg = oreg = !exists || S_ISREG(sb.st_mode);
+
+ ofp = NULL;
+ if ((ifp = zopen(in, "r", bits)) == NULL) {
+ cwarn("%s", in);
+ return;
+ }
+ if (stat(in, &sb)) {
+ cwarn("%s", in);
+ goto err;
+ }
+ if (!S_ISREG(sb.st_mode))
+ isreg = 0;
+
+ /*
+ * Try to read the first few uncompressed bytes from the input file
+ * before blindly truncating the output file.
+ */
+ if ((nr = fread(buf, 1, sizeof(buf), ifp)) == 0) {
+ cwarn("%s", in);
+ (void)fclose(ifp);
+ return;
+ }
+ if ((ofp = fopen(out, "w")) == NULL ||
+ (nr != 0 && fwrite(buf, 1, nr, ofp) != nr)) {
+ cwarn("%s", out);
+ (void)fclose(ifp);
+ return;
+ }
+
+ while ((nr = fread(buf, 1, sizeof(buf), ifp)) != 0)
+ if (fwrite(buf, 1, nr, ofp) != nr) {
+ cwarn("%s", out);
+ goto err;
+ }
+
+ if (ferror(ifp) || fclose(ifp)) {
+ cwarn("%s", in);
+ goto err;
+ }
+ ifp = NULL;
+
+ if (fclose(ofp)) {
+ cwarn("%s", out);
+ goto err;
+ }
+
+ if (!cat && isreg) {
+ setfile(out, &sb);
+
+ if (unlink(in))
+ cwarn("%s", in);
+ if (verbose) {
+ struct stat isb = sb;
+ stat(out, &sb);
+ (void)fprintf(stderr, "%s: ", out);
+ if (isb.st_size > sb.st_size)
+ (void)fprintf(stderr, "%.0f%% compression\n",
+ ((float)sb.st_size / isb.st_size) * 100.0);
+ else
+ (void)fprintf(stderr, "%.0f%% expansion\n",
+ ((float)isb.st_size / sb.st_size) * 100.0);
+ }
+ }
+ return;
+
+err: if (ofp) {
+ if (!cat && oreg)
+ (void)unlink(out);
+ (void)fclose(ofp);
+ }
+ if (ifp)
+ (void)fclose(ifp);
+}
+
+void
+setfile(const char *name, struct stat *fs)
+{
+ static struct timeval tv[2];
+
+ fs->st_mode &= S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
+
+ TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec);
+ TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec);
+ if (utimes(name, tv))
+ cwarn("utimes: %s", name);
+
+ /*
+ * Changing the ownership probably won't succeed, unless we're root
+ * or POSIX_CHOWN_RESTRICTED is not set. Set uid/gid before setting
+ * the mode; current BSD behavior is to remove all setuid bits on
+ * chown. If chown fails, lose setuid/setgid bits.
+ */
+ if (chown(name, fs->st_uid, fs->st_gid)) {
+ if (errno != EPERM)
+ cwarn("chown: %s", name);
+ fs->st_mode &= ~(S_ISUID|S_ISGID);
+ }
+ if (chmod(name, fs->st_mode) && errno != ENOTSUP)
+ cwarn("chmod: %s", name);
+
+ if (chflags(name, fs->st_flags) && errno != ENOTSUP)
+ cwarn("chflags: %s", name);
+}
+
+int
+permission(const char *fname)
+{
+ int ch, first;
+
+ if (!ios_isatty(STDERR_FILENO))
+ return (0);
+ (void)fprintf(stderr, "overwrite %s? ", fname);
+ fflush(stderr);
+ first = ch = getchar();
+ while (ch != '\n' && ch != EOF)
+ ch = getchar();
+ return (first == 'y');
+}
+
+void
+usage(int iscompress)
+{
+ if (iscompress)
+ (void)fprintf(stderr,
+ "usage: compress [-cfv] [-b bits] [file ...]\n");
+ else
+ (void)fprintf(stderr,
+ "usage: uncompress [-cfv] [-b bits] [file ...]\n");
+ exit(1);
+}
+
+void
+cwarnx(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vwarnx(fmt, ap);
+ va_end(ap);
+ eval = 1;
+}
+
+void
+cwarn(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vwarn(fmt, ap);
+ va_end(ap);
+ eval = 1;
+}
diff --git a/files/Sources/files/compress/doc/NOTES b/files/Sources/files/compress/doc/NOTES
new file mode 100644
index 00000000..4ced6896
--- /dev/null
+++ b/files/Sources/files/compress/doc/NOTES
@@ -0,0 +1,142 @@
+
+ $FreeBSD: src/usr.bin/compress/doc/NOTES,v 1.3 2011/10/16 14:30:28 eadler Exp $
+
+From: James A. Woods
+
+>From vn Fri Dec 2 18:05:27 1988
+Subject: Re: Looking for C source for RSA
+Newsgroups: sci.crypt
+
+# Illegitimi noncarborundum
+
+Patents are a tar pit.
+
+A good case can be made that most are just a license to sue, and nothing
+is illegal until a patent is upheld in court.
+
+For example, if you receive netnews by means other than 'nntp',
+these very words are being modulated by 'compress',
+a variation on the patented Lempel-Ziv-Welch algorithm.
+
+Original Ziv-Lempel is patent number 4,464,650, and the more powerful
+LZW method is #4,558,302. Yet despite any similarities between 'compress'
+and LZW (the public-domain 'compress' code was designed and given to the
+world before the ink on the Welch patent was dry), no attorneys from Sperry
+(the assignee) have asked you to unplug your Usenet connection.
+
+Why? I can't speak for them, but it is possible the claims are too broad,
+or, just as bad, not broad enough. ('compress' does things not mentioned
+in the Welch patent.) Maybe they realize that they can commercialize
+LZW better by selling hardware implementations rather than by licensing
+software. Again, the LZW software delineated in the patent is *not*
+the same as that of 'compress'.
+
+At any rate, court-tested software patents are a different animal;
+corporate patents in a portfolio are usually traded like baseball cards
+to shut out small fry rather than actually be defended before
+non-technical juries. Perhaps RSA will undergo this test successfully,
+although the grant to "exclude others from making, using, or selling"
+the invention would then only apply to the U.S. (witness the
+Genentech patent of the TPA molecule in the U.S. but struck down
+in Great Britain as too broad.)
+
+The concept is still exotic for those who learned in school the rule of thumb
+that one may patent "apparatus" but not an "idea".
+Apparently this all changed in Diamond v. Diehr (1981) when the U. S. Supreme
+Court reversed itself.
+
+Scholars should consult the excellent article in the Washington and Lee
+Law Review (fall 1984, vol. 41, no. 4) by Anthony and Colwell for a
+comprehensive survey of an area which will remain murky for some time.
+
+Until the dust clears, how you approach ideas which are patented depends
+on how paranoid you are of a legal onslaught. Arbitrary? Yes. But
+the patent bar the CCPA (Court of Customs and Patent Appeals)
+thanks you for any uncertainty as they, at least, stand to gain
+from any trouble.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+From: James A. Woods
+Subject: Re: Looking for C source for RSA (actually 'compress' patents)
+
+ In article <2042@eos.UUCP> you write:
+ >The concept is still exotic for those who learned in school the rule of thumb
+ >that one may patent "apparatus" but not an "idea".
+
+A rule of thumb that has never been completely valid, as any chemical
+engineer can tell you. (Chemical processes were among the earliest patents,
+as I recall.)
+
+ ah yes -- i date myself when relaying out-of-date advice from elderly
+ attorneys who don't even specialize in patents. one other interesting
+ class of patents include the output of optical lens design programs,
+ which yield formulae which can then fairly directly can be molded
+ into glass. although there are restrictions on patenting equations,
+ the "embedded systems" seem to fly past the legal gauntlets.
+
+ anyway, I'm still learning about intellectual property law after
+ several conversations from a Unisys (nee sperry) lawyer re 'compress'.
+
+ it's more complicated than this, but they're letting (oral
+ communication only) software versions of 'compress' slide
+ as far as licensing fees go. this includes 'arc', 'stuffit',
+ and other commercial wrappers for 'compress'. yet they are
+ signing up licensees for hardware chips. Hewlett-Packard
+ supposedly has an active vlsi project, and Unisys has
+ board-level LZW-based tape controllers. (to build LZW into
+ a disk controller would be strange, as you'd have to build
+ in a filesystem too!)
+
+ it's byzantine
+ that Unisys is in a tiff with HP regarding the patents,
+ after discovering some sort of "compress" button on some
+ HP terminal product. why? well, professor Abraham Lempel jumped
+ from being department chairman of computer science at technion in
+ Israel to sperry (where he got the first patent), but then to work
+ at Hewlett-Packard on sabbatical. the second Welch patent
+ is only weakly derivative of the first, so they want chip
+ licenses and HP relented. however, everyone agrees something
+ like the current Unix implementation is the way to go with
+ software, so HP (and UCB) long ago asked spencer Thomas and i to sign
+ off on copyright permission (although they didn't need to, it being pd).
+ Lempel, HP, and Unisys grumbles they can't make money off the
+ software since a good free implementation (not the best --
+ i have more ideas!) escaped via Usenet. (Lempel's own pascal
+ code was apparently horribly slow.)
+ i don't follow the IBM 'arc' legal bickering; my impression
+ is that the pc folks are making money off the archiver/wrapper
+ look/feel of the thing [if ms-dos can be said to have a look and feel].
+
+ now where is telebit with the compress firmware? in a limbo
+ netherworld, probably, with sperry still welcoming outfits
+ to sign patent licenses, a common tactic to bring other small fry
+ into the fold. the guy who crammed 12-bit compress into the modem
+ there left. also what is transpiring with 'compress' and sys 5 rel 4?
+ beats me, but if sperry got a hold of them on these issues,
+ at&t would likely re-implement another algorithm if they
+ thought 'compress' infringes. needful to say, i don't think
+ it does after the above mentioned legal conversation.
+ my own beliefs on whether algorithms should be patentable at all
+ change with the weather. if the courts finally nail down
+ patent protection for algorithms, academic publication in
+ textbooks will be somewhat at odds with the engineering world,
+ where the textbook codes will simply be a big tease to get
+ money into the patent holder coffers...
+
+ oh, if you implement LZW from the patent, you won't get
+ good rates because it doesn't mention adaptive table reset,
+ lack thereof being *the* serious deficiency of Thomas' first version.
+
+ now i know that patent law generally protects against independent
+ re-invention (like the 'xor' hash function pleasantly mentioned
+ in the patent [but not the paper]).
+ but the upshot is that if anyone ever wanted to sue us,
+ we're partially covered with
+ independently-developed twists, plus the fact that some of us work
+ in a bureaucratic morass (as contractor to a public agency in my case).
+
+ quite a mess, huh? I've wanted to tell someone this stuff
+ for a long time, for posterity if nothing else.
+
+james
+
diff --git a/files/Sources/files/compress/doc/README b/files/Sources/files/compress/doc/README
new file mode 100644
index 00000000..0828cdfb
--- /dev/null
+++ b/files/Sources/files/compress/doc/README
@@ -0,0 +1,284 @@
+
+ @(#)README 8.1 (Berkeley) 6/9/93
+ $FreeBSD: src/usr.bin/compress/doc/README,v 1.3 2002/12/30 21:18:11 schweikh Exp $
+
+Compress version 4.0 improvements over 3.0:
+ o compress() speedup (10-50%) by changing division hash to xor
+ o decompress() speedup (5-10%)
+ o Memory requirements reduced (3-30%)
+ o Stack requirements reduced to less than 4kb
+ o Removed 'Big+Fast' compress code (FBITS) because of compress speedup
+ o Portability mods for Z8000 and PC/XT (but not zeus 3.2)
+ o Default to 'quiet' mode
+ o Unification of 'force' flags
+ o Manual page overhaul
+ o Portability enhancement for M_XENIX
+ o Removed text on #else and #endif
+ o Added "-V" switch to print version and options
+ o Added #defines for SIGNED_COMPARE_SLOW
+ o Added Makefile and "usermem" program
+ o Removed all floating point computations
+ o New programs: [deleted]
+
+The "usermem" script attempts to determine the maximum process size. Some
+editing of the script may be necessary (see the comments). [It should work
+fine on 4.3 BSD.] If you can't get it to work at all, just create file
+"USERMEM" containing the maximum process size in decimal.
+
+The following preprocessor symbols control the compilation of "compress.c":
+
+ o USERMEM Maximum process memory on the system
+ o SACREDMEM Amount to reserve for other processes
+ o SIGNED_COMPARE_SLOW Unsigned compare instructions are faster
+ o NO_UCHAR Don't use "unsigned char" types
+ o BITS Overrules default set by USERMEM-SACREDMEM
+ o vax Generate inline assembler
+ o interdata Defines SIGNED_COMPARE_SLOW
+ o M_XENIX Makes arrays < 65536 bytes each
+ o pdp11 BITS=12, NO_UCHAR
+ o z8000 BITS=12
+ o pcxt BITS=12
+ o BSD4_2 Allow long filenames ( > 14 characters) &
+ Call setlinebuf(stderr)
+
+The difference "usermem-sacredmem" determines the maximum BITS that can be
+specified with the "-b" flag.
+
+memory: at least BITS
+------ -- ----- ----
+ 433,484 16
+ 229,600 15
+ 127,536 14
+ 73,464 13
+ 0 12
+
+The default is BITS=16.
+
+The maximum bits can be overruled by specifying "-DBITS=bits" at
+compilation time.
+
+WARNING: files compressed on a large machine with more bits than allowed by
+a version of compress on a smaller machine cannot be decompressed! Use the
+"-b12" flag to generate a file on a large machine that can be uncompressed
+on a 16-bit machine.
+
+The output of compress 4.0 is fully compatible with that of compress 3.0.
+In other words, the output of compress 4.0 may be fed into uncompress 3.0 or
+the output of compress 3.0 may be fed into uncompress 4.0.
+
+The output of compress 4.0 not compatible with that of
+compress 2.0. However, compress 4.0 still accepts the output of
+compress 2.0. To generate output that is compatible with compress
+2.0, use the undocumented "-C" flag.
+
+ -from mod.sources, submitted by vax135!petsd!joe (Joe Orost), 8/1/85
+--------------------------------
+
+Enclosed is compress version 3.0 with the following changes:
+
+1. "Block" compression is performed. After the BITS run out, the
+ compression ratio is checked every so often. If it is decreasing,
+ the table is cleared and a new set of substrings are generated.
+
+ This makes the output of compress 3.0 not compatible with that of
+ compress 2.0. However, compress 3.0 still accepts the output of
+ compress 2.0. To generate output that is compatible with compress
+ 2.0, use the undocumented "-C" flag.
+
+2. A quiet "-q" flag has been added for use by the news system.
+
+3. The character chaining has been deleted and the program now uses
+ hashing. This improves the speed of the program, especially
+ during decompression. Other speed improvements have been made,
+ such as using putc() instead of fwrite().
+
+4. A large table is used on large machines when a relatively small
+ number of bits is specified. This saves much time when compressing
+ for a 16-bit machine on a 32-bit virtual machine. Note that the
+ speed improvement only occurs when the input file is > 30000
+ characters, and the -b BITS is less than or equal to the cutoff
+ described below.
+
+Most of these changes were made by James A. Woods (ames!jaw). Thank you
+James!
+
+To compile compress:
+
+ cc -O -DUSERMEM=usermem -o compress compress.c
+
+Where "usermem" is the amount of physical user memory available (in bytes).
+If any physical memory is to be reserved for other processes, put in
+"-DSACREDMEM sacredmem", where "sacredmem" is the amount to be reserved.
+
+The difference "usermem-sacredmem" determines the maximum BITS that can be
+specified, and the cutoff bits where the large+fast table is used.
+
+memory: at least BITS cutoff
+------ -- ----- ---- ------
+ 4,718,592 16 13
+ 2,621,440 16 12
+ 1,572,864 16 11
+ 1,048,576 16 10
+ 631,808 16 --
+ 329,728 15 --
+ 178,176 14 --
+ 99,328 13 --
+ 0 12 --
+
+The default memory size is 750,000 which gives a maximum BITS=16 and no
+large+fast table.
+
+The maximum bits can be overruled by specifying "-DBITS=bits" at
+compilation time.
+
+If your machine doesn't support unsigned characters, define "NO_UCHAR"
+when compiling.
+
+If your machine has "int" as 16-bits, define "SHORT_INT" when compiling.
+
+After compilation, move "compress" to a standard executable location, such
+as /usr/local. Then:
+ cd /usr/local
+ ln compress uncompress
+ ln compress zcat
+
+On machines that have a fixed stack size (such as Perkin-Elmer), set the
+stack to at least 12kb. ("setstack compress 12" on Perkin-Elmer).
+
+Next, install the manual (compress.l).
+ cp compress.l /usr/man/manl
+ cd /usr/man/manl
+ ln compress.l uncompress.l
+ ln compress.l zcat.l
+
+ - or -
+
+ cp compress.l /usr/man/man1/compress.1
+ cd /usr/man/man1
+ ln compress.1 uncompress.1
+ ln compress.1 zcat.1
+
+ regards,
+ petsd!joe
+
+Here is a note from the net:
+
+>From hplabs!pesnta!amd!turtlevax!ken Sat Jan 5 03:35:20 1985
+Path: ames!hplabs!pesnta!amd!turtlevax!ken
+From: ken@turtlevax.UUCP (Ken Turkowski)
+Newsgroups: net.sources
+Subject: Re: Compress release 3.0 : sample Makefile
+Organization: CADLINC, Inc. @ Menlo Park, CA
+
+In the compress 3.0 source recently posted to mod.sources, there is a
+#define variable which can be set for optimum performance on a machine
+with a large amount of memory. A program (usermem) to calculate the
+usable amount of physical user memory is enclosed, as well as a sample
+4.2BSD Vax Makefile for compress.
+
+Here is the README file from the previous version of compress (2.0):
+
+>Enclosed is compress.c version 2.0 with the following bugs fixed:
+>
+>1. The packed files produced by compress are different on different
+> machines and dependent on the vax sysgen option.
+> The bug was in the different byte/bit ordering on the
+> various machines. This has been fixed.
+>
+> This version is NOT compatible with the original vax posting
+> unless the '-DCOMPATIBLE' option is specified to the C
+> compiler. The original posting has a bug which I fixed,
+> causing incompatible files. I recommend you NOT to use this
+> option unless you already have a lot of packed files from
+> the original posting by Thomas.
+>2. The exit status is not well defined (on some machines) causing the
+> scripts to fail.
+> The exit status is now 0,1 or 2 and is documented in
+> compress.l.
+>3. The function getopt() is not available in all C libraries.
+> The function getopt() is no longer referenced by the
+> program.
+>4. Error status is not being checked on the fwrite() and fflush() calls.
+> Fixed.
+>
+>The following enhancements have been made:
+>
+>1. Added facilities of "compact" into the compress program. "Pack",
+> "Unpack", and "Pcat" are no longer required (no longer supplied).
+>2. Installed work around for C compiler bug with "-O".
+>3. Added a magic number header (\037\235). Put the bits specified
+> in the file.
+>4. Added "-f" flag to force overwrite of output file.
+>5. Added "-c" flag and "zcat" program. 'ln compress zcat' after you
+> compile.
+>6. The 'uncompress' script has been deleted; simply
+> 'ln compress uncompress' after you compile and it will work.
+>7. Removed extra bit masking for machines that support unsigned
+> characters. If your machine doesn't support unsigned characters,
+> define "NO_UCHAR" when compiling.
+>
+>Compile "compress.c" with "-O -o compress" flags. Move "compress" to a
+>standard executable location, such as /usr/local. Then:
+> cd /usr/local
+> ln compress uncompress
+> ln compress zcat
+>
+>On machines that have a fixed stack size (such as Perkin-Elmer), set the
+>stack to at least 12kb. ("setstack compress 12" on Perkin-Elmer).
+>
+>Next, install the manual (compress.l).
+> cp compress.l /usr/man/manl - or -
+> cp compress.l /usr/man/man1/compress.1
+>
+>Here is the README that I sent with my first posting:
+>
+>>Enclosed is a modified version of compress.c, along with scripts to make it
+>>run identically to pack(1), unpack(1), and pcat(1). Here is what I
+>>(petsd!joe) and a colleague (petsd!peora!srd) did:
+>>
+>>1. Removed VAX dependencies.
+>>2. Changed the struct to separate arrays; saves mucho memory.
+>>3. Did comparisons in unsigned, where possible. (Faster on Perkin-Elmer.)
+>>4. Sorted the character next chain and changed the search to stop
+>>prematurely. This saves a lot on the execution time when compressing.
+>>
+>>This version is totally compatible with the original version. Even though
+>>lint(1) -p has no complaints about compress.c, it won't run on a 16-bit
+>>machine, due to the size of the arrays.
+>>
+>>Here is the README file from the original author:
+>>
+>>>Well, with all this discussion about file compression (for news batching
+>>>in particular) going around, I decided to implement the text compression
+>>>algorithm described in the June Computer magazine. The author claimed
+>>>blinding speed and good compression ratios. It's certainly faster than
+>>>compact (but, then, what wouldn't be), but it's also the same speed as
+>>>pack, and gets better compression than both of them. On 350K bytes of
+>>>Unix-wizards, compact took about 8 minutes of CPU, pack took about 80
+>>>seconds, and compress (herein) also took 80 seconds. But, compact and
+>>>pack got about 30% compression, whereas compress got over 50%. So, I
+>>>decided I had something, and that others might be interested, too.
+>>>
+>>>As is probably true of compact and pack (although I haven't checked),
+>>>the byte order within a word is probably relevant here, but as long as
+>>>you stay on a single machine type, you should be ok. (Can anybody
+>>>elucidate on this?) There are a couple of asm's in the code (extv and
+>>>insv instructions), so anyone porting it to another machine will have to
+>>>deal with this anyway (and could probably make it compatible with Vax
+>>>byte order at the same time). Anyway, I've linted the code (both with
+>>>and without -p), so it should run elsewhere. Note the longs in the
+>>>code, you can take these out if you reduce BITS to <= 15.
+>>>
+>>>Have fun, and as always, if you make good enhancements, or bug fixes,
+>>>I'd like to see them.
+>>>
+>>>=Spencer (thomas@utah-20, {harpo,hplabs,arizona}!utah-cs!thomas)
+>>
+>> regards,
+>> joe
+>>
+>>--
+>>Full-Name: Joseph M. Orost
+>>UUCP: ..!{decvax,ucbvax,ihnp4}!vax135!petsd!joe
+>>US Mail: MS 313; Perkin-Elmer; 106 Apple St; Tinton Falls, NJ 07724
+>>Phone: (201) 870-5844
diff --git a/files/Sources/files/compress/doc/revision.log b/files/Sources/files/compress/doc/revision.log
new file mode 100644
index 00000000..04c96e68
--- /dev/null
+++ b/files/Sources/files/compress/doc/revision.log
@@ -0,0 +1,118 @@
+/* $FreeBSD: src/usr.bin/compress/doc/revision.log,v 1.5 2011/03/31 14:35:33 emaste Exp $ */
+
+/*
+ * $Header: compress.c,v 4.0 85/07/30 12:50:00 joe Release $
+ *
+ * Revision 4.0 85/07/30 12:50:00 joe
+ * Removed ferror() calls in output routine on every output except first.
+ * Prepared for release to the world.
+ *
+ * Revision 3.6 85/07/04 01:22:21 joe
+ * Remove much wasted storage by overlaying hash table with the tables
+ * used by decompress: tab_suffix[1<putc] and
+ * added signal catcher [plus beef in writeerr()] to delete effluvia.
+ *
+ * Revision 2.0 84/08/28 22:00:00 petsd!joe
+ * Add check for foreground before prompting user. Insert maxbits into
+ * compressed file. Force file being uncompressed to end with ".Z".
+ * Added "-c" flag and "zcat". Prepared for release.
+ *
+ * Revision 1.10 84/08/24 18:28:00 turtlevax!ken
+ * Will only compress regular files (no directories), added a magic number
+ * header (plus an undocumented -n flag to handle old files without headers),
+ * added -f flag to force overwriting of possibly existing destination file,
+ * otherwise the user is prompted for a response. Will tack on a .Z to a
+ * filename if it doesn't have one when decompressing. Will only replace
+ * file if it was compressed.
+ *
+ * Revision 1.9 84/08/16 17:28:00 turtlevax!ken
+ * Removed scanargs(), getopt(), added .Z extension and unlimited number of
+ * filenames to compress. Flags may be clustered (-Ddvb12) or separated
+ * (-D -d -v -b 12), or combination thereof. Modes and other status is
+ * copied with copystat(). -O bug for 4.2 seems to have disappeared with
+ * 1.8.
+ *
+ * Revision 1.8 84/08/09 23:15:00 joe
+ * Made it compatible with vax version, installed jim's fixes/enhancements
+ *
+ * Revision 1.6 84/08/01 22:08:00 joe
+ * Sped up algorithm significantly by sorting the compress chain.
+ *
+ * Revision 1.5 84/07/13 13:11:00 srd
+ * Added C version of vax asm routines. Changed structure to arrays to
+ * save much memory. Do unsigned compares where possible (faster on
+ * Perkin-Elmer)
+ *
+ * Revision 1.4 84/07/05 03:11:11 thomas
+ * Clean up the code a little and lint it. (Lint complains about all
+ * the regs used in the asm, but I'm not going to "fix" this.)
+ *
+ * Revision 1.3 84/07/05 02:06:54 thomas
+ * Minor fixes.
+ *
+ * Revision 1.2 84/07/05 00:27:27 thomas
+ * Add variable bit length output.
+ *
+ */
+
+static char rcs_ident[] =
+ "$Header: compress.c,v 4.0 85/07/30 12:50:00 joe Release $";
diff --git a/files/Sources/files/compress/uncompress.1 b/files/Sources/files/compress/uncompress.1
new file mode 100644
index 00000000..208c3ce8
--- /dev/null
+++ b/files/Sources/files/compress/uncompress.1
@@ -0,0 +1 @@
+.so man1/compress.1
\ No newline at end of file
diff --git a/files/Sources/files/compress/zcat.sh b/files/Sources/files/compress/zcat.sh
new file mode 100644
index 00000000..6799f461
--- /dev/null
+++ b/files/Sources/files/compress/zcat.sh
@@ -0,0 +1,38 @@
+#!/bin/sh -
+# $NetBSD: zcat.sh,v 1.4 1995/03/26 19:54:37 glass Exp $
+#
+# Copyright (c) 1992, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# @(#)zcat.sh 8.1 (Berkeley) 6/6/93
+#
+
+uncompress -c $*
diff --git a/files/Sources/files/compress/zopen.3 b/files/Sources/files/compress/zopen.3
new file mode 100644
index 00000000..f6c7f344
--- /dev/null
+++ b/files/Sources/files/compress/zopen.3
@@ -0,0 +1,137 @@
+.\" Copyright (c) 1992, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)zopen.3 8.1 (Berkeley) 6/9/93
+.\" $FreeBSD: src/usr.bin/compress/zopen.3,v 1.9 2010/12/11 08:32:16 joel Exp $
+.\"
+.Dd June 9, 1993
+.Dt ZOPEN 3
+.Os
+.Sh NAME
+.Nm zopen
+.Nd compressed stream open function
+.Sh SYNOPSIS
+.Fd #include \&"zopen.h\&"
+.Ft FILE *
+.Fn zopen "const char *path" "const char *mode" "int bits"
+.Sh DESCRIPTION
+The
+.Fn zopen
+function
+opens the compressed file whose name is the string pointed to by
+.Fa path
+and associates a stream with it.
+.Pp
+The argument
+.Fa mode
+points to one of the following one-character strings:
+.Bl -tag -width indent
+.It Dq Li r
+Open compressed file for reading.
+The stream is positioned at the beginning of the file.
+.It Dq Li w
+Truncate file to zero length or create compressed file for writing.
+The stream is positioned at the beginning of the file.
+.El
+.Pp
+Any created files will have mode
+.Pf \\*q Dv S_IRUSR
+\&|
+.Dv S_IWUSR
+\&|
+.Dv S_IRGRP
+\&|
+.Dv S_IWGRP
+\&|
+.Dv S_IROTH
+\&|
+.Dv S_IWOTH Ns \\*q
+.Pq Li 0666 ,
+as modified by the process'
+umask value (see
+.Xr umask 2 ) .
+.Pp
+Files may only be read or written.
+Seek operations are not allowed.
+.Pp
+The
+.Fa bits
+argument, if non-zero, is set to the bits code limit.
+If zero, the default is 16.
+See
+.Xr compress 1
+for more information.
+.Sh RETURN VALUES
+Upon successful completion
+.Fn zopen
+returns a
+.Tn FILE
+pointer.
+Otherwise,
+.Dv NULL
+is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+.Bl -tag -width [EINVAL]
+.It Bq Er EINVAL
+The
+.Fa mode
+or
+.Fa bits
+arguments specified to
+.Fn zopen
+were invalid.
+.It Bq Er EFTYPE
+The compressed file starts with an invalid header, or the compressed
+file is compressed with more bits than can be handled.
+.El
+.Pp
+The
+.Fn zopen
+function may also fail and set
+.Va errno
+for any of the errors specified for the routines
+.Xr fopen 3
+or
+.Xr funopen 3 .
+.Sh SEE ALSO
+.Xr compress 1 ,
+.Xr fopen 3 ,
+.Xr funopen 3
+.Sh HISTORY
+The
+.Nm
+function
+first appeared in
+.Bx 4.4 .
+.Sh BUGS
+The
+.Fn zopen
+function
+may not be portable to systems other than
+.Bx .
diff --git a/files/Sources/files/compress/zopen.c b/files/Sources/files/compress/zopen.c
new file mode 100644
index 00000000..589ce525
--- /dev/null
+++ b/files/Sources/files/compress/zopen.c
@@ -0,0 +1,738 @@
+/*-
+ * Copyright (c) 1985, 1986, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Diomidis Spinellis and James A. Woods, derived from original
+ * work by Spencer Thomas and Joseph Orost.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)zopen.c 8.1 (Berkeley) 6/27/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include
+__FBSDID("$FreeBSD: src/usr.bin/compress/zopen.c,v 1.17 2011/09/28 08:47:17 bz Exp $");
+
+/*-
+ * fcompress.c - File compression ala IEEE Computer, June 1984.
+ *
+ * Compress authors:
+ * Spencer W. Thomas (decvax!utah-cs!thomas)
+ * Jim McKie (decvax!mcvax!jim)
+ * Steve Davies (decvax!vax135!petsd!peora!srd)
+ * Ken Turkowski (decvax!decwrl!turtlevax!ken)
+ * James A. Woods (decvax!ihnp4!ames!jaw)
+ * Joe Orost (decvax!vax135!petsd!joe)
+ *
+ * Cleaned up and converted to library returning I/O streams by
+ * Diomidis Spinellis .
+ *
+ * zopen(filename, mode, bits)
+ * Returns a FILE * that can be used for read or write. The modes
+ * supported are only "r" and "w". Seeking is not allowed. On
+ * reading the file is decompressed, on writing it is compressed.
+ * The output is compatible with compress(1) with 16 bit tables.
+ * Any file produced by compress(1) can be read.
+ */
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "zopen.h"
+
+#define BITS 16 /* Default bits. */
+#define HSIZE 69001 /* 95% occupancy */
+
+/* A code_int must be able to hold 2**BITS values of type int, and also -1. */
+typedef long code_int;
+typedef long count_int;
+
+typedef u_char char_type;
+static char_type magic_header[] =
+ {'\037', '\235'}; /* 1F 9D */
+
+#define BIT_MASK 0x1f /* Defines for third byte of header. */
+#define BLOCK_MASK 0x80
+
+/*
+ * Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is
+ * a fourth header byte (for expansion).
+ */
+#define INIT_BITS 9 /* Initial number of bits/code. */
+
+#define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
+
+struct s_zstate {
+ FILE *zs_fp; /* File stream for I/O */
+ char zs_mode; /* r or w */
+ enum {
+ S_START, S_MIDDLE, S_EOF
+ } zs_state; /* State of computation */
+ u_int zs_n_bits; /* Number of bits/code. */
+ u_int zs_maxbits; /* User settable max # bits/code. */
+ code_int zs_maxcode; /* Maximum code, given n_bits. */
+ code_int zs_maxmaxcode; /* Should NEVER generate this code. */
+ count_int zs_htab [HSIZE];
+ u_short zs_codetab [HSIZE];
+ code_int zs_hsize; /* For dynamic table sizing. */
+ code_int zs_free_ent; /* First unused entry. */
+ /*
+ * Block compression parameters -- after all codes are used up,
+ * and compression rate changes, start over.
+ */
+ int zs_block_compress;
+ int zs_clear_flg;
+ long zs_ratio;
+ count_int zs_checkpoint;
+ u_int zs_offset;
+ long zs_in_count; /* Length of input. */
+ long zs_bytes_out; /* Length of compressed output. */
+ long zs_out_count; /* # of codes output (for debugging). */
+ char_type zs_buf[BITS];
+ union {
+ struct {
+ long zs_fcode;
+ code_int zs_ent;
+ code_int zs_hsize_reg;
+ int zs_hshift;
+ } w; /* Write parameters */
+ struct {
+ char_type *zs_stackp;
+ int zs_finchar;
+ code_int zs_code, zs_oldcode, zs_incode;
+ int zs_roffset, zs_size;
+ char_type zs_gbuf[BITS];
+ } r; /* Read parameters */
+ } u;
+};
+
+/* Definitions to retain old variable names */
+#define fp zs->zs_fp
+#define zmode zs->zs_mode
+#define state zs->zs_state
+#define n_bits zs->zs_n_bits
+#define maxbits zs->zs_maxbits
+#define maxcode zs->zs_maxcode
+#define maxmaxcode zs->zs_maxmaxcode
+#define htab zs->zs_htab
+#define codetab zs->zs_codetab
+#define hsize zs->zs_hsize
+#define free_ent zs->zs_free_ent
+#define block_compress zs->zs_block_compress
+#define clear_flg zs->zs_clear_flg
+#define ratio zs->zs_ratio
+#define checkpoint zs->zs_checkpoint
+#define offset zs->zs_offset
+#define in_count zs->zs_in_count
+#define bytes_out zs->zs_bytes_out
+#define out_count zs->zs_out_count
+#define buf zs->zs_buf
+#define fcode zs->u.w.zs_fcode
+#define hsize_reg zs->u.w.zs_hsize_reg
+#define ent zs->u.w.zs_ent
+#define hshift zs->u.w.zs_hshift
+#define stackp zs->u.r.zs_stackp
+#define finchar zs->u.r.zs_finchar
+#define code zs->u.r.zs_code
+#define oldcode zs->u.r.zs_oldcode
+#define incode zs->u.r.zs_incode
+#define roffset zs->u.r.zs_roffset
+#define size zs->u.r.zs_size
+#define gbuf zs->u.r.zs_gbuf
+
+/*
+ * To save much memory, we overlay the table used by compress() with those
+ * used by decompress(). The tab_prefix table is the same size and type as
+ * the codetab. The tab_suffix table needs 2**BITS characters. We get this
+ * from the beginning of htab. The output stack uses the rest of htab, and
+ * contains characters. There is plenty of room for any possible stack
+ * (stack used to be 8000 characters).
+ */
+
+#define htabof(i) htab[i]
+#define codetabof(i) codetab[i]
+
+#define tab_prefixof(i) codetabof(i)
+#define tab_suffixof(i) ((char_type *)(htab))[i]
+#define de_stack ((char_type *)&tab_suffixof(1 << BITS))
+
+#define CHECK_GAP 10000 /* Ratio check interval. */
+
+/*
+ * the next two codes should not be changed lightly, as they must not
+ * lie within the contiguous general code space.
+ */
+#define FIRST 257 /* First free entry. */
+#define CLEAR 256 /* Table clear output code. */
+
+static int cl_block(struct s_zstate *);
+static void cl_hash(struct s_zstate *, count_int);
+static code_int getcode(struct s_zstate *);
+static int output(struct s_zstate *, code_int);
+static int zclose(void *);
+static int zread(void *, char *, int);
+static int zwrite(void *, const char *, int);
+
+/*-
+ * Algorithm from "A Technique for High Performance Data Compression",
+ * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19.
+ *
+ * Algorithm:
+ * Modified Lempel-Ziv method (LZW). Basically finds common
+ * substrings and replaces them with a variable size code. This is
+ * deterministic, and can be done on the fly. Thus, the decompression
+ * procedure needs no input table, but tracks the way the table was built.
+ */
+
+/*-
+ * compress write
+ *
+ * Algorithm: use open addressing double hashing (no chaining) on the
+ * prefix code / next character combination. We do a variant of Knuth's
+ * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
+ * secondary probe. Here, the modular division first probe is gives way
+ * to a faster exclusive-or manipulation. Also do block compression with
+ * an adaptive reset, whereby the code table is cleared when the compression
+ * ratio decreases, but after the table fills. The variable-length output
+ * codes are re-sized at this point, and a special CLEAR code is generated
+ * for the decompressor. Late addition: construct the table according to
+ * file size for noticeable speed improvement on small files. Please direct
+ * questions about this implementation to ames!jaw.
+ */
+static int
+zwrite(void *cookie, const char *wbp, int num)
+{
+ code_int i;
+ int c, disp;
+ struct s_zstate *zs;
+ const u_char *bp;
+ u_char tmp;
+ int count;
+
+ if (num == 0)
+ return (0);
+
+ zs = cookie;
+ count = num;
+ bp = (const u_char *)wbp;
+ if (state == S_MIDDLE)
+ goto middle;
+ state = S_MIDDLE;
+
+ maxmaxcode = 1L << maxbits;
+ if (fwrite(magic_header,
+ sizeof(char), sizeof(magic_header), fp) != sizeof(magic_header))
+ return (-1);
+ tmp = (u_char)((maxbits) | block_compress);
+ if (fwrite(&tmp, sizeof(char), sizeof(tmp), fp) != sizeof(tmp))
+ return (-1);
+
+ offset = 0;
+ bytes_out = 3; /* Includes 3-byte header mojo. */
+ out_count = 0;
+ clear_flg = 0;
+ ratio = 0;
+ in_count = 1;
+ checkpoint = CHECK_GAP;
+ maxcode = MAXCODE(n_bits = INIT_BITS);
+ free_ent = ((block_compress) ? FIRST : 256);
+
+ ent = *bp++;
+ --count;
+
+ hshift = 0;
+ for (fcode = (long)hsize; fcode < 65536L; fcode *= 2L)
+ hshift++;
+ hshift = 8 - hshift; /* Set hash code range bound. */
+
+ hsize_reg = hsize;
+ cl_hash(zs, (count_int)hsize_reg); /* Clear hash table. */
+
+middle: for (; count--;) {
+ c = *bp++;
+ in_count++;
+ fcode = (long)(((long)c << maxbits) + ent);
+ i = ((c << hshift) ^ ent); /* Xor hashing. */
+
+ if (htabof(i) == fcode) {
+ ent = codetabof(i);
+ continue;
+ } else if ((long)htabof(i) < 0) /* Empty slot. */
+ goto nomatch;
+ disp = hsize_reg - i; /* Secondary hash (after G. Knott). */
+ if (i == 0)
+ disp = 1;
+probe: if ((i -= disp) < 0)
+ i += hsize_reg;
+
+ if (htabof(i) == fcode) {
+ ent = codetabof(i);
+ continue;
+ }
+ if ((long)htabof(i) >= 0)
+ goto probe;
+nomatch: if (output(zs, (code_int) ent) == -1)
+ return (-1);
+ out_count++;
+ ent = c;
+ if (free_ent < maxmaxcode) {
+ codetabof(i) = free_ent++; /* code -> hashtable */
+ htabof(i) = fcode;
+ } else if ((count_int)in_count >=
+ checkpoint && block_compress) {
+ if (cl_block(zs) == -1)
+ return (-1);
+ }
+ }
+ return (num);
+}
+
+static int
+zclose(void *cookie)
+{
+ struct s_zstate *zs;
+ int rval;
+
+ zs = cookie;
+ if (zmode == 'w') { /* Put out the final code. */
+ if (output(zs, (code_int) ent) == -1) {
+ (void)fclose(fp);
+ free(zs);
+ return (-1);
+ }
+ out_count++;
+ if (output(zs, (code_int) - 1) == -1) {
+ (void)fclose(fp);
+ free(zs);
+ return (-1);
+ }
+ }
+ rval = fclose(fp) == EOF ? -1 : 0;
+ free(zs);
+ return (rval);
+}
+
+/*-
+ * Output the given code.
+ * Inputs:
+ * code: A n_bits-bit integer. If == -1, then EOF. This assumes
+ * that n_bits =< (long)wordsize - 1.
+ * Outputs:
+ * Outputs code to the file.
+ * Assumptions:
+ * Chars are 8 bits long.
+ * Algorithm:
+ * Maintain a BITS character long buffer (so that 8 codes will
+ * fit in it exactly). Use the VAX insv instruction to insert each
+ * code in turn. When the buffer fills up empty it and start over.
+ */
+
+static char_type lmask[9] =
+ {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
+static char_type rmask[9] =
+ {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
+
+static int
+output(struct s_zstate *zs, code_int ocode)
+{
+ int r_off;
+ u_int bits;
+ char_type *bp;
+
+ r_off = offset;
+ bits = n_bits;
+ bp = buf;
+ if (ocode >= 0) {
+ /* Get to the first byte. */
+ bp += (r_off >> 3);
+ r_off &= 7;
+ /*
+ * Since ocode is always >= 8 bits, only need to mask the first
+ * hunk on the left.
+ */
+ *bp = (*bp & rmask[r_off]) | ((ocode << r_off) & lmask[r_off]);
+ bp++;
+ bits -= (8 - r_off);
+ ocode >>= 8 - r_off;
+ /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
+ if (bits >= 8) {
+ *bp++ = ocode;
+ ocode >>= 8;
+ bits -= 8;
+ }
+ /* Last bits. */
+ if (bits)
+ *bp = ocode;
+ offset += n_bits;
+ if (offset == (n_bits << 3)) {
+ bp = buf;
+ bits = n_bits;
+ bytes_out += bits;
+ if (fwrite(bp, sizeof(char), bits, fp) != bits)
+ return (-1);
+// bp += bits;
+// bits = 0;
+ offset = 0;
+ }
+ /*
+ * If the next entry is going to be too big for the ocode size,
+ * then increase it, if possible.
+ */
+ if (free_ent > maxcode || (clear_flg > 0)) {
+ /*
+ * Write the whole buffer, because the input side won't
+ * discover the size increase until after it has read it.
+ */
+ if (offset > 0) {
+ if (fwrite(buf, 1, n_bits, fp) != n_bits)
+ return (-1);
+ bytes_out += n_bits;
+ }
+ offset = 0;
+
+ if (clear_flg) {
+ maxcode = MAXCODE(n_bits = INIT_BITS);
+ clear_flg = 0;
+ } else {
+ n_bits++;
+ if (n_bits == maxbits)
+ maxcode = maxmaxcode;
+ else
+ maxcode = MAXCODE(n_bits);
+ }
+ }
+ } else {
+ /* At EOF, write the rest of the buffer. */
+ if (offset > 0) {
+ offset = (offset + 7) / 8;
+ if (fwrite(buf, 1, offset, fp) != offset)
+ return (-1);
+ bytes_out += offset;
+ }
+ offset = 0;
+ }
+ return (0);
+}
+
+/*
+ * Decompress read. This routine adapts to the codes in the file building
+ * the "string" table on-the-fly; requiring no table to be stored in the
+ * compressed file. The tables used herein are shared with those of the
+ * compress() routine. See the definitions above.
+ */
+static int
+zread(void *cookie, char *rbp, int num)
+{
+ u_int count;
+ struct s_zstate *zs;
+ u_char *bp, header[3];
+
+ if (num == 0)
+ return (0);
+
+ zs = cookie;
+ count = num;
+ bp = (u_char *)rbp;
+ switch (state) {
+ case S_START:
+ state = S_MIDDLE;
+ break;
+ case S_MIDDLE:
+ goto middle;
+ case S_EOF:
+ goto eof;
+ }
+
+ /* Check the magic number */
+ if (fread(header,
+ sizeof(char), sizeof(header), fp) != sizeof(header) ||
+ memcmp(header, magic_header, sizeof(magic_header)) != 0) {
+ errno = EFTYPE;
+ return (-1);
+ }
+ maxbits = header[2]; /* Set -b from file. */
+ block_compress = maxbits & BLOCK_MASK;
+ maxbits &= BIT_MASK;
+ maxmaxcode = 1L << maxbits;
+ if (maxbits > BITS || maxbits < 12) {
+ errno = EFTYPE;
+ return (-1);
+ }
+ /* As above, initialize the first 256 entries in the table. */
+ maxcode = MAXCODE(n_bits = INIT_BITS);
+ for (code = 255; code >= 0; code--) {
+ tab_prefixof(code) = 0;
+ tab_suffixof(code) = (char_type) code;
+ }
+ free_ent = block_compress ? FIRST : 256;
+
+ finchar = oldcode = getcode(zs);
+ if (oldcode == -1) /* EOF already? */
+ return (0); /* Get out of here */
+
+ /* First code must be 8 bits = char. */
+ *bp++ = (u_char)finchar;
+ count--;
+ stackp = de_stack;
+
+ while ((code = getcode(zs)) > -1) {
+
+ if ((code == CLEAR) && block_compress) {
+ for (code = 255; code >= 0; code--)
+ tab_prefixof(code) = 0;
+ clear_flg = 1;
+ free_ent = FIRST;
+ oldcode = -1;
+ continue;
+ }
+ incode = code;
+
+ /* Special case for kWkWk string. */
+ if (code >= free_ent) {
+ if (code > free_ent || oldcode == -1) {
+ /* Bad stream. */
+ errno = EINVAL;
+ return (-1);
+ }
+ *stackp++ = finchar;
+ code = oldcode;
+ }
+ /*
+ * The above condition ensures that code < free_ent.
+ * The construction of tab_prefixof in turn guarantees that
+ * each iteration decreases code and therefore stack usage is
+ * bound by 1 << BITS - 256.
+ */
+
+ /* Generate output characters in reverse order. */
+ while (code >= 256) {
+ *stackp++ = tab_suffixof(code);
+ code = tab_prefixof(code);
+ }
+ *stackp++ = finchar = tab_suffixof(code);
+
+ /* And put them out in forward order. */
+middle: do {
+ if (count-- == 0)
+ return (num);
+ *bp++ = *--stackp;
+ } while (stackp > de_stack);
+
+ /* Generate the new entry. */
+ if ((code = free_ent) < maxmaxcode && oldcode != -1) {
+ tab_prefixof(code) = (u_short) oldcode;
+ tab_suffixof(code) = finchar;
+ free_ent = code + 1;
+ }
+
+ /* Remember previous code. */
+ oldcode = incode;
+ }
+ state = S_EOF;
+eof: return (num - count);
+}
+
+/*-
+ * Read one code from the standard input. If EOF, return -1.
+ * Inputs:
+ * stdin
+ * Outputs:
+ * code or -1 is returned.
+ */
+static code_int
+getcode(struct s_zstate *zs)
+{
+ code_int gcode;
+ int r_off, bits;
+ char_type *bp;
+
+ bp = gbuf;
+ if (clear_flg > 0 || roffset >= size || free_ent > maxcode) {
+ /*
+ * If the next entry will be too big for the current gcode
+ * size, then we must increase the size. This implies reading
+ * a new buffer full, too.
+ */
+ if (free_ent > maxcode) {
+ n_bits++;
+ if (n_bits == maxbits) /* Won't get any bigger now. */
+ maxcode = maxmaxcode;
+ else
+ maxcode = MAXCODE(n_bits);
+ }
+ if (clear_flg > 0) {
+ maxcode = MAXCODE(n_bits = INIT_BITS);
+ clear_flg = 0;
+ }
+ size = fread(gbuf, 1, n_bits, fp);
+ if (size <= 0) /* End of file. */
+ return (-1);
+ roffset = 0;
+ /* Round size down to integral number of codes. */
+ size = (size << 3) - (n_bits - 1);
+ }
+ r_off = roffset;
+ bits = n_bits;
+
+ /* Get to the first byte. */
+ bp += (r_off >> 3);
+ r_off &= 7;
+
+ /* Get first part (low order bits). */
+ gcode = (*bp++ >> r_off);
+ bits -= (8 - r_off);
+ r_off = 8 - r_off; /* Now, roffset into gcode word. */
+
+ /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
+ if (bits >= 8) {
+ gcode |= *bp++ << r_off;
+ r_off += 8;
+ bits -= 8;
+ }
+
+ /* High order bits. */
+ gcode |= (*bp & rmask[bits]) << r_off;
+ roffset += n_bits;
+
+ return (gcode);
+}
+
+static int
+cl_block(struct s_zstate *zs) /* Table clear for block compress. */
+{
+ long rat;
+
+ checkpoint = in_count + CHECK_GAP;
+
+ if (in_count > 0x007fffff) { /* Shift will overflow. */
+ rat = bytes_out >> 8;
+ if (rat == 0) /* Don't divide by zero. */
+ rat = 0x7fffffff;
+ else
+ rat = in_count / rat;
+ } else
+ rat = (in_count << 8) / bytes_out; /* 8 fractional bits. */
+ if (rat > ratio)
+ ratio = rat;
+ else {
+ ratio = 0;
+ cl_hash(zs, (count_int) hsize);
+ free_ent = FIRST;
+ clear_flg = 1;
+ if (output(zs, (code_int) CLEAR) == -1)
+ return (-1);
+ }
+ return (0);
+}
+
+static void
+cl_hash(struct s_zstate *zs, count_int cl_hsize) /* Reset code table. */
+{
+ count_int *htab_p;
+ long i, m1;
+
+ m1 = -1;
+ htab_p = htab + cl_hsize;
+ i = cl_hsize - 16;
+ do { /* Might use Sys V memset(3) here. */
+ *(htab_p - 16) = m1;
+ *(htab_p - 15) = m1;
+ *(htab_p - 14) = m1;
+ *(htab_p - 13) = m1;
+ *(htab_p - 12) = m1;
+ *(htab_p - 11) = m1;
+ *(htab_p - 10) = m1;
+ *(htab_p - 9) = m1;
+ *(htab_p - 8) = m1;
+ *(htab_p - 7) = m1;
+ *(htab_p - 6) = m1;
+ *(htab_p - 5) = m1;
+ *(htab_p - 4) = m1;
+ *(htab_p - 3) = m1;
+ *(htab_p - 2) = m1;
+ *(htab_p - 1) = m1;
+ htab_p -= 16;
+ } while ((i -= 16) >= 0);
+ for (i += 16; i > 0; i--)
+ *--htab_p = m1;
+}
+
+FILE *
+zopen(const char *fname, const char *mode, int bits)
+{
+ struct s_zstate *zs;
+
+ if ((mode[0] != 'r' && mode[0] != 'w') || mode[1] != '\0' ||
+ bits < 0 || bits > BITS) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ if ((zs = calloc(1, sizeof(struct s_zstate))) == NULL)
+ return (NULL);
+
+ maxbits = bits ? bits : BITS; /* User settable max # bits/code. */
+ maxmaxcode = 1L << maxbits; /* Should NEVER generate this code. */
+ hsize = HSIZE; /* For dynamic table sizing. */
+ free_ent = 0; /* First unused entry. */
+ block_compress = BLOCK_MASK;
+ clear_flg = 0;
+ ratio = 0;
+ checkpoint = CHECK_GAP;
+ in_count = 1; /* Length of input. */
+ out_count = 0; /* # of codes output (for debugging). */
+ state = S_START;
+ roffset = 0;
+ size = 0;
+
+ /*
+ * Layering compress on top of stdio in order to provide buffering,
+ * and ensure that reads and write work with the data specified.
+ */
+ if ((fp = fopen(fname, mode)) == NULL) {
+ free(zs);
+ return (NULL);
+ }
+ switch (*mode) {
+ case 'r':
+ zmode = 'r';
+ return (funopen(zs, zread, NULL, NULL, zclose));
+ case 'w':
+ zmode = 'w';
+ return (funopen(zs, NULL, zwrite, NULL, zclose));
+ }
+ /* NOTREACHED */
+ return (NULL);
+}
diff --git a/files/Sources/files/compress/zopen.h b/files/Sources/files/compress/zopen.h
new file mode 100644
index 00000000..8ad5691f
--- /dev/null
+++ b/files/Sources/files/compress/zopen.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 1996
+ * FreeBSD Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY FreeBSD Inc. AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL [your name] OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/usr.bin/compress/zopen.h,v 1.5 2002/03/22 01:19:31 imp Exp $
+ */
+
+#ifndef _ZOPEN_H_
+#define _ZOPEN_H_
+
+FILE *zopen(const char *, const char *, int);
+
+#endif /* _ZOPEN_H_ */
diff --git a/files/Sources/files/cp/cp.1 b/files/Sources/files/cp/cp.1
new file mode 100644
index 00000000..8c346c7d
--- /dev/null
+++ b/files/Sources/files/cp/cp.1
@@ -0,0 +1,311 @@
+.\"-
+.\" Copyright (c) 1989, 1990, 1993, 1994
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the Institute of Electrical and Electronics Engineers, Inc.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)cp.1 8.3 (Berkeley) 4/18/94
+.\" $FreeBSD: src/bin/cp/cp.1,v 1.33 2005/02/25 00:40:46 trhodes Exp $
+.\"
+.Dd February 23, 2005
+.Dt CP 1
+.Os
+.Sh NAME
+.Nm cp
+.Nd copy files
+.Sh SYNOPSIS
+.Nm cp
+.Oo
+.Fl R
+.Op Fl H | Fl L | Fl P
+.Oc
+.Op Fl fi | n
+.Op Fl apvX
+.Ar source_file target_file
+.Nm cp
+.Oo
+.Fl R
+.Op Fl H | Fl L | Fl P
+.Oc
+.Op Fl fi | n
+.Op Fl apvX
+.Ar source_file ... target_directory
+.Sh DESCRIPTION
+In the first synopsis form, the
+.Nm cp
+utility copies the contents of the
+.Ar source_file
+to the
+.Ar target_file .
+In the second synopsis form,
+the contents of each named
+.Ar source_file
+is copied to the destination
+.Ar target_directory .
+The names of the files themselves are not changed.
+If
+.Nm cp
+detects an attempt to copy a file to itself, the copy will fail.
+.Pp
+The following options are available:
+.Bl -tag -width flag
+.It Fl a
+Same as
+.Fl pPR
+options. Preserves structure and attributes of files
+but not directory structure.
+.It Fl f
+.\"For each existing destination pathname, remove it and
+If the destination file cannot be opened, remove it and
+create a new file, without prompting for confirmation
+regardless of its permissions.
+(The
+.Fl f
+option overrides any previous
+.Fl n
+option.)
+.Pp
+The target file is not unlinked before the copy.
+Thus, any existing access rights will be retained.
+.It Fl H
+If the
+.Fl R
+option is specified, symbolic links on the command line are followed.
+(Symbolic links encountered in the tree traversal are not followed.)
+.It Fl i
+Cause
+.Nm cp
+to write a prompt to the standard error output before copying a file
+that would overwrite an existing file.
+If the response from the standard input begins with the character
+.Sq Li y
+or
+.Sq Li Y ,
+the file copy is attempted.
+(The
+.Fl i
+option overrides any previous
+.Fl n
+option.)
+.It Fl L
+If the
+.Fl R
+option is specified, all symbolic links are followed.
+.It Fl n
+Do not overwrite an existing file.
+(The
+.Fl n
+option overrides any previous
+.Fl f
+or
+.Fl i
+options.)
+.It Fl P
+If the
+.Fl R
+option is specified, no symbolic links are followed.
+This is the default.
+.It Fl p
+Cause
+.Nm cp
+to preserve the following attributes of each source
+file in the copy: modification time, access time,
+file flags, file mode, user ID, and group ID, as allowed by permissions.
+Access Control Lists (ACLs) and Extended Attributes (EAs),
+including resource forks, will also be preserved.
+.Pp
+If the user ID and group ID cannot be preserved, no error message
+is displayed and the exit value is not altered.
+.Pp
+If the source file has its set-user-ID bit on and the user ID cannot
+be preserved, the set-user-ID bit is not preserved
+in the copy's permissions.
+If the source file has its set-group-ID bit on and the group ID cannot
+be preserved, the set-group-ID bit is not preserved
+in the copy's permissions.
+If the source file has both its set-user-ID and set-group-ID bits on,
+and either the user ID or group ID cannot be preserved, neither
+the set-user-ID nor set-group-ID bits are preserved in the copy's
+permissions.
+.It Fl R
+If
+.Ar source_file
+designates a directory,
+.Nm cp
+copies the directory and the entire subtree connected at that point.
+If the
+.Ar source_file
+ends in a
+.Pa / ,
+the contents of the directory are copied rather than the
+directory itself.
+This option also causes symbolic links to be copied, rather than
+indirected through, and for
+.Nm cp
+to create special files rather than copying them as normal files.
+Created directories have the same mode as the corresponding source
+directory, unmodified by the process' umask.
+.Pp
+In
+.Fl R
+mode,
+.Nm cp
+will continue copying even if errors are detected.
+.Pp
+Note that
+.Nm cp
+copies hard-linked files as separate files.
+If you need to preserve hard links, consider using
+.Xr tar 1 ,
+.Xr cpio 1 ,
+or
+.Xr pax 1
+instead.
+.It Fl v
+Cause
+.Nm cp
+to be verbose, showing files as they are copied.
+.It Fl X
+Do not copy Extended Attributes (EAs) or resource forks.
+.It Fl c
+copy files using clonefile(2)
+.El
+.Pp
+For each destination file that already exists, its contents are
+overwritten if permissions allow.
+Its mode, user ID, and group
+ID are unchanged unless the
+.Fl p
+option was specified.
+.Pp
+In the second synopsis form,
+.Ar target_directory
+must exist unless there is only one named
+.Ar source_file
+which is a directory and the
+.Fl R
+flag is specified.
+.Pp
+If the destination file does not exist, the mode of the source file is
+used as modified by the file mode creation mask
+.Pf ( Ic umask ,
+see
+.Xr csh 1 ) .
+If the source file has its set-user-ID bit on, that bit is removed
+unless both the source file and the destination file are owned by the
+same user.
+If the source file has its set-group-ID bit on, that bit is removed
+unless both the source file and the destination file are in the same
+group and the user is a member of that group.
+If both the set-user-ID and set-group-ID bits are set, all of the above
+conditions must be fulfilled or both bits are removed.
+.Pp
+Appropriate permissions are required for file creation or overwriting.
+.Pp
+Symbolic links are always followed unless the
+.Fl R
+flag is set, in which case symbolic links are not followed, by default.
+The
+.Fl H
+or
+.Fl L
+flags (in conjunction with the
+.Fl R
+flag) cause symbolic links to be followed as described above.
+The
+.Fl H ,
+.Fl L
+and
+.Fl P
+options are ignored unless the
+.Fl R
+option is specified.
+In addition, these options override each other and the
+command's actions are determined by the last one specified.
+.Pp
+If
+.Nm cp
+receives a
+.Dv SIGINFO
+(see the
+.Cm status
+argument for
+.Xr stty 1 )
+signal, the current input and output file and the percentage complete
+will be written to the standard output.
+.Sh EXIT STATUS
+.Ex -std
+.Sh COMPATIBILITY
+Historic versions of the
+.Nm cp
+utility had a
+.Fl r
+option.
+This implementation supports that option;
+however, its use is strongly discouraged,
+as it does not correctly copy special files, symbolic links, or fifo's.
+.Pp
+The
+.Fl v
+and
+.Fl n
+options are non-standard and their use in scripts is not recommended.
+.Sh LEGACY DESCRIPTION
+In legacy mode,
+.Fl f
+will override
+.Fl i .
+Also, under the
+.Fl f
+option, the target file is always unlinked before the copy.
+Thus, new access rights will always be set.
+.Pp
+In
+.Fl R
+mode, copying will terminate if an error is encountered.
+.Pp
+For more information about legacy mode, see
+.Xr compat 5 .
+.Sh SEE ALSO
+.Xr mv 1 ,
+.Xr rcp 1 ,
+.Xr umask 2 ,
+.Xr fts 3 ,
+.Xr compat 5 ,
+.Xr symlink 7
+.Sh STANDARDS
+The
+.Nm cp
+command is expected to be
+.St -p1003.2
+compatible.
+.Sh HISTORY
+A
+.Nm cp
+command appeared in
+.At v1 .
diff --git a/files/Sources/files/cp/cp.c b/files/Sources/files/cp/cp.c
new file mode 100644
index 00000000..3e9cce3f
--- /dev/null
+++ b/files/Sources/files/cp/cp.c
@@ -0,0 +1,587 @@
+/*-
+ * Copyright (c) 1988, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * David Hitz of Auspex Systems Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char const copyright[] =
+"@(#) Copyright (c) 1988, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)cp.c 8.2 (Berkeley) 4/1/94";
+#endif /* not lint */
+#endif
+#include
+__FBSDID("$FreeBSD: src/bin/cp/cp.c,v 1.52 2005/09/05 04:36:08 csjp Exp $");
+
+/*
+ * Cp copies source files to target files.
+ *
+ * The global PATH_T structure "to" always contains the path to the
+ * current target file. Since fts(3) does not change directories,
+ * this path can be either absolute or dot-relative.
+ *
+ * The basic algorithm is to initialize "to" and use fts(3) to traverse
+ * the file hierarchy rooted in the argument list. A trivial case is the
+ * case of 'cp file1 file2'. The more interesting case is the case of
+ * 'cp file1 file2 ... fileN dir' where the hierarchy is traversed and the
+ * path (relative to the root of the traversal) is appended to dir (stored
+ * in "to") to form the final target path.
+ */
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef __APPLE__
+#include
+// #include
+// #else /* !__APPLE__ */
+#define COMPAT_MODE(a,b) (1)
+#include "ios_error.h"
+#endif /* __APPLE__ */
+
+#include "extern.h"
+
+#define STRIP_TRAILING_SLASH(p) { \
+ while ((p).p_end > (p).p_path + 1 && (p).p_end[-1] == '/') \
+ *--(p).p_end = 0; \
+}
+
+static char emptystring[] = "";
+
+PATH_T to = { to.p_path, emptystring, "" };
+
+__thread int cp_fflag, cp_iflag, cp_nflag, cp_pflag, cp_vflag;
+#ifdef __APPLE__
+__thread int Xflag;
+#endif /* __APPLE__ */
+static int Rflag, rflag;
+__thread int cp_cflag = 0;
+volatile __thread sig_atomic_t info;
+
+enum op { FILE_TO_FILE, FILE_TO_DIR, DIR_TO_DNE };
+
+static int copy(char *[], enum op, int);
+static void siginfo(int __unused);
+
+int
+cp_main(int argc, char *argv[])
+{
+ struct stat to_stat, tmp_stat;
+ enum op type;
+ int Hflag, Lflag, Pflag, ch, fts_options, r, have_trailing_slash;
+ char *target;
+
+ Hflag = Lflag = Pflag = 0;
+ cp_fflag = cp_iflag = cp_nflag = cp_pflag = cp_vflag = 0;
+#ifdef __APPLE__
+ Xflag = 0;
+#endif /* __APPLE__ */
+ Rflag = rflag = cp_cflag = 0;
+ optind = 1; opterr = 1; optreset = 1;
+
+ while ((ch = getopt(argc, argv, "cHLPRXafinprv")) != -1)
+ switch (ch) {
+ case 'c':
+ cp_cflag = 1;
+ break;
+ case 'H':
+ Hflag = 1;
+ Lflag = Pflag = 0;
+ break;
+ case 'L':
+ Lflag = 1;
+ Hflag = Pflag = 0;
+ break;
+ case 'P':
+ Pflag = 1;
+ Hflag = Lflag = 0;
+ break;
+ case 'R':
+ Rflag = 1;
+ break;
+ case 'X':
+ Xflag = 1;
+ break;
+ case 'f':
+ cp_fflag = 1;
+ /* Determine if the STD is SUSv3 or Legacy */
+ if (COMPAT_MODE("bin/cp", "unix2003"))
+ cp_nflag = 0; /* reset cp_nflag, but not cp_iflag */
+ else
+ cp_iflag = cp_nflag = 0; /* reset both */
+ break;
+ case 'i':
+ cp_iflag = 1;
+ if (COMPAT_MODE("bin/cp", "unix2003"))
+ cp_nflag = 0; /* reset cp_nflag, but not cp_fflag */
+ else
+ cp_fflag = cp_nflag = 0;
+ break;
+ case 'n':
+ cp_nflag = 1;
+ cp_fflag = cp_iflag = 0;
+ break;
+ case 'p':
+ cp_pflag = 1;
+ break;
+ case 'r':
+ rflag = 1;
+ break;
+ case 'v':
+ cp_vflag = 1;
+ break;
+ case 'a':
+ cp_pflag = 1;
+ Pflag = 1;
+ Rflag = 1;
+ break;
+ default:
+ cp_usage();
+ break;
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 2)
+ cp_usage();
+
+ if (cp_cflag && Xflag) {
+ errx(1, "the -c and -X options may not be specified together");
+ }
+
+ fts_options = FTS_NOCHDIR | FTS_PHYSICAL;
+ if (rflag) {
+ if (Rflag) {
+ errx(1,
+ "cp: the -R and -r options may not be specified together.\n");
+ }
+ if (Hflag || Lflag || Pflag) {
+ errx(1,
+ "cp: the -H, -L, and -P options may not be specified with the -r option.\n");
+ }
+ fts_options &= ~FTS_PHYSICAL;
+ fts_options |= FTS_LOGICAL;
+ }
+ if (Rflag) {
+ if (Hflag)
+ fts_options |= FTS_COMFOLLOW;
+ if (Lflag) {
+ fts_options &= ~FTS_PHYSICAL;
+ fts_options |= FTS_LOGICAL;
+ }
+ } else {
+ fts_options &= ~FTS_PHYSICAL;
+ fts_options |= FTS_LOGICAL | FTS_COMFOLLOW;
+ }
+ (void)signal(SIGINFO, siginfo);
+
+ /* Save the target base in "to". */
+ target = argv[--argc];
+ if (strlcpy(to.p_path, target, sizeof(to.p_path)) >= sizeof(to.p_path)) {
+ errx(1, "%s: name too long", target);
+ }
+ to.p_end = to.p_path + strlen(to.p_path);
+ if (to.p_path == to.p_end) {
+ *to.p_end++ = '.';
+ *to.p_end = 0;
+ }
+ have_trailing_slash = (to.p_end[-1] == '/');
+ if (have_trailing_slash)
+ STRIP_TRAILING_SLASH(to);
+ to.target_end = to.p_end;
+
+ /* Set end of argument list for fts(3). */
+ argv[argc] = NULL;
+
+ /*
+ * Cp has two distinct cases:
+ *
+ * cp [-R] source target
+ * cp [-R] source1 ... sourceN directory
+ *
+ * In both cases, source can be either a file or a directory.
+ *
+ * In (1), the target becomes a copy of the source. That is, if the
+ * source is a file, the target will be a file, and likewise for
+ * directories.
+ *
+ * In (2), the real target is not directory, but "directory/source".
+ */
+ r = stat(to.p_path, &to_stat);
+ if (r == -1 && errno != ENOENT) {
+ err(1, "%s", to.p_path);
+ }
+ if (r == -1 || !S_ISDIR(to_stat.st_mode)) {
+ /*
+ * Case (1). Target is not a directory.
+ */
+ if (argc > 1) {
+ cp_usage();
+ exit(1);
+ }
+ /*
+ * Need to detect the case:
+ * cp -R dir foo
+ * Where dir is a directory and foo does not exist, where
+ * we want pathname concatenations turned on but not for
+ * the initial mkdir().
+ */
+ if (r == -1) {
+ if (rflag || (Rflag && (Lflag || Hflag)))
+ stat(*argv, &tmp_stat);
+ else
+ lstat(*argv, &tmp_stat);
+
+ if (S_ISDIR(tmp_stat.st_mode) && (Rflag || rflag))
+ type = DIR_TO_DNE;
+ else
+ type = FILE_TO_FILE;
+ } else
+ type = FILE_TO_FILE;
+
+ if (have_trailing_slash && type == FILE_TO_FILE) {
+ if (r == -1) {
+ errx(1, "directory %s does not exist",
+ to.p_path);
+ }
+ else {
+ errx(1, "%s is not a directory", to.p_path);
+ }
+ }
+ } else
+ /*
+ * Case (2). Target is a directory.
+ */
+ type = FILE_TO_DIR;
+
+ return (copy(argv, type, fts_options));
+}
+
+static int
+copy(char *argv[], enum op type, int fts_options)
+{
+ struct stat to_stat;
+ FTS *ftsp;
+ FTSENT *curr;
+ int base = 0, dne, badcp, rval;
+ size_t nlen;
+ char *p, *target_mid;
+ mode_t mask, mode;
+
+ /*
+ * Keep an inverted copy of the umask, for use in correcting
+ * permissions on created directories when not using -p.
+ */
+ mask = ~umask(0777);
+ umask(~mask);
+
+ if ((ftsp = fts_open(argv, fts_options, NULL)) == NULL) {
+ err(1, "fts_open");
+ }
+ for (badcp = rval = 0; (curr = fts_read(ftsp)) != NULL; badcp = 0) {
+ switch (curr->fts_info) {
+ case FTS_NS:
+ case FTS_DNR:
+ case FTS_ERR:
+ warnx("%s: %s",
+ curr->fts_path, strerror(curr->fts_errno));
+ rval = 1;
+ continue;
+ case FTS_DC: /* Warn, continue. */
+ warnx("%s: directory causes a cycle", curr->fts_path);
+ rval = 1;
+ continue;
+ default:
+ ;
+ }
+#ifdef __APPLE__
+
+#ifdef __clang__
+#pragma clang diagnostic push
+/* clang doesn't like fts_name[1], but we know better... */
+#pragma clang diagnostic ignored "-Warray-bounds"
+#endif
+ /* Skip ._ when using copyfile and exists */
+ if ((cp_pflag || !Xflag) && (curr->fts_level != FTS_ROOTLEVEL) &&
+ (curr->fts_namelen > 2) && /* ._\0 is not AppleDouble */
+ (curr->fts_name[0] == '.') && (curr->fts_name[1] == '_')) {
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+ struct stat statbuf;
+ char path[PATH_MAX];
+ char *p = strrchr(curr->fts_path, '/');
+ if (p) {
+ size_t s = p + 2 - curr->fts_path;
+ if (s > sizeof(path)) s = sizeof(path);
+ strlcpy(path, curr->fts_path, s);
+ strlcat(path, curr->fts_name+2, sizeof(path));
+ } else {
+ strlcpy(path, curr->fts_name+2, sizeof(path));
+ }
+ if (!lstat(path, &statbuf)) {
+ continue;
+ }
+ }
+#endif /* __APPLE__ */
+ /*
+ * If we are in case (2) or (3) above, we need to append the
+ * source name to the target name.
+ */
+ if (type != FILE_TO_FILE) {
+ /*
+ * Need to remember the roots of traversals to create
+ * correct pathnames. If there's a directory being
+ * copied to a non-existent directory, e.g.
+ * cp -R a/dir noexist
+ * the resulting path name should be noexist/foo, not
+ * noexist/dir/foo (where foo is a file in dir), which
+ * is the case where the target exists.
+ *
+ * Also, check for "..". This is for correct path
+ * concatenation for paths ending in "..", e.g.
+ * cp -R .. /tmp
+ * Paths ending in ".." are changed to ".". This is
+ * tricky, but seems the easiest way to fix the problem.
+ *
+ * XXX
+ * Since the first level MUST be FTS_ROOTLEVEL, base
+ * is always initialized.
+ */
+ if (curr->fts_level == FTS_ROOTLEVEL) {
+ if (type != DIR_TO_DNE) {
+ p = strrchr(curr->fts_path, '/');
+ base = (p == NULL) ? 0 :
+ (int)(p - curr->fts_path + 1);
+
+ if (!strcmp(&curr->fts_path[base],
+ ".."))
+ base += 1;
+ } else
+ base = curr->fts_pathlen;
+ }
+
+ p = &curr->fts_path[base];
+ nlen = curr->fts_pathlen - base;
+ target_mid = to.target_end;
+ if (*p != '/' && target_mid[-1] != '/')
+ *target_mid++ = '/';
+ *target_mid = 0;
+ if (target_mid - to.p_path + nlen >= PATH_MAX) {
+ warnx("%s%s: name too long (not copied)",
+ to.p_path, p);
+ rval = 1;
+ continue;
+ }
+ (void)strncat(target_mid, p, nlen);
+ to.p_end = target_mid + nlen;
+ *to.p_end = 0;
+ STRIP_TRAILING_SLASH(to);
+ }
+
+ if (curr->fts_info == FTS_DP) {
+ /*
+ * We are nearly finished with this directory. If we
+ * didn't actually copy it, or otherwise don't need to
+ * change its attributes, then we are done.
+ */
+ if (!curr->fts_number)
+ continue;
+ /*
+ * If -p is in effect, set all the attributes.
+ * Otherwise, set the correct permissions, limited
+ * by the umask. Optimise by avoiding a chmod()
+ * if possible (which is usually the case if we
+ * made the directory). Note that mkdir() does not
+ * honour setuid, setgid and sticky bits, but we
+ * normally want to preserve them on directories.
+ */
+ if (cp_pflag) {
+ if (setfile(curr->fts_statp, -1))
+ rval = 1;
+#ifdef __APPLE__
+ /* setfile will fail if writeattr is denied */
+ if (copyfile(curr->fts_path, to.p_path, NULL, COPYFILE_ACL)<0)
+ warn("%s: unable to copy ACL to %s", curr->fts_path, to.p_path);
+#else /* !__APPLE__ */
+ if (preserve_dir_acls(curr->fts_statp,
+ curr->fts_accpath, to.p_path) != 0)
+ rval = 1;
+#endif /* __APPLE__ */
+ } else {
+ mode = curr->fts_statp->st_mode;
+ if ((mode & (S_ISUID | S_ISGID | S_ISTXT)) ||
+ ((mode | S_IRWXU) & mask) != (mode & mask))
+ if (chmod(to.p_path, mode & mask) != 0){
+ warn("chmod: %s", to.p_path);
+ rval = 1;
+ }
+ }
+ continue;
+ }
+
+ /* Not an error but need to remember it happened */
+ if (stat(to.p_path, &to_stat) == -1)
+ dne = 1;
+ else {
+ if (to_stat.st_dev == curr->fts_statp->st_dev &&
+ to_stat.st_ino == curr->fts_statp->st_ino) {
+ warnx("%s and %s are identical (not copied).",
+ to.p_path, curr->fts_path);
+ rval = 1;
+ if (S_ISDIR(curr->fts_statp->st_mode))
+ (void)fts_set(ftsp, curr, FTS_SKIP);
+ continue;
+ }
+ if (!S_ISDIR(curr->fts_statp->st_mode) &&
+ S_ISDIR(to_stat.st_mode)) {
+ warnx("cannot overwrite directory %s with "
+ "non-directory %s\n",
+ to.p_path, curr->fts_path);
+ rval = 1;
+ continue;
+ }
+ dne = 0;
+ }
+
+ switch (curr->fts_statp->st_mode & S_IFMT) {
+ case S_IFLNK:
+ /* Catch special case of a non-dangling symlink */
+ if ((fts_options & FTS_LOGICAL) ||
+ ((fts_options & FTS_COMFOLLOW) &&
+ curr->fts_level == 0)) {
+ if (copy_file(curr, dne))
+ badcp = rval = 1;
+ } else {
+ if (copy_link(curr, !dne))
+ badcp = rval = 1;
+ }
+ break;
+ case S_IFDIR:
+ if (!Rflag && !rflag) {
+ warnx("%s is a directory (not copied).",
+ curr->fts_path);
+ (void)fts_set(ftsp, curr, FTS_SKIP);
+ badcp = rval = 1;
+ break;
+ }
+ /*
+ * If the directory doesn't exist, create the new
+ * one with the from file mode plus owner RWX bits,
+ * modified by the umask. Trade-off between being
+ * able to write the directory (if from directory is
+ * 555) and not causing a permissions race. If the
+ * umask blocks owner writes, we fail..
+ */
+ if (dne) {
+ if (mkdir(to.p_path,
+ curr->fts_statp->st_mode | S_IRWXU) < 0) {
+ if (COMPAT_MODE("bin/cp", "unix2003")) {
+ warn("%s", to.p_path);
+ } else {
+ err(1, "%s", to.p_path);
+ }
+ }
+ } else if (!S_ISDIR(to_stat.st_mode)) {
+ errno = ENOTDIR;
+ if (COMPAT_MODE("bin/cp", "unix2003")) {
+ warn("%s", to.p_path);
+ } else {
+ err(1, "%s", to.p_path);
+ }
+ }
+ /*
+ * Arrange to correct directory attributes later
+ * (in the post-order phase) if this is a new
+ * directory, or if the -p flag is in effect.
+ */
+ curr->fts_number = cp_pflag || dne;
+#ifdef __APPLE__
+ if (!Xflag) {
+ if (copyfile(curr->fts_path, to.p_path, NULL, COPYFILE_XATTR) < 0)
+ warn("%s: unable to copy extended attributes to %s", curr->fts_path, to.p_path);
+ /* ACL and mtime set in postorder traversal */
+ }
+#endif /* __APPLE__ */
+ break;
+ case S_IFBLK:
+ case S_IFCHR:
+ if (Rflag) {
+ if (copy_special(curr->fts_statp, !dne))
+ badcp = rval = 1;
+ } else {
+ if (copy_file(curr, dne))
+ badcp = rval = 1;
+ }
+ break;
+ case S_IFIFO:
+ if (Rflag) {
+ if (copy_fifo(curr->fts_statp, !dne))
+ badcp = rval = 1;
+ } else {
+ if (copy_file(curr, dne))
+ badcp = rval = 1;
+ }
+ break;
+ default:
+ if (copy_file(curr, dne))
+ badcp = rval = 1;
+ break;
+ }
+ if (cp_vflag && !badcp)
+ (void)fprintf(thread_stdout, "%s -> %s\n", curr->fts_path, to.p_path);
+ }
+ fts_close(ftsp);
+ if (errno) {
+ err(1, "fts_read");
+ }
+ return (rval);
+}
+
+static void
+siginfo(int sig __unused)
+{
+
+ info = 1;
+}
diff --git a/files/Sources/files/cp/extern.h b/files/Sources/files/cp/extern.h
new file mode 100644
index 00000000..4e399de0
--- /dev/null
+++ b/files/Sources/files/cp/extern.h
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)extern.h 8.2 (Berkeley) 4/1/94
+ * $FreeBSD: src/bin/cp/extern.h,v 1.20 2005/09/05 04:36:08 csjp Exp $
+ */
+
+typedef struct {
+ char *p_end; /* pointer to NULL at end of path */
+ char *target_end; /* pointer to end of target base */
+ char p_path[PATH_MAX]; /* pointer to the start of a path */
+} PATH_T;
+
+extern PATH_T to;
+extern __thread int cp_fflag, cp_iflag, cp_nflag, cp_pflag, cp_vflag;
+#ifdef __APPLE__
+extern __thread int Xflag;
+#endif /* __APPLE__ */
+extern __thread int cp_cflag;
+extern volatile __thread sig_atomic_t info;
+
+__BEGIN_DECLS
+int copy_fifo(struct stat *, int);
+int copy_file(const FTSENT *, int);
+int copy_link(const FTSENT *, int);
+int copy_special(struct stat *, int);
+int setfile(struct stat *, int);
+int preserve_dir_acls(struct stat *, char *, char *);
+int preserve_fd_acls(int, int);
+void cp_usage(void);
+__END_DECLS
diff --git a/files/Sources/files/cp/utils.c b/files/Sources/files/cp/utils.c
new file mode 100644
index 00000000..090724aa
--- /dev/null
+++ b/files/Sources/files/cp/utils.c
@@ -0,0 +1,534 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)utils.c 8.3 (Berkeley) 4/1/94";
+#endif
+#endif /* not lint */
+#include
+__FBSDID("$FreeBSD: src/bin/cp/utils.c,v 1.46 2005/09/05 04:36:08 csjp Exp $");
+
+#include
+#include
+#include
+#include
+#ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef __APPLE__
+#include
+#include
+#include
+#include
+// #include
+#include
+#include
+// #else
+#define COMPAT_MODE(a,b) (1)
+#endif /* __APPLE__ */
+
+#include "extern.h"
+#include "ios_error.h"
+#define cp_pct(x,y) (int)(100.0 * (double)(x) / (double)(y))
+
+int
+copy_file(const FTSENT *entp, int dne)
+{
+ static char buf[MAXBSIZE];
+ struct stat *fs;
+ int ch, checkch, from_fd, rval, to_fd;
+ ssize_t rcount;
+ ssize_t wcount;
+ size_t wresid;
+ off_t wtotal;
+ char *bufp;
+#ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
+ char *p;
+#endif
+ mode_t mode = 0;
+ struct stat to_stat;
+
+ if ((from_fd = open(entp->fts_path, O_RDONLY, 0)) == -1) {
+ warn("%s", entp->fts_path);
+ return (1);
+ }
+
+ fs = entp->fts_statp;
+
+ /*
+ * If the file exists and we're interactive, verify with the user.
+ * If the file DNE, set the mode to be the from file, minus setuid
+ * bits, modified by the umask; arguably wrong, but it makes copying
+ * executables work right and it's been that way forever. (The
+ * other choice is 666 or'ed with the execute bits on the from file
+ * modified by the umask.)
+ */
+ if (!dne) {
+#define YESNO "(y/n [n]) "
+ if (cp_nflag) {
+ if (cp_vflag)
+ fprintf(thread_stdout, "%s not overwritten\n", to.p_path);
+ (void)close(from_fd);
+ return (1);
+ } else if (cp_iflag) {
+ (void)fprintf(thread_stderr, "overwrite %s? %s",
+ to.p_path, YESNO);
+ fflush(thread_stderr);
+ checkch = ch = getchar();
+ while (ch != '\n' && ch != EOF)
+ ch = getchar();
+ if (checkch != 'y' && checkch != 'Y') {
+ (void)close(from_fd);
+ (void)fprintf(thread_stderr, "not overwritten\n");
+ fflush(thread_stderr);
+ return (1);
+ }
+ }
+
+ if (cp_cflag) {
+ (void)unlink(to.p_path);
+ int error = clonefile(entp->fts_path, to.p_path, 0);
+ if (error)
+ warn("%s: clonefile failed", to.p_path);
+ (void)close(from_fd);
+ return error == 0 ? 0 : 1;
+ }
+
+ if (COMPAT_MODE("bin/cp", "unix2003")) {
+ /* first try to overwrite existing destination file name */
+ to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0);
+ if (to_fd == -1) {
+ if (cp_fflag) {
+ /* Only if it fails remove file and create a new one */
+ (void)unlink(to.p_path);
+ to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
+ fs->st_mode & ~(S_ISUID | S_ISGID));
+ }
+ }
+ } else {
+ if (cp_fflag) {
+ /* remove existing destination file name,
+ * create a new file */
+ (void)unlink(to.p_path);
+ to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
+ fs->st_mode & ~(S_ISUID | S_ISGID));
+ } else
+ /* overwrite existing destination file name */
+ to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0);
+ }
+ } else {
+
+ if (cp_cflag) {
+ int error = clonefile(entp->fts_path, to.p_path, 0);
+ if (error)
+ warn("%s: clonefile failed", to.p_path);
+ (void)close(from_fd);
+ return error == 0 ? 0 : 1;
+ }
+
+ to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
+ fs->st_mode & ~(S_ISUID | S_ISGID));
+ }
+
+ if (to_fd == -1) {
+ warn("%s", to.p_path);
+ (void)close(from_fd);
+ return (1);
+ }
+
+ rval = 0;
+
+#ifdef __APPLE__
+ if (S_ISREG(fs->st_mode)) {
+ struct statfs sfs;
+
+ /*
+ * Pre-allocate blocks for the destination file if it
+ * resides on Xsan.
+ */
+ if (fstatfs(to_fd, &sfs) == 0 &&
+ strcmp(sfs.f_fstypename, "acfs") == 0) {
+ fstore_t fst;
+
+ fst.fst_flags = 0;
+ fst.fst_posmode = F_PEOFPOSMODE;
+ fst.fst_offset = 0;
+ fst.fst_length = fs->st_size;
+
+ (void) fcntl(to_fd, F_PREALLOCATE, &fst);
+ }
+ }
+#endif /* __APPLE__ */
+
+ if (fstat(to_fd, &to_stat) != -1) {
+ mode = to_stat.st_mode;
+ if ((mode & (S_IRWXG|S_IRWXO))
+ && fchmod(to_fd, mode & ~(S_IRWXG|S_IRWXO))) {
+ if (errno != EPERM) /* we have write access but do not own the file */
+ warn("%s: fchmod failed", to.p_path);
+ mode = 0;
+ }
+ } else {
+ warn("%s", to.p_path);
+ }
+ /*
+ * Mmap and write if less than 8M (the limit is so we don't totally
+ * trash memory on big files. This is really a minor hack, but it
+ * wins some CPU back.
+ */
+#ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
+ if (S_ISREG(fs->st_mode) && fs->st_size > 0 &&
+ fs->st_size <= 8 * 1048576) {
+ if ((p = mmap(NULL, (size_t)fs->st_size, PROT_READ,
+ MAP_SHARED, from_fd, (off_t)0)) == MAP_FAILED) {
+ warn("%s", entp->fts_path);
+ rval = 1;
+ } else {
+ wtotal = 0;
+ for (bufp = p, wresid = fs->st_size; ;
+ bufp += wcount, wresid -= (size_t)wcount) {
+ wcount = write(to_fd, bufp, wresid);
+ wtotal += wcount;
+ if (info) {
+ info = 0;
+ (void)fprintf(thread_stderr,
+ "%s -> %s %3d%%\n",
+ entp->fts_path, to.p_path,
+ cp_pct(wtotal, fs->st_size));
+
+ }
+ if (wcount >= (ssize_t)wresid || wcount <= 0)
+ break;
+ }
+ if (wcount != (ssize_t)wresid) {
+ warn("%s", to.p_path);
+ rval = 1;
+ }
+ /* Some systems don't unmap on close(2). */
+ if (munmap(p, fs->st_size) < 0) {
+ warn("%s", entp->fts_path);
+ rval = 1;
+ }
+ }
+ } else
+#endif
+ {
+ wtotal = 0;
+ while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) {
+ for (bufp = buf, wresid = rcount; ;
+ bufp += wcount, wresid -= wcount) {
+ wcount = write(to_fd, bufp, wresid);
+ wtotal += wcount;
+ if (info) {
+ info = 0;
+ (void)fprintf(thread_stderr,
+ "%s -> %s %3d%%\n",
+ entp->fts_path, to.p_path,
+ cp_pct(wtotal, fs->st_size));
+
+ }
+ if (wcount >= (ssize_t)wresid || wcount <= 0)
+ break;
+ }
+ if (wcount != (ssize_t)wresid) {
+ warn("%s", to.p_path);
+ rval = 1;
+ break;
+ }
+ }
+ if (rcount < 0) {
+ warn("%s", entp->fts_path);
+ rval = 1;
+ }
+ }
+
+ /*
+ * Don't remove the target even after an error. The target might
+ * not be a regular file, or its attributes might be important,
+ * or its contents might be irreplaceable. It would only be safe
+ * to remove it if we created it and its length is 0.
+ */
+ if (mode != 0)
+ if (fchmod(to_fd, mode))
+ warn("%s: fchmod failed", to.p_path);
+#ifdef __APPLE__
+ /* do these before setfile in case copyfile changes mtime */
+ if (!Xflag && S_ISREG(fs->st_mode)) { /* skip devices, etc */
+ if (fcopyfile(from_fd, to_fd, NULL, COPYFILE_XATTR) < 0)
+ warn("%s: could not copy extended attributes to %s", entp->fts_path, to.p_path);
+ }
+ if (cp_pflag && setfile(fs, to_fd))
+ rval = 1;
+ if (cp_pflag) {
+ /* If this ACL denies writeattr then setfile will fail... */
+ if (fcopyfile(from_fd, to_fd, NULL, COPYFILE_ACL) < 0)
+ warn("%s: could not copy ACL to %s", entp->fts_path, to.p_path);
+ }
+#else /* !__APPLE__ */
+ if (cp_pflag && setfile(fs, to_fd))
+ rval = 1;
+ if (cp_pflag && preserve_fd_acls(from_fd, to_fd) != 0)
+ rval = 1;
+#endif /* __APPLE__ */
+ (void)close(from_fd);
+ if (close(to_fd)) {
+ warn("%s", to.p_path);
+ rval = 1;
+ }
+ return (rval);
+}
+
+int
+copy_link(const FTSENT *p, int exists)
+{
+ ssize_t len;
+ char llink[PATH_MAX];
+
+ if ((len = readlink(p->fts_path, llink, sizeof(llink) - 1)) == -1) {
+ warn("readlink: %s", p->fts_path);
+ return (1);
+ }
+ llink[len] = '\0';
+ if (exists && unlink(to.p_path)) {
+ warn("unlink: %s", to.p_path);
+ return (1);
+ }
+ if (symlink(llink, to.p_path)) {
+ warn("symlink: %s", llink);
+ return (1);
+ }
+#ifdef __APPLE__
+ if (!Xflag)
+ if (copyfile(p->fts_path, to.p_path, NULL, COPYFILE_XATTR | COPYFILE_NOFOLLOW_SRC) <0)
+ warn("%s: could not copy extended attributes to %s",
+ p->fts_path, to.p_path, strerror(errno));
+#endif
+ return (cp_pflag ? setfile(p->fts_statp, -1) : 0);
+}
+
+int
+copy_fifo(struct stat *from_stat, int exists)
+{
+ if (exists && unlink(to.p_path)) {
+ warn("unlink: %s", to.p_path);
+ return (1);
+ }
+ if (mkfifo(to.p_path, from_stat->st_mode)) {
+ warn("mkfifo: %s", to.p_path);
+ return (1);
+ }
+ return (cp_pflag ? setfile(from_stat, -1) : 0);
+}
+
+int
+copy_special(struct stat *from_stat, int exists)
+{
+ if (exists && unlink(to.p_path)) {
+ warn("unlink: %s", to.p_path);
+ return (1);
+ }
+ if (mknod(to.p_path, from_stat->st_mode, from_stat->st_rdev)) {
+ warn("mknod: %s", to.p_path);
+ return (1);
+ }
+ return (cp_pflag ? setfile(from_stat, -1) : 0);
+}
+
+int
+setfile(struct stat *fs, int fd)
+{
+ static struct timeval tv[2];
+ struct stat ts;
+ int rval, gotstat, islink, fdval;
+
+ rval = 0;
+ fdval = fd != -1;
+ islink = !fdval && S_ISLNK(fs->st_mode);
+ fs->st_mode &= S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO;
+
+ TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec);
+ TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec);
+ if (fdval ? futimes(fd, tv) : (islink ? lutimes(to.p_path, tv) : utimes(to.p_path, tv))) {
+ warn("%sutimes: %s", fdval ? "f" : (islink ? "l" : ""), to.p_path);
+ rval = 1;
+ }
+ if (fdval ? fstat(fd, &ts) : (islink ? lstat(to.p_path, &ts) :
+ stat(to.p_path, &ts))) {
+ gotstat = 0;
+ } else {
+ gotstat = 1;
+ ts.st_mode &= S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO;
+ }
+ /*
+ * Changing the ownership probably won't succeed, unless we're root
+ * or POSIX_CHOWN_RESTRICTED is not set. Set uid/gid before setting
+ * the mode; current BSD behavior is to remove all setuid bits on
+ * chown. If chown fails, lose setuid/setgid bits.
+ */
+ if (!gotstat || fs->st_uid != ts.st_uid || fs->st_gid != ts.st_gid) {
+ if (fdval ? fchown(fd, fs->st_uid, fs->st_gid) : (islink ?
+ lchown(to.p_path, fs->st_uid, fs->st_gid) :
+ chown(to.p_path, fs->st_uid, fs->st_gid))) {
+ if (errno != EPERM) {
+ warn("%schown: %s", fdval ? "f" : (islink ? "l" : ""), to.p_path);
+ rval = 1;
+ }
+ fs->st_mode &= ~(S_ISUID | S_ISGID);
+ }
+ }
+
+ if (!gotstat || fs->st_mode != ts.st_mode) {
+ if (fdval ? fchmod(fd, fs->st_mode) : (islink ?
+ lchmod(to.p_path, fs->st_mode) :
+ chmod(to.p_path, fs->st_mode))) {
+ warn("%schmod: %s", fdval ? "f" : (islink ? "l" : ""), to.p_path);
+ rval = 1;
+ }
+ }
+
+ if (!gotstat || fs->st_flags != ts.st_flags) {
+ if (fdval ? fchflags(fd, fs->st_flags) : (islink ?
+ lchflags(to.p_path, fs->st_flags) :
+ chflags(to.p_path, fs->st_flags))) {
+ if (errno != EPERM) {
+ warn("%schflags: %s", fdval ? "f" : (islink ? "l" : ""), to.p_path);
+ rval = 1;
+ }
+ }
+ }
+ return (rval);
+}
+
+#ifndef __APPLE__
+int
+preserve_fd_acls(int source_fd, int dest_fd)
+{
+ struct acl *aclp;
+ acl_t acl;
+
+ if (fpathconf(source_fd, _PC_ACL_EXTENDED) != 1 ||
+ fpathconf(dest_fd, _PC_ACL_EXTENDED) != 1)
+ return (0);
+ acl = acl_get_fd(source_fd);
+ if (acl == NULL) {
+ warn("failed to get acl entries while setting %s", to.p_path);
+ return (1);
+ }
+ aclp = &acl->ats_acl;
+ if (aclp->acl_cnt == 3)
+ return (0);
+ if (acl_set_fd(dest_fd, acl) < 0) {
+ warn("failed to set acl entries for %s", to.p_path);
+ return (1);
+ }
+ return (0);
+}
+
+int
+preserve_dir_acls(struct stat *fs, char *source_dir, char *dest_dir)
+{
+ acl_t (*aclgetf)(const char *, acl_type_t);
+ int (*aclsetf)(const char *, acl_type_t, acl_t);
+ struct acl *aclp;
+ acl_t acl;
+
+ if (pathconf(source_dir, _PC_ACL_EXTENDED) != 1 ||
+ pathconf(dest_dir, _PC_ACL_EXTENDED) != 1)
+ return (0);
+ /*
+ * If the file is a link we will not follow it
+ */
+ if (S_ISLNK(fs->st_mode)) {
+ aclgetf = acl_get_link_np;
+ aclsetf = acl_set_link_np;
+ } else {
+ aclgetf = acl_get_file;
+ aclsetf = acl_set_file;
+ }
+ /*
+ * Even if there is no ACL_TYPE_DEFAULT entry here, a zero
+ * size ACL will be returned. So it is not safe to simply
+ * check the pointer to see if the default ACL is present.
+ */
+ acl = aclgetf(source_dir, ACL_TYPE_DEFAULT);
+ if (acl == NULL) {
+ warn("failed to get default acl entries on %s",
+ source_dir, strerror(errno));
+ return (1);
+ }
+ aclp = &acl->ats_acl;
+ if (aclp->acl_cnt != 0 && aclsetf(dest_dir,
+ ACL_TYPE_DEFAULT, acl) < 0) {
+ warn("failed to set default acl entries on %s",
+ dest_dir, strerror(errno));
+ return (1);
+ }
+ acl = aclgetf(source_dir, ACL_TYPE_ACCESS);
+ if (acl == NULL) {
+ warn("failed to get acl entries on %s", source_dir);
+ return (1);
+ }
+ aclp = &acl->ats_acl;
+ if (aclsetf(dest_dir, ACL_TYPE_ACCESS, acl) < 0) {
+ warn("failed to set acl entries on %s", dest_dir);
+ return (1);
+ }
+ return (0);
+}
+#endif /* !__APPLE__ */
+
+void
+cp_usage(void)
+{
+
+ if (COMPAT_MODE("bin/cp", "unix2003")) {
+ (void)fprintf(thread_stderr, "%s\n%s\n",
+"usage: cp [-R [-H | -L | -P]] [-fi | -n] [-apvXc] source_file target_file",
+" cp [-R [-H | -L | -P]] [-fi | -n] [-apvXc] source_file ... "
+"target_directory");
+ } else {
+ (void)fprintf(thread_stderr, "%s\n%s\n",
+"usage: cp [-R [-H | -L | -P]] [-f | -i | -n] [-apvXc] source_file target_file",
+" cp [-R [-H | -L | -P]] [-f | -i | -n] [-apvXc] source_file ... "
+"target_directory");
+ }
+ exit(EX_USAGE);
+}
diff --git a/files/Sources/files/df/df.1 b/files/Sources/files/df/df.1
new file mode 100644
index 00000000..4560ab95
--- /dev/null
+++ b/files/Sources/files/df/df.1
@@ -0,0 +1,217 @@
+.\" Copyright (c) 1989, 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)df.1 8.3 (Berkeley) 5/8/95
+.\" $FreeBSD: src/bin/df/df.1,v 1.18.2.7 2002/04/22 22:17:36 keramida Exp $
+.\"
+.Dd May 8, 1995
+.Dt DF 1
+.Os
+.Sh NAME
+.Nm df
+.Nd display free disk space
+.Sh SYNOPSIS
+.Nm df
+.Oo
+.Fl b | h | H | k |
+.Fl m | g | P
+.Oc
+.Op Fl ailn
+.Op Fl t
+.Op Fl T Ar type
+.Op Ar file | filesystem ...
+.Sh LEGACY SYNOPSIS
+.Nm df
+.Oo
+.Fl b | h | H | k |
+.Fl m | P
+.Oc
+.Op Fl ailn
+.Op Fl t Ar type
+.Op Fl T Ar type
+.Op Ar file | filesystem ...
+.Sh DESCRIPTION
+The
+.Nm df
+utility
+displays statistics about the amount of free disk space on the specified
+.Ar filesystem
+or on the filesystem of which
+.Ar file
+is a part.
+Values are displayed in 512-byte per block counts.
+If neither a file or a filesystem operand is specified,
+statistics for all mounted filesystems are displayed
+(subject to the
+.Fl t
+option below).
+.Pp
+The following options are available:
+.Bl -tag -width Ds
+.It Fl a
+Show all mount points, including those that were mounted with the MNT_IGNORE
+flag.
+.It Fl b
+Use (the default) 512-byte blocks.
+This is only useful as a way to override an
+.Ev BLOCKSIZE
+specification from the environment.
+.It Fl g
+Use 1073741824-byte (1-Gbyte) blocks rather than the default.
+Note that this overrides the
+.Ev BLOCKSIZE
+specification from the environment.
+.It Fl H
+"Human-readable" output. Use unit suffixes: Byte, Kilobyte, Megabyte,
+Gigabyte, Terabyte and Petabyte in order to reduce the number of
+digits to three or less using base 10 for sizes.
+.It Fl h
+"Human-readable" output. Use unit suffixes: Byte, Kilobyte, Megabyte,
+Gigabyte, Terabyte and Petabyte in order to reduce the number of
+digits to three or less using base 2 for sizes.
+.It Fl i
+Include statistics on the number of free inodes. This option is now the default to conform to
+.St -susv3
+Use
+.Fl P
+to suppress this output.
+.It Fl k
+Use 1024-byte (1-Kbyte) blocks, rather than the default.
+Note that this overrides the
+.Ev BLOCKSIZE
+specification from the environment.
+.It Fl l
+Only display information about locally-mounted filesystems.
+.It Fl m
+Use 1048576-byte (1-Mbyte) blocks rather than the default. Note that
+this overrides the
+.Ev BLOCKSIZE
+specification from the environment.
+.It Fl n
+Print out the previously obtained statistics from the filesystems.
+This option should be used if it is possible that one or more
+filesystems are in a state such that they will not be able to provide
+statistics without a long delay.
+When this option is specified,
+.Nm df
+will not request new statistics from the filesystems, but will respond
+with the possibly stale statistics that were previously obtained.
+.It Fl P
+Use (the default) 512-byte blocks.
+This is only useful as a way to override an
+.Ev BLOCKSIZE
+specification from the environment.
+.It Fl T
+Only print out statistics for filesystems of the specified types.
+More than one type may be specified in a comma separated list.
+The list of filesystem types can be prefixed with
+.Dq no
+to specify the filesystem types for which action should
+.Em not
+be taken.
+For example, the
+.Nm df
+command:
+.Bd -literal -offset indent
+df -T nonfs,mfs
+.Ed
+.Pp
+lists all filesystems except those of type
+.Tn NFS
+and
+.Tn MFS .
+The
+.Xr lsvfs 1
+command can be used to find out the types of filesystems
+that are available on the system.
+.It Fl t
+If used with no arguments,
+this option is a no-op
+(Mac OS X already prints the total allocated-space figures).
+If used with an argument, it acts like
+.Fl T ,
+but this usage is deprecated and should not be relied upon.
+.El
+.Sh ENVIRONMENT
+.Bl -tag -width BLOCKSIZE
+.It Ev BLOCKSIZE
+If the environment variable
+.Ev BLOCKSIZE
+is set, the block counts will be displayed in units of that size block.
+.El
+.Sh BUGS
+The
+.Fl n
+and
+.Fl t
+flags are ignored if a file or filesystem is specified.
+.Sh LEGACY DESCRIPTION
+The "capacity" percentage is normally rounded up to the next higher integer.
+In legacy mode, it is rounded down to the next lower integer.
+.Pp
+When the
+.Fl P
+option and the
+.Fl k
+option are used together,
+sizes are reported in 1024-blocks.
+In legacy mode, when the
+.Fl P
+option and
+.Fl k
+option are used together,
+the last option specified dictates the reported block size.
+.Pp
+The
+.Fl t
+option is normally a no-op
+(Mac OS X already prints the total allocated-space figures).
+In legacy mode, it is equivalent to
+.Fl T .
+.Pp
+For more information about legacy mode, see
+.Xr compat 5 .
+.Sh SEE ALSO
+.Xr lsvfs 1 ,
+.Xr quota 1 ,
+.Xr fstatfs 2 ,
+.Xr getfsstat 2 ,
+.Xr statfs 2 ,
+.Xr getmntinfo 3 ,
+.Xr compat 5 ,
+.Xr fstab 5 ,
+.Xr mount 8 ,
+.Xr quot 8
+.Sh HISTORY
+A
+.Nm df
+command appeared in
+.At v1 .
diff --git a/files/Sources/files/df/df.c b/files/Sources/files/df/df.c
new file mode 100644
index 00000000..649c1b73
--- /dev/null
+++ b/files/Sources/files/df/df.c
@@ -0,0 +1,650 @@
+/*
+ * Copyright (c) 1980, 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include
+#ifndef lint
+__used static const char copyright[] =
+"@(#) Copyright (c) 1980, 1990, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)df.c 8.9 (Berkeley) 5/8/95";
+#else
+__used static const char rcsid[] =
+ "$FreeBSD: src/bin/df/df.c,v 1.23.2.9 2002/07/01 00:14:24 iedowse Exp $";
+#endif
+#endif /* not lint */
+
+#ifdef __APPLE__
+#define MNT_IGNORE 0
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "libutil.h"
+#include "ios_error.h"
+
+#ifdef __APPLE__
+// #include "get_compat.h"
+// #else
+#define COMPAT_MODE(func, mode) 1
+#endif
+
+#define UNITS_SI 1
+#define UNITS_2 2
+
+#define KILO_SZ(n) (n)
+#define MEGA_SZ(n) ((n) * (n))
+#define GIGA_SZ(n) ((n) * (n) * (n))
+#define TERA_SZ(n) ((n) * (n) * (n) * (n))
+#define PETA_SZ(n) ((n) * (n) * (n) * (n) * (n))
+
+#define KILO_2_SZ (KILO_SZ(1024ULL))
+#define MEGA_2_SZ (MEGA_SZ(1024ULL))
+#define GIGA_2_SZ (GIGA_SZ(1024ULL))
+#define TERA_2_SZ (TERA_SZ(1024ULL))
+#define PETA_2_SZ (PETA_SZ(1024ULL))
+
+#define KILO_SI_SZ (KILO_SZ(1000ULL))
+#define MEGA_SI_SZ (MEGA_SZ(1000ULL))
+#define GIGA_SI_SZ (GIGA_SZ(1000ULL))
+#define TERA_SI_SZ (TERA_SZ(1000ULL))
+#define PETA_SI_SZ (PETA_SZ(1000ULL))
+
+/* Maximum widths of various fields. */
+struct maxwidths {
+ int mntfrom;
+ int total;
+ int used;
+ int avail;
+ int iused;
+ int ifree;
+};
+
+static unsigned long long vals_si [] = {1, KILO_SI_SZ, MEGA_SI_SZ, GIGA_SI_SZ, TERA_SI_SZ, PETA_SI_SZ};
+static unsigned long long vals_base2[] = {1, KILO_2_SZ, MEGA_2_SZ, GIGA_2_SZ, TERA_2_SZ, PETA_2_SZ};
+static unsigned long long *valp;
+
+typedef enum { NONE, KILO, MEGA, GIGA, TERA, PETA, UNIT_MAX } unit_t;
+
+static unit_t unitp [] = { NONE, KILO, MEGA, GIGA, TERA, PETA };
+
+static int bread(off_t, void *, int);
+int checkvfsname(const char *, char **);
+static char *getmntpt(char *);
+static int int64width(int64_t);
+static char *makenetvfslist(void);
+char **makevfslist(const char *);
+static void prthuman(struct statfs *, uint64_t);
+static void prthumanval(int64_t);
+static void prtstat(struct statfs *, struct maxwidths *);
+static long regetmntinfo(struct statfs **, long, char **);
+static unit_t unit_adjust(double *);
+static void update_maxwidths(struct maxwidths *, struct statfs *);
+static void usage(void);
+
+static int aflag = 0, hflag, iflag, nflag;
+static int headerlen, timesthrough;
+
+static __inline int imax(int a, int b)
+{
+ return (a > b ? a : b);
+}
+
+int
+df_main(int argc, char *argv[])
+{
+ struct stat stbuf;
+ struct statfs statfsbuf, *mntbuf;
+ struct maxwidths maxwidths;
+ char *mntpt, **vfslist;
+ long mntsize;
+ int ch, i, rv, tflag = 0, kludge_tflag = 0;
+ int kflag = 0;
+ // always init the flags:
+ aflag = hflag = iflag = nflag = 0;
+ headerlen = 0; timesthrough = 0;
+ optind = 1; opterr = 1; optreset = 1;
+
+ const char *options = "abgHhiklmnPt:T:";
+ if (COMPAT_MODE("bin/df", "unix2003")) {
+ /* Unix2003 requires -t be "include total capacity". which df
+ already does, but it conflicts with the old -t so we need to
+ *not* expect a string after -t (we provide -T in both cases
+ to cover the old use of -t) */
+ options = "abgHhiklmnPtT:";
+ // iflag = 1;
+ iflag = 0;
+ }
+
+ vfslist = NULL;
+ while ((ch = getopt(argc, argv, options)) != -1)
+ switch (ch) {
+ case 'a':
+ aflag = 1;
+ break;
+ case 'b':
+ /* FALLTHROUGH */
+ case 'P':
+ if (COMPAT_MODE("bin/df", "unix2003")) {
+ if (!kflag) {
+ /* -k overrides -P */
+ putenv("BLOCKSIZE=512");
+ }
+ iflag = 0;
+ } else {
+ putenv("BLOCKSIZE=512");
+ }
+ hflag = 0;
+ break;
+ case 'g':
+ putenv("BLOCKSIZE=1g");
+ hflag = 0;
+ break;
+ case 'H':
+ hflag = UNITS_SI;
+ valp = vals_si;
+ break;
+ case 'h':
+ hflag = UNITS_2;
+ valp = vals_base2;
+ break;
+ case 'i':
+ iflag = 1;
+ break;
+ case 'k':
+ if (COMPAT_MODE("bin/df", "unix2003")) {
+ putenv("BLOCKSIZE=1024");
+ } else {
+ putenv("BLOCKSIZE=1k");
+ }
+ kflag = 1;
+ hflag = 0;
+ break;
+ case 'l':
+ if (tflag) {
+ errx(1, "-l and -T are mutually exclusive.");
+ }
+ if (vfslist != NULL)
+ break;
+ vfslist = makevfslist(makenetvfslist());
+ break;
+ case 'm':
+ putenv("BLOCKSIZE=1m");
+ hflag = 0;
+ break;
+ case 'n':
+ nflag = 1;
+ break;
+ case 't':
+ /* Unix2003 uses -t for something we do by default */
+ if (COMPAT_MODE("bin/df", "unix2003")) {
+ kludge_tflag = 1;
+ break;
+ }
+ case 'T':
+ if (vfslist != NULL) {
+ if (tflag) {
+ errx(1, "only one -%c option may be specified", ch);
+ }
+ else {
+ errx(1, "-l and -%c are mutually exclusive.", ch);
+ }
+ }
+ tflag++;
+ vfslist = makevfslist(optarg);
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* If we are in unix2003 mode, have seen a -t but no -T and the first
+ non switch arg isn't a file, let's pretend they used -T on it.
+ This makes the Lexmark printer installer happy (PR-3918471) */
+ if (tflag == 0 && kludge_tflag && *argv && stat(*argv, &stbuf) < 0
+ && errno == ENOENT) {
+ vfslist = makevfslist(*argv++);
+ }
+
+ mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
+ bzero(&maxwidths, sizeof(maxwidths));
+ for (i = 0; i < mntsize; i++)
+ update_maxwidths(&maxwidths, &mntbuf[i]);
+
+ rv = 0;
+ if (!*argv) {
+ mntsize = regetmntinfo(&mntbuf, mntsize, vfslist);
+ bzero(&maxwidths, sizeof(maxwidths));
+ for (i = 0; i < mntsize; i++)
+ update_maxwidths(&maxwidths, &mntbuf[i]);
+ for (i = 0; i < mntsize; i++) {
+ if (aflag || (mntbuf[i].f_flags & MNT_IGNORE) == 0)
+ prtstat(&mntbuf[i], &maxwidths);
+ }
+ exit(rv);
+ }
+
+ for (; *argv; argv++) {
+ if (stat(*argv, &stbuf) < 0) {
+ if ((mntpt = getmntpt(*argv)) == 0) {
+ warn("%s", *argv);
+ rv = 1;
+ continue;
+ }
+ } else if (S_ISCHR(stbuf.st_mode) || S_ISBLK(stbuf.st_mode)) {
+ warnx("%s: Raw devices not supported", *argv);
+ rv = 1;
+ continue;
+ } else
+ mntpt = *argv;
+ /*
+ * Statfs does not take a `wait' flag, so we cannot
+ * implement nflag here.
+ */
+ if (statfs(mntpt, &statfsbuf) < 0) {
+ warn("%s", mntpt);
+ rv = 1;
+ continue;
+ }
+ /* Check to make sure the arguments we've been
+ * given are satisfied. Return an error if we
+ * have been asked to list a mount point that does
+ * not match the other args we've been given (-l, -t, etc.)
+ */
+ if (checkvfsname(statfsbuf.f_fstypename, vfslist)) {
+ rv++;
+ continue;
+ }
+
+ if (argc == 1) {
+ bzero(&maxwidths, sizeof(maxwidths));
+ update_maxwidths(&maxwidths, &statfsbuf);
+ }
+ prtstat(&statfsbuf, &maxwidths);
+ }
+ return (rv);
+}
+
+char *
+getmntpt(char *name)
+{
+ long mntsize, i;
+ struct statfs *mntbuf;
+
+ mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
+ for (i = 0; i < mntsize; i++) {
+ if (!strcmp(mntbuf[i].f_mntfromname, name))
+ return (mntbuf[i].f_mntonname);
+ }
+ return (0);
+}
+
+/*
+ * Make a pass over the filesystem info in ``mntbuf'' filtering out
+ * filesystem types not in vfslist and possibly re-stating to get
+ * current (not cached) info. Returns the new count of valid statfs bufs.
+ */
+long
+regetmntinfo(struct statfs **mntbufp, long mntsize, char **vfslist)
+{
+ int i, j;
+ struct statfs *mntbuf;
+
+ if (vfslist == NULL)
+ return (nflag ? mntsize : getmntinfo(mntbufp, MNT_WAIT));
+
+ mntbuf = *mntbufp;
+ for (j = 0, i = 0; i < mntsize; i++) {
+ if (checkvfsname(mntbuf[i].f_fstypename, vfslist))
+ continue;
+ if (!nflag)
+ (void)statfs(mntbuf[i].f_mntonname,&mntbuf[j]);
+ else if (i != j)
+ mntbuf[j] = mntbuf[i];
+ j++;
+ }
+ return (j);
+}
+
+/*
+ * Output in "human-readable" format. Uses 3 digits max and puts
+ * unit suffixes at the end. Makes output compact and easy to read,
+ * especially on huge disks.
+ *
+ */
+unit_t
+unit_adjust(double *val)
+{
+ double abval;
+ unit_t unit;
+ unsigned int unit_sz;
+
+ abval = fabs(*val);
+
+ unit_sz = abval ? ilogb(abval) / 10 : 0;
+
+ if (unit_sz >= UNIT_MAX) {
+ unit = NONE;
+ } else {
+ unit = unitp[unit_sz];
+ *val /= (double)valp[unit_sz];
+ }
+
+ return (unit);
+}
+
+void
+prthuman(struct statfs *sfsp, uint64_t used)
+{
+ int64_t value;
+
+ value = sfsp->f_blocks;
+ value *= sfsp->f_bsize;
+ prthumanval(value);
+ value = used;
+ value *= sfsp->f_bsize;
+ prthumanval(value);
+ value = sfsp->f_bavail;
+ value *= sfsp->f_bsize;
+ prthumanval(value);
+}
+
+void
+prthumanval(int64_t bytes)
+{
+ char buf[6];
+ int flags;
+
+ flags = HN_B | HN_NOSPACE | HN_DECIMAL;
+ if (hflag == UNITS_SI)
+ flags |= HN_DIVISOR_1000;
+
+ humanize_number(buf, sizeof(buf) - (bytes < 0 ? 0 : 1),
+ bytes, "", HN_AUTOSCALE, flags);
+
+ if (hflag == UNITS_SI)
+ (void)fprintf(thread_stdout, " %6s", buf);
+ else
+ (void)fprintf(thread_stdout, "%6si", buf);
+
+}
+
+/*
+ * Convert statfs returned filesystem size into BLOCKSIZE units.
+ * Attempts to avoid overflow for large filesystems.
+ */
+static intmax_t fsbtoblk(int64_t num, uint64_t fsbs, u_long bs, char *fs)
+{
+ if (num < 0) {
+ warnx("negative filesystem block count/size from fs %s", fs);
+ return 0;
+ } else if ((fsbs != 0) && (fsbs < bs)) {
+ return (num / (intmax_t) (bs / fsbs));
+ } else {
+ return (num * (intmax_t) (fsbs / bs));
+ }
+}
+
+/*
+ * Print out status about a filesystem.
+ */
+void
+prtstat(struct statfs *sfsp, struct maxwidths *mwp)
+{
+ static long blocksize;
+ // static int headerlen, timesthrough;
+ static const char *header;
+ uint64_t used, availblks, inodes;
+ char * avail_str;
+
+ if (++timesthrough == 1) {
+ mwp->mntfrom = imax(mwp->mntfrom, (int)strlen("Filesystem"));
+ if (hflag) {
+ header = " Size";
+ mwp->total = mwp->used = mwp->avail = (int)strlen(header);
+ } else {
+ header = getbsize(&headerlen, &blocksize);
+ mwp->total = imax(mwp->total, headerlen);
+ }
+ mwp->used = imax(mwp->used, (int)strlen("Used"));
+ if (COMPAT_MODE("bin/df", "unix2003") && !hflag) {
+ avail_str = "Available";
+ } else {
+ avail_str = "Avail";
+ }
+ mwp->avail = imax(mwp->avail, (int)strlen(avail_str));
+
+ (void)fprintf(thread_stdout, "%-*s %*s %*s %*s Capacity", mwp->mntfrom,
+ "Filesystem", mwp->total, header, mwp->used, "Used",
+ mwp->avail, avail_str);
+ if (iflag) {
+ mwp->iused = imax(mwp->iused, (int)strlen(" iused"));
+ mwp->ifree = imax(mwp->ifree, (int)strlen("ifree"));
+ (void)fprintf(thread_stdout, " %*s %*s %%iused", mwp->iused - 2,
+ "iused", mwp->ifree, "ifree");
+ }
+ (void)fprintf(thread_stdout, " Mounted on\n");
+ }
+
+ (void)fprintf(thread_stdout, "%-*s", mwp->mntfrom, sfsp->f_mntfromname);
+ if (sfsp->f_blocks > sfsp->f_bfree)
+ used = sfsp->f_blocks - sfsp->f_bfree;
+ else
+ used = 0;
+ availblks = sfsp->f_bavail + used;
+ if (hflag) {
+ prthuman(sfsp, used);
+ } else {
+ (void)fprintf(thread_stdout, " %*jd %*jd %*jd", mwp->total,
+ fsbtoblk(sfsp->f_blocks, sfsp->f_bsize, blocksize, sfsp->f_mntonname),
+ mwp->used, fsbtoblk(used, sfsp->f_bsize, blocksize, sfsp->f_mntonname),
+ mwp->avail, fsbtoblk(sfsp->f_bavail, sfsp->f_bsize, blocksize, sfsp->f_mntonname));
+ }
+ if (COMPAT_MODE("bin/df", "unix2003")) {
+ /* Standard says percentage must be rounded UP to next
+ integer value, not truncated */
+ double value;
+ if (availblks == 0)
+ value = 100.0;
+ else {
+ value = (double)used / (double)availblks * 100.0;
+ if ((value-(int)value) > 0.0) value = value + 1.0;
+ }
+ (void)fprintf(thread_stdout, " %5.0f%%", trunc(value));
+ } else {
+ (void)fprintf(thread_stdout, " %5.0f%%",
+ availblks == 0 ? 100.0 : (double)used / (double)availblks * 100.0);
+ }
+ if (iflag) {
+ inodes = sfsp->f_files;
+ used = inodes - sfsp->f_ffree;
+ (void)fprintf(thread_stdout, " %*llu %*llu %4.0f%% ", mwp->iused, used,
+ mwp->ifree, sfsp->f_ffree, inodes == 0 ? 100.0 :
+ (double)used / (double)inodes * 100.0);
+ } else
+ (void)fprintf(thread_stdout, " ");
+ (void)fprintf(thread_stdout, " %s\n", sfsp->f_mntonname);
+}
+
+/*
+ * Update the maximum field-width information in `mwp' based on
+ * the filesystem specified by `sfsp'.
+ */
+void
+update_maxwidths(struct maxwidths *mwp, struct statfs *sfsp)
+{
+ static long blocksize;
+ int dummy;
+
+ if (blocksize == 0)
+ getbsize(&dummy, &blocksize);
+
+ mwp->mntfrom = imax(mwp->mntfrom, (int)strlen(sfsp->f_mntfromname));
+ mwp->total = imax(mwp->total, int64width(fsbtoblk(sfsp->f_blocks,
+ sfsp->f_bsize, blocksize, sfsp->f_mntonname)));
+ if (sfsp->f_blocks >= sfsp->f_bfree)
+ mwp->used = imax(mwp->used, int64width(fsbtoblk(sfsp->f_blocks -
+ sfsp->f_bfree, sfsp->f_bsize, blocksize, sfsp->f_mntonname)));
+ mwp->avail = imax(mwp->avail, int64width(fsbtoblk(sfsp->f_bavail,
+ sfsp->f_bsize, blocksize, sfsp->f_mntonname)));
+ mwp->iused = imax(mwp->iused, int64width(sfsp->f_files - sfsp->f_ffree));
+ mwp->ifree = imax(mwp->ifree, int64width(sfsp->f_ffree));
+}
+
+/* Return the width in characters of the specified long. */
+int
+int64width(int64_t val)
+{
+ int len;
+
+ len = 0;
+ /* Negative or zero values require one extra digit. */
+ if (val <= 0) {
+ val = -val;
+ len++;
+ }
+ while (val > 0) {
+ len++;
+ val /= 10;
+ }
+
+ return (len);
+}
+
+void
+usage(void)
+{
+
+ char *t_flag = COMPAT_MODE("bin/df", "unix2003") ? "[-t]" : "[-t type]";
+ (void)fprintf(thread_stderr,
+ "usage: df [-b | -H | -h | -k | -m | -g | -P] [-ailn] [-T type] %s [filesystem ...]\n", t_flag);
+ exit(EX_USAGE);
+}
+
+char *
+makenetvfslist(void)
+{
+ char *str, *strptr, **listptr;
+#ifndef __APPLE__
+ int mib[3], maxvfsconf, cnt=0, i;
+ size_t miblen;
+ struct ovfsconf *ptr;
+#else
+ int mib[4], maxvfsconf, cnt=0, i;
+ size_t miblen;
+ struct vfsconf vfc;
+#endif
+
+ mib[0] = CTL_VFS; mib[1] = VFS_GENERIC; mib[2] = VFS_MAXTYPENUM;
+ miblen=sizeof(maxvfsconf);
+ if (sysctl(mib, 3,
+ &maxvfsconf, &miblen, NULL, 0)) {
+ warn("sysctl failed");
+ return (NULL);
+ }
+
+ if ((listptr = malloc(sizeof(char*) * maxvfsconf)) == NULL) {
+ warnx("malloc failed");
+ return (NULL);
+ }
+
+#ifndef __APPLE__
+ for (ptr = getvfsent(); ptr; ptr = getvfsent())
+ if (ptr->vfc_flags & VFCF_NETWORK) {
+ listptr[cnt++] = strdup(ptr->vfc_name);
+ if (listptr[cnt-1] == NULL) {
+ warnx("malloc failed");
+ return (NULL);
+ }
+ }
+#else
+ miblen = sizeof (struct vfsconf);
+ mib[2] = VFS_CONF;
+ for (i = 0; i < maxvfsconf; i++) {
+ mib[3] = i;
+ if (sysctl(mib, 4, &vfc, &miblen, NULL, 0) == 0) {
+ if (!(vfc.vfc_flags & MNT_LOCAL)) {
+ listptr[cnt++] = strdup(vfc.vfc_name);
+ if (listptr[cnt-1] == NULL) {
+ free(listptr);
+ warnx("malloc failed");
+ return (NULL);
+ }
+ }
+ }
+ }
+#endif
+
+ if (cnt == 0 ||
+ (str = malloc(sizeof(char) * (32 * cnt + cnt + 2))) == NULL) {
+ if (cnt > 0)
+ warnx("malloc failed");
+ free(listptr);
+ return (NULL);
+ }
+
+ *str = 'n'; *(str + 1) = 'o';
+ for (i = 0, strptr = str + 2; i < cnt; i++, strptr++) {
+ strncpy(strptr, listptr[i], 32);
+ strptr += strlen(listptr[i]);
+ *strptr = ',';
+ free(listptr[i]);
+ }
+ *(--strptr) = '\0';
+
+ free(listptr);
+ return (str);
+}
diff --git a/files/Sources/files/df/vfslist.c b/files/Sources/files/df/vfslist.c
new file mode 100644
index 00000000..e21eb32d
--- /dev/null
+++ b/files/Sources/files/df/vfslist.c
@@ -0,0 +1,106 @@
+/*-
+ * Copyright (c) 1995
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)vfslist.c 8.1 (Berkeley) 5/8/95";
+#endif
+__used static const char rcsid[] =
+ "$FreeBSD: src/sbin/mount/vfslist.c,v 1.4 1999/08/28 00:13:27 peter Exp $";
+#endif /* not lint */
+
+#include
+#include
+#include
+#include
+#include
+#include "ios_error.h"
+
+#ifndef __APPLE__
+#include "extern.h"
+#endif
+
+static int skipvfs;
+
+int checkvfsname(const char *, const char **);
+const char **makevfslist(const char *);
+
+int
+checkvfsname(vfsname, vfslist)
+ const char *vfsname;
+ const char **vfslist;
+{
+
+ if (vfslist == NULL)
+ return (0);
+ while (*vfslist != NULL) {
+ if (strcmp(vfsname, *vfslist) == 0)
+ return (skipvfs);
+ ++vfslist;
+ }
+ return (!skipvfs);
+}
+
+const char **
+makevfslist(fslist)
+ const char *fslist;
+{
+ const char **av;
+ int i;
+ const char *cnextcp;
+ char *nextcp;
+
+ if (fslist == NULL)
+ return (NULL);
+ if (fslist[0] == 'n' && fslist[1] == 'o') {
+ fslist += 2;
+ skipvfs = 1;
+ }
+ for (i = 0, cnextcp = fslist; *cnextcp; cnextcp++)
+ if (*cnextcp == ',')
+ i++;
+ if ((av = malloc((size_t)(i + 2) * sizeof(char *))) == NULL) {
+ warnx("malloc failed");
+ return (NULL);
+ }
+ nextcp = strdup(fslist);
+ i = 0;
+ av[i++] = nextcp;
+ while ((nextcp = strchr(nextcp, ',')) != NULL) {
+ *nextcp++ = '\0';
+ av[i++] = nextcp;
+ }
+ av[i++] = NULL;
+ return (av);
+}
diff --git a/files/Sources/files/du/du.1 b/files/Sources/files/du/du.1
new file mode 100644
index 00000000..1bc6b2b6
--- /dev/null
+++ b/files/Sources/files/du/du.1
@@ -0,0 +1,172 @@
+.\" Copyright (c) 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)du.1 8.2 (Berkeley) 4/1/94
+.\" $FreeBSD: src/usr.bin/du/du.1,v 1.30 2005/05/21 09:55:05 ru Exp $
+.\"
+.Dd June 2, 2004
+.Dt DU 1
+.Os
+.Sh NAME
+.Nm du
+.Nd display disk usage statistics
+.Sh SYNOPSIS
+.Nm du
+.Op Fl H | L | P
+.Op Fl a | s | d Ar depth
+.Op Fl c
+.Op Fl h | k | m | g
+.Op Fl x
+.Op Fl I Ar mask
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm du
+utility displays the file system block usage for each file argument
+and for each directory in the file hierarchy rooted in each directory
+argument.
+If no file is specified, the block usage of the hierarchy rooted in
+the current directory is displayed.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl a
+Display an entry for each file in a file hierarchy.
+.It Fl c
+Display a grand total.
+.It Fl d Ar depth
+Display an entry for all files and directories
+.Ar depth
+directories deep.
+.It Fl H
+Symbolic links on the command line are followed, symbolic links in file
+hierarchies are not followed.
+.It Fl h
+"Human-readable" output.
+Use unit suffixes: Byte, Kilobyte, Megabyte,
+Gigabyte, Terabyte and Petabyte.
+.It Fl I Ar mask
+Ignore files and directories matching the specified
+.Ar mask .
+.It Fl g
+Display block counts in 1073741824-byte (1-Gbyte) blocks.
+.It Fl k
+Display block counts in 1024-byte (1-Kbyte) blocks.
+.It Fl L
+Symbolic links on the command line and in file hierarchies are followed.
+.It Fl m
+Display block counts in 1048576-byte (1-Mbyte) blocks.
+.It Fl P
+No symbolic links are followed.
+This is the default.
+.It Fl r
+Generate messages about directories that cannot be read, files
+that cannot be opened, and so on.
+This is the default case.
+This option exists solely for conformance with
+.St -xpg4 .
+.It Fl s
+Display an entry for each specified file.
+(Equivalent to
+.Fl d Li 0 )
+.It Fl x
+File system mount points are not traversed.
+.El
+.Pp
+The
+.Nm du
+utility counts the storage used by symbolic links and not the files they
+reference unless the
+.Fl H
+or
+.Fl L
+option is specified.
+If either the
+.Fl H
+or
+.Fl L
+options are specified, storage used by any symbolic links which are
+followed is not counted or displayed.
+If more than one of the
+.Fl H ,
+.Fl L ,
+and
+.Fl P
+options is specified, the last one given is used.
+.Pp
+Files having multiple hard links are counted (and displayed) a single
+time per
+.Nm du
+execution.
+Directories having multiple hard links (typically Time Machine backups) are
+counted a single time per
+.Nm du
+execution.
+.Sh ENVIRONMENT
+.Bl -tag -width BLOCKSIZE
+.It Ev BLOCKSIZE
+If the environment variable
+.Ev BLOCKSIZE
+is set, and the
+.Fl k
+option is not specified, the block counts will be displayed in units of that
+size block.
+If
+.Ev BLOCKSIZE
+is not set, and the
+.Fl k
+option is not specified, the block counts will be displayed in 512-byte blocks.
+.El
+.Sh LEGACY DESCRIPTION
+In legacy mode, only one of the
+.Fl H ,
+.Fl L ,
+or
+.Fl P
+options may be specified.
+.Pp
+The command will detect and report a SYMLOOP error
+(loop involving symbolic links).
+In legacy mode, this is not the case.
+.Pp
+For more information about legacy mode, see
+.Xr compat 5 .
+.Sh SEE ALSO
+.Xr df 1 ,
+.Xr fts 3 ,
+.Xr compat 5 ,
+.Xr symlink 7 ,
+.Xr quot 8
+.Sh HISTORY
+A
+.Nm du
+command appeared in
+.At v1 .
diff --git a/files/Sources/files/du/du.c b/files/Sources/files/du/du.c
new file mode 100644
index 00000000..8ecdd7a7
--- /dev/null
+++ b/files/Sources/files/du/du.c
@@ -0,0 +1,751 @@
+/*
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Newcomb.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include
+#ifndef lint
+__used static const char copyright[] =
+"@(#) Copyright (c) 1989, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static const char sccsid[] = "@(#)du.c 8.5 (Berkeley) 5/4/95";
+#endif
+#endif /* not lint */
+#include
+__FBSDID("$FreeBSD: src/usr.bin/du/du.c,v 1.38 2005/04/09 14:31:40 stefanf Exp $");
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "ios_error.h"
+
+#ifdef __APPLE__
+// #include
+// #else
+#define COMPAT_MODE(func, mode) (1)
+#endif
+
+#define KILO_SZ(n) (n)
+#define MEGA_SZ(n) ((n) * (n))
+#define GIGA_SZ(n) ((n) * (n) * (n))
+#define TERA_SZ(n) ((n) * (n) * (n) * (n))
+#define PETA_SZ(n) ((n) * (n) * (n) * (n) * (n))
+
+#define KILO_2_SZ (KILO_SZ(1024ULL))
+#define MEGA_2_SZ (MEGA_SZ(1024ULL))
+#define GIGA_2_SZ (GIGA_SZ(1024ULL))
+#define TERA_2_SZ (TERA_SZ(1024ULL))
+#define PETA_2_SZ (PETA_SZ(1024ULL))
+
+#define KILO_SI_SZ (KILO_SZ(1000ULL))
+#define MEGA_SI_SZ (MEGA_SZ(1000ULL))
+#define GIGA_SI_SZ (GIGA_SZ(1000ULL))
+#define TERA_SI_SZ (TERA_SZ(1000ULL))
+#define PETA_SI_SZ (PETA_SZ(1000ULL))
+
+#define TWO_TB (2LL * 1024LL * 1024LL * 1024LL * 1024LL)
+
+static unsigned long long vals_si [] = {1, KILO_SI_SZ, MEGA_SI_SZ, GIGA_SI_SZ, TERA_SI_SZ, PETA_SI_SZ};
+static unsigned long long vals_base2[] = {1, KILO_2_SZ, MEGA_2_SZ, GIGA_2_SZ, TERA_2_SZ, PETA_2_SZ};
+static unsigned long long *valp;
+
+typedef enum { NONE, KILO, MEGA, GIGA, TERA, PETA, UNIT_MAX } unit_t;
+
+static int unitp [] = { NONE, KILO, MEGA, GIGA, TERA, PETA };
+
+SLIST_HEAD(ignhead, ignentry) ignores;
+struct ignentry {
+ char *mask;
+ SLIST_ENTRY(ignentry) next;
+};
+
+static int linkchk(FTSENT *);
+static int dirlinkchk(FTSENT *);
+static void usage(void);
+static void prthumanval(double);
+static unit_t unit_adjust(double *);
+static void ignoreadd(const char *);
+static void ignoreclean(void);
+static int ignorep(FTSENT *);
+
+int
+du_main(int argc, char *argv[])
+{
+ FTS *fts;
+ FTSENT *p;
+ off_t savednumber = 0;
+ long blocksize;
+ int ftsoptions;
+ int listall;
+ int depth;
+ int Hflag, Lflag, Pflag, aflag, sflag, dflag, cflag, hflag, ch, notused, rval;
+ char **save;
+ static char dot[] = ".";
+ off_t *ftsnum, *ftsparnum;
+
+ setlocale(LC_ALL, "");
+
+ Hflag = Lflag = Pflag = aflag = sflag = dflag = cflag = hflag = 0;
+ optind = 1; opterr = 1; optreset = 1;
+
+ save = argv;
+ ftsoptions = FTS_NOCHDIR;
+ depth = INT_MAX;
+ SLIST_INIT(&ignores);
+
+ while ((ch = getopt(argc, argv, "HI:LPasd:cghkmrx")) != -1)
+ switch (ch) {
+ case 'H':
+ Lflag = Pflag = 0;
+ Hflag = 1;
+ break;
+ case 'I':
+ ignoreadd(optarg);
+ break;
+ case 'L':
+ Hflag = Pflag = 0;
+ Lflag = 1;
+ break;
+ case 'P':
+ Hflag = Lflag = 0;
+ Pflag = 1;
+ break;
+ case 'a':
+ aflag = 1;
+ break;
+ case 's':
+ sflag = 1;
+ break;
+ case 'd':
+ dflag = 1;
+ errno = 0;
+ depth = atoi(optarg);
+ if (errno == ERANGE || depth < 0) {
+ warnx("invalid argument to option d: %s", optarg);
+ usage();
+ }
+ break;
+ case 'c':
+ cflag = 1;
+ break;
+ case 'h':
+ putenv("BLOCKSIZE=512");
+ hflag = 1;
+ valp = vals_base2;
+ break;
+ case 'k':
+ hflag = 0;
+ putenv("BLOCKSIZE=1024");
+ break;
+ case 'm':
+ hflag = 0;
+ putenv("BLOCKSIZE=1048576");
+ break;
+ case 'g':
+ hflag = 0;
+ putenv("BLOCKSIZE=1g");
+ break;
+ case 'r': /* Compatibility. */
+ break;
+ case 'x':
+ ftsoptions |= FTS_XDEV;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+
+// argc -= optind;
+ argv += optind;
+
+ /*
+ * XXX
+ * Because of the way that fts(3) works, logical walks will not count
+ * the blocks actually used by symbolic links. We rationalize this by
+ * noting that users computing logical sizes are likely to do logical
+ * copies, so not counting the links is correct. The real reason is
+ * that we'd have to re-implement the kernel's symbolic link traversing
+ * algorithm to get this right. If, for example, you have relative
+ * symbolic links referencing other relative symbolic links, it gets
+ * very nasty, very fast. The bottom line is that it's documented in
+ * the man page, so it's a feature.
+ */
+
+ if (Hflag + Lflag + Pflag > 1)
+ usage();
+
+ if (Hflag + Lflag + Pflag == 0)
+ Pflag = 1; /* -P (physical) is default */
+
+ if (Hflag)
+ ftsoptions |= FTS_COMFOLLOW;
+
+ if (Lflag)
+ ftsoptions |= FTS_LOGICAL;
+
+ if (Pflag)
+ ftsoptions |= FTS_PHYSICAL;
+
+ listall = 0;
+
+ if (aflag) {
+ if (sflag || dflag)
+ usage();
+ listall = 1;
+ } else if (sflag) {
+ if (dflag)
+ usage();
+ depth = 0;
+ }
+
+ if (!*argv) {
+ argv = save;
+ argv[0] = dot;
+ argv[1] = NULL;
+ }
+
+ (void) getbsize(¬used, &blocksize);
+ blocksize /= 512;
+
+ rval = 0;
+
+ if ((fts = fts_open(argv, ftsoptions, NULL)) == NULL) {
+ err(1, "fts_open");
+ }
+
+ while ((p = fts_read(fts)) != NULL) {
+ switch (p->fts_info) {
+ case FTS_D:
+ if (ignorep(p) || dirlinkchk(p))
+ fts_set(fts, p, FTS_SKIP);
+ break;
+ case FTS_DP:
+ if (ignorep(p))
+ break;
+
+ ftsparnum = (off_t *)&p->fts_parent->fts_number;
+ ftsnum = (off_t *)&p->fts_number;
+ if (p->fts_statp->st_size < TWO_TB) {
+ ftsparnum[0] += ftsnum[0] += p->fts_statp->st_blocks;
+ } else {
+ ftsparnum[0] += ftsnum[0] += howmany(p->fts_statp->st_size, 512LL);
+ }
+
+ if (p->fts_level <= depth) {
+ if (hflag) {
+ (void) prthumanval(howmany(*ftsnum, blocksize));
+ (void) fprintf(thread_stdout, "\t%s\n", p->fts_path);
+ } else {
+ (void) fprintf(thread_stdout, "%jd\t%s\n",
+ (intmax_t)howmany(*ftsnum, blocksize),
+ p->fts_path);
+ }
+ }
+ break;
+ case FTS_DC: /* Ignore. */
+ if (COMPAT_MODE("bin/du", "unix2003")) {
+ errx(1, "Can't follow symlink cycle from %s to %s", p->fts_path, p->fts_cycle->fts_path);
+ }
+ break;
+ case FTS_DNR: /* Warn, continue. */
+ case FTS_ERR:
+ case FTS_NS:
+ warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
+ rval = 1;
+ break;
+ case FTS_SLNONE:
+ if (COMPAT_MODE("bin/du", "unix2003")) {
+ struct stat sb;
+ int rc = stat(p->fts_path, &sb);
+ if (rc < 0 && errno == ELOOP) {
+ errx(1, "Too many symlinks at %s", p->fts_path);
+ }
+ }
+ default:
+ if (ignorep(p))
+ break;
+
+ if (p->fts_statp->st_nlink > 1 && linkchk(p))
+ break;
+
+ if (listall || p->fts_level == 0) {
+ if (hflag) {
+ if (p->fts_statp->st_size < TWO_TB) {
+ (void) prthumanval(howmany(p->fts_statp->st_blocks,
+ blocksize));
+ } else {
+ (void) prthumanval(howmany(howmany(p->fts_statp->st_size, 512LL),
+ blocksize));
+ }
+ (void) fprintf(thread_stdout, "\t%s\n", p->fts_path);
+ } else {
+ if (p->fts_statp->st_size < TWO_TB) {
+ (void) fprintf(thread_stdout, "%jd\t%s\n",
+ (intmax_t)howmany(p->fts_statp->st_blocks, blocksize),
+ p->fts_path);
+ } else {
+ (void) fprintf(thread_stdout, "%jd\t%s\n",
+ (intmax_t)howmany(howmany(p->fts_statp->st_size, 512LL), blocksize),
+ p->fts_path);
+ }
+ }
+ }
+
+ ftsparnum = (off_t *)&p->fts_parent->fts_number;
+ if (p->fts_statp->st_size < TWO_TB) {
+ ftsparnum[0] += p->fts_statp->st_blocks;
+ } else {
+ ftsparnum[0] += p->fts_statp->st_size / 512LL;
+ }
+ }
+ savednumber = ((off_t *)&p->fts_parent->fts_number)[0];
+ }
+
+ if (errno) {
+ err(1, "fts_read");
+ }
+
+ if (cflag) {
+ if (hflag) {
+ (void) prthumanval(howmany(savednumber, blocksize));
+ (void) fprintf(thread_stdout, "\ttotal\n");
+ } else {
+ (void) fprintf(thread_stdout, "%jd\ttotal\n", (intmax_t)howmany(savednumber, blocksize));
+ }
+ }
+
+ ignoreclean();
+ exit(rval);
+}
+
+static int
+linkchk(FTSENT *p)
+{
+ struct links_entry {
+ struct links_entry *next;
+ struct links_entry *previous;
+ int links;
+ dev_t dev;
+ ino_t ino;
+ };
+ static const size_t links_hash_initial_size = 8192;
+ static struct links_entry **buckets;
+ static struct links_entry *free_list;
+ static size_t number_buckets;
+ static unsigned long number_entries;
+ static char stop_allocating;
+ struct links_entry *le, **new_buckets;
+ struct stat *st;
+ size_t i, new_size;
+ int hash;
+
+ st = p->fts_statp;
+
+ /* If necessary, initialize the hash table. */
+ if (buckets == NULL) {
+ number_buckets = links_hash_initial_size;
+ buckets = malloc(number_buckets * sizeof(buckets[0]));
+ if (buckets == NULL) {
+ errx(1, "No memory for hardlink detection");
+ }
+ for (i = 0; i < number_buckets; i++)
+ buckets[i] = NULL;
+ }
+
+ /* If the hash table is getting too full, enlarge it. */
+ if (number_entries > number_buckets * 10 && !stop_allocating) {
+ new_size = number_buckets * 2;
+ new_buckets = malloc(new_size * sizeof(struct links_entry *));
+
+ /* Try releasing the free list to see if that helps. */
+ if (new_buckets == NULL && free_list != NULL) {
+ while (free_list != NULL) {
+ le = free_list;
+ free_list = le->next;
+ free(le);
+ }
+ new_buckets = malloc(new_size * sizeof(new_buckets[0]));
+ }
+
+ if (new_buckets == NULL) {
+ stop_allocating = 1;
+ warnx("No more memory for tracking hard links");
+ } else {
+ memset(new_buckets, 0,
+ new_size * sizeof(struct links_entry *));
+ for (i = 0; i < number_buckets; i++) {
+ while (buckets[i] != NULL) {
+ /* Remove entry from old bucket. */
+ le = buckets[i];
+ buckets[i] = le->next;
+
+ /* Add entry to new bucket. */
+ hash = (le->dev ^ le->ino) % new_size;
+
+ if (new_buckets[hash] != NULL)
+ new_buckets[hash]->previous =
+ le;
+ le->next = new_buckets[hash];
+ le->previous = NULL;
+ new_buckets[hash] = le;
+ }
+ }
+ free(buckets);
+ buckets = new_buckets;
+ number_buckets = new_size;
+ }
+ }
+
+ /* Try to locate this entry in the hash table. */
+ hash = ( st->st_dev ^ st->st_ino ) % number_buckets;
+ for (le = buckets[hash]; le != NULL; le = le->next) {
+ if (le->dev == st->st_dev && le->ino == st->st_ino) {
+ /*
+ * Save memory by releasing an entry when we've seen
+ * all of it's links.
+ */
+ if (--le->links <= 0) {
+ if (le->previous != NULL)
+ le->previous->next = le->next;
+ if (le->next != NULL)
+ le->next->previous = le->previous;
+ if (buckets[hash] == le)
+ buckets[hash] = le->next;
+ number_entries--;
+ /* Recycle this node through the free list */
+ if (stop_allocating) {
+ free(le);
+ } else {
+ le->next = free_list;
+ free_list = le;
+ }
+ }
+ return (1);
+ }
+ }
+
+ if (stop_allocating)
+ return (0);
+
+ /* Add this entry to the links cache. */
+ if (free_list != NULL) {
+ /* Pull a node from the free list if we can. */
+ le = free_list;
+ free_list = le->next;
+ } else
+ /* Malloc one if we have to. */
+ le = malloc(sizeof(struct links_entry));
+ if (le == NULL) {
+ stop_allocating = 1;
+ warnx("No more memory for tracking hard links");
+ return (0);
+ }
+ le->dev = st->st_dev;
+ le->ino = st->st_ino;
+ le->links = st->st_nlink - 1;
+ number_entries++;
+ le->next = buckets[hash];
+ le->previous = NULL;
+ if (buckets[hash] != NULL)
+ buckets[hash]->previous = le;
+ buckets[hash] = le;
+ return (0);
+}
+
+static int
+dirlinkchk(FTSENT *p)
+{
+ struct links_entry {
+ struct links_entry *next;
+ struct links_entry *previous;
+ int links;
+ dev_t dev;
+ ino_t ino;
+ };
+ static const size_t links_hash_initial_size = 8192;
+ static struct links_entry **buckets;
+ static struct links_entry *free_list;
+ static size_t number_buckets;
+ static unsigned long number_entries;
+ static char stop_allocating;
+ struct links_entry *le, **new_buckets;
+ struct stat *st;
+ size_t i, new_size;
+ int hash;
+ struct attrbuf {
+ int size;
+ int linkcount;
+ } buf;
+ struct attrlist attrList;
+
+ memset(&attrList, 0, sizeof(attrList));
+ attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
+ attrList.dirattr = ATTR_DIR_LINKCOUNT;
+ if (-1 == getattrlist(p->fts_path, &attrList, &buf, sizeof(buf), 0))
+ return 0;
+ if (buf.linkcount == 1)
+ return 0;
+ st = p->fts_statp;
+
+ /* If necessary, initialize the hash table. */
+ if (buckets == NULL) {
+ number_buckets = links_hash_initial_size;
+ buckets = malloc(number_buckets * sizeof(buckets[0]));
+ if (buckets == NULL) {
+ errx(1, "No memory for directory hardlink detection");
+ }
+ for (i = 0; i < number_buckets; i++)
+ buckets[i] = NULL;
+ }
+
+ /* If the hash table is getting too full, enlarge it. */
+ if (number_entries > number_buckets * 10 && !stop_allocating) {
+ new_size = number_buckets * 2;
+ new_buckets = malloc(new_size * sizeof(struct links_entry *));
+
+ /* Try releasing the free list to see if that helps. */
+ if (new_buckets == NULL && free_list != NULL) {
+ while (free_list != NULL) {
+ le = free_list;
+ free_list = le->next;
+ free(le);
+ }
+ new_buckets = malloc(new_size * sizeof(new_buckets[0]));
+ }
+
+ if (new_buckets == NULL) {
+ stop_allocating = 1;
+ warnx("No more memory for tracking directory hard links");
+ } else {
+ memset(new_buckets, 0,
+ new_size * sizeof(struct links_entry *));
+ for (i = 0; i < number_buckets; i++) {
+ while (buckets[i] != NULL) {
+ /* Remove entry from old bucket. */
+ le = buckets[i];
+ buckets[i] = le->next;
+
+ /* Add entry to new bucket. */
+ hash = (le->dev ^ le->ino) % new_size;
+
+ if (new_buckets[hash] != NULL)
+ new_buckets[hash]->previous =
+ le;
+ le->next = new_buckets[hash];
+ le->previous = NULL;
+ new_buckets[hash] = le;
+ }
+ }
+ free(buckets);
+ buckets = new_buckets;
+ number_buckets = new_size;
+ }
+ }
+
+ /* Try to locate this entry in the hash table. */
+ hash = ( st->st_dev ^ st->st_ino ) % number_buckets;
+ for (le = buckets[hash]; le != NULL; le = le->next) {
+ if (le->dev == st->st_dev && le->ino == st->st_ino) {
+ /*
+ * Save memory by releasing an entry when we've seen
+ * all of it's links.
+ */
+ if (--le->links <= 0) {
+ if (le->previous != NULL)
+ le->previous->next = le->next;
+ if (le->next != NULL)
+ le->next->previous = le->previous;
+ if (buckets[hash] == le)
+ buckets[hash] = le->next;
+ number_entries--;
+ /* Recycle this node through the free list */
+ if (stop_allocating) {
+ free(le);
+ } else {
+ le->next = free_list;
+ free_list = le;
+ }
+ }
+ return (1);
+ }
+ }
+
+ if (stop_allocating)
+ return (0);
+ /* Add this entry to the links cache. */
+ if (free_list != NULL) {
+ /* Pull a node from the free list if we can. */
+ le = free_list;
+ free_list = le->next;
+ } else
+ /* Malloc one if we have to. */
+ le = malloc(sizeof(struct links_entry));
+ if (le == NULL) {
+ stop_allocating = 1;
+ warnx("No more memory for tracking hard links");
+ return (0);
+ }
+ le->dev = st->st_dev;
+ le->ino = st->st_ino;
+ le->links = buf.linkcount - 1;
+ number_entries++;
+ le->next = buckets[hash];
+ le->previous = NULL;
+ if (buckets[hash] != NULL)
+ buckets[hash]->previous = le;
+ buckets[hash] = le;
+ return (0);
+}
+
+/*
+ * Output in "human-readable" format. Uses 3 digits max and puts
+ * unit suffixes at the end. Makes output compact and easy to read,
+ * especially on huge disks.
+ *
+ */
+unit_t
+unit_adjust(double *val)
+{
+ double abval;
+ unit_t unit;
+ unsigned int unit_sz;
+
+ abval = fabs(*val);
+
+ unit_sz = abval ? ilogb(abval) / 10 : 0;
+
+ if (unit_sz >= UNIT_MAX) {
+ unit = NONE;
+ } else {
+ unit = unitp[unit_sz];
+ *val /= (double)valp[unit_sz];
+ }
+
+ return (unit);
+}
+
+void
+prthumanval(double bytes)
+{
+ unit_t unit;
+
+ bytes *= 512;
+ unit = unit_adjust(&bytes);
+
+ if (bytes == 0)
+ (void)fprintf(thread_stdout, " 0B");
+ else if (bytes > 10)
+ (void)fprintf(thread_stdout, "%3.0f%c", bytes, "BKMGTPE"[unit]);
+ else
+ (void)fprintf(thread_stdout, "%3.1f%c", bytes, "BKMGTPE"[unit]);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(thread_stderr,
+ "usage: du [-H | -L | -P] [-a | -s | -d depth] [-c] [-h | -k | -m | -g] [-x] [-I mask] [file ...]\n");
+ exit(EX_USAGE);
+}
+
+void
+ignoreadd(const char *mask)
+{
+ struct ignentry *ign;
+
+ ign = calloc(1, sizeof(*ign));
+ if (ign == NULL) {
+ errx(1, "cannot allocate memory");
+ }
+ ign->mask = strdup(mask);
+ if (ign->mask == NULL) {
+ errx(1, "cannot allocate memory");
+ }
+ SLIST_INSERT_HEAD(&ignores, ign, next);
+}
+
+void
+ignoreclean(void)
+{
+ struct ignentry *ign;
+
+ while (!SLIST_EMPTY(&ignores)) {
+ ign = SLIST_FIRST(&ignores);
+ SLIST_REMOVE_HEAD(&ignores, next);
+ free(ign->mask);
+ free(ign);
+ }
+}
+
+int
+ignorep(FTSENT *ent)
+{
+ struct ignentry *ign;
+
+#ifdef __APPLE__
+ if (S_ISDIR(ent->fts_statp->st_mode) && !strcmp("fd", ent->fts_name)) {
+ struct statfs sfsb;
+ int rc = statfs(ent->fts_accpath, &sfsb);
+ if (rc >= 0 && !strcmp("devfs", sfsb.f_fstypename)) {
+ /* Don't cd into /dev/fd/N since one of those is likely to be
+ the cwd as of the start of du which causes all manner of
+ unpleasant surprises */
+ return 1;
+ }
+ }
+#endif /* __APPLE__ */
+ SLIST_FOREACH(ign, &ignores, next)
+ if (fnmatch(ign->mask, ent->fts_name, 0) != FNM_NOMATCH)
+ return 1;
+ return 0;
+}
diff --git a/files/Sources/files/gzip/futimens.c b/files/Sources/files/gzip/futimens.c
new file mode 100644
index 00000000..08345c33
--- /dev/null
+++ b/files/Sources/files/gzip/futimens.c
@@ -0,0 +1,100 @@
+/*-
+ * Copyright (c) 2015 Jilles Tjoelker
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include
+__FBSDID("$FreeBSD$");
+
+#include
+
+#include
+#include