aboutsummaryrefslogtreecommitdiffstats
path: root/awk1.c
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2010-07-02 15:49:42 +0300
committerArnold D. Robbins <arnold@skeeve.com>2010-07-02 15:49:42 +0300
commit483a58b779f2bd6c5fff64c9429a766d33e46a41 (patch)
tree41ee58e21c390c40d90893b277542b309e7d0de7 /awk1.c
parent3711eedc1b995eb1926c9ffb902d5d796cacf8d0 (diff)
downloadegawk-483a58b779f2bd6c5fff64c9429a766d33e46a41.tar.gz
egawk-483a58b779f2bd6c5fff64c9429a766d33e46a41.tar.bz2
egawk-483a58b779f2bd6c5fff64c9429a766d33e46a41.zip
Now at 2.03.
Diffstat (limited to 'awk1.c')
-rw-r--r--awk1.c555
1 files changed, 176 insertions, 379 deletions
diff --git a/awk1.c b/awk1.c
index b6b4c7b4..e8bb49f4 100644
--- a/awk1.c
+++ b/awk1.c
@@ -1,4 +1,3 @@
-
/*
* awk1 -- Expression tree constructors and main program for gawk.
*
@@ -6,6 +5,20 @@
* 1986
*
* $Log: awk1.c,v $
+ * Revision 1.34 89/03/24 15:57:21 david
+ * hashnode changes to NODE
+ *
+ * Revision 1.33 89/03/21 10:58:26 david
+ * cleanup and movement of code to awk.y
+ *
+ * Revision 1.32 89/03/15 22:00:35 david
+ * old case stuff removed
+ * new case stuff added
+ * add new escape sequences
+ *
+ * Revision 1.31 89/03/15 21:31:10 david
+ * purge obstack stuff
+ *
* Revision 1.30 88/12/15 12:56:18 david
* changes from Jay to compile under gcc and fixing a bug in treatment of
* input files
@@ -148,6 +161,22 @@
#include "awk.h"
+extern int yyparse();
+extern void init_vars();
+extern void set_fs();
+extern int close_io();
+extern void init_args();
+extern void init_fields();
+extern int inrec();
+extern int getopt();
+extern int re_set_syntax();
+extern NODE *node();
+
+static void do_file();
+static void usage();
+
+NODE *variables[HASHSIZE];
+
/*
* The parse tree and field nodes are stored here. Parse_end is a dummy item
* used to free up unneeded fields without freeing the program being run
@@ -159,7 +188,6 @@ int param_counter;
NODE *Nnull_string;
/* The special variable that contains the name of the current input file */
-extern NODE *FILENAME_node;
extern NODE *ARGC_node;
extern NODE *ARGV_node;
@@ -187,10 +215,10 @@ int tempsource = 0; /* source is in a temp file */
char **sourcefile = NULL; /* source file name(s) */
int numfiles = -1; /* how many source files */
-int ignorecase = 0; /* global flag for ignoring case */
-
int strict = 0; /* turn off gnu extensions */
+NODE *expression_value;
+
main(argc, argv)
int argc;
char **argv;
@@ -201,25 +229,23 @@ char **argv;
extern int yydebug;
#endif
- extern char *lexptr;
- extern char *lexptr_begin;
extern char *version_string;
- extern FILE *nextfile();
- FILE *fp, *fopen();
+ FILE *fp;
static char template[] = "/tmp/gawk.XXXXX";
- char *mktemp ();
int c;
- extern int opterr, optind, getopt();
+ extern int opterr, optind;
extern char *optarg;
- char *cp, *rindex();
+ char *cp;
+ extern char *rindex();
+ extern char *mktemp();
/*
* for strict to work, legal options must be first
*/
-#define EXTENSIONS 4 /* where to clear */
+#define EXTENSIONS 5 /* where to clear */
#ifdef DEBUG
- char *awk_opts = "F:f:ivdD";
+ char *awk_opts = "F:f:vVdD";
#else
- char *awk_opts = "F:f:iv";
+ char *awk_opts = "F:f:vV";
#endif
#ifdef DEBUG
@@ -258,7 +284,7 @@ char **argv;
cp++;
else
cp = myname;
- if (strcmp (cp, "awk") == 0)
+ if (STREQ(cp, "awk"))
strict = 1;
#endif
@@ -292,14 +318,14 @@ char **argv;
sourcefile[++numfiles] = optarg;
break;
- case 'i':
- ignorecase = 1;
- break;
-
case 'v':
fprintf(stderr, "%s", version_string);
break;
+ case 'V':
+ copyleft();
+ break;
+
case '?':
default:
/* getopt will print a message for us */
@@ -336,7 +362,6 @@ char **argv;
init_args(optind, argc, myname, argv);
/* Read in the program */
- lexptr_begin = lexptr;
if (yyparse() || errcount)
exit(1);
@@ -367,19 +392,20 @@ char **argv;
exit(exit_val);
}
+static void
do_file(fp)
FILE *fp;
{
input_file = fp;
/* This is where it spends all its time. The infamous MAIN LOOP */
- if (inrec() == 0) {
+ if (inrec() == 0)
while (interpret(expression_value) && inrec() == 0)
;
- }
if (fp != stdin)
(void) fclose(fp);
}
+static void
usage()
{
#ifdef STRICT
@@ -395,84 +421,110 @@ usage()
exit(11);
}
-NODE *
-node_common(op)
-NODETYPE op;
+/* Generate compiled regular expressions */
+struct re_pattern_buffer *
+make_regexp(s, ignorecase)
+NODE *s;
+int ignorecase;
{
- register NODE *r;
- extern int lineno;
- extern int numfiles;
- extern int tempsource;
- extern char **sourcefile;
- extern int curinfile;
-
- emalloc(r, NODE *, sizeof(NODE), "node_common");
- r->type = op;
- r->source_line = lineno;
- if (numfiles > 1 && !tempsource)
- r->source_file = sourcefile[curinfile];
+ struct re_pattern_buffer *rp;
+ char *err;
+
+ emalloc(rp, struct re_pattern_buffer *, sizeof(*rp), "make_regexp");
+ bzero((char *) rp, sizeof(*rp));
+ emalloc(rp->buffer, char *, 8, "make_regexp");
+ rp->allocated = 8;
+ emalloc(rp->fastmap, char *, 256, "make_regexp");
+
+ if (! strict && ignorecase)
+ rp->translate = casetable;
else
- r->source_file = NULL;
- return r;
+ rp->translate = NULL;
+ if ((err = re_compile_pattern(s->stptr, s->stlen, rp)) != NULL)
+ fatal("%s: /%s/", err, s->stptr);
+ free_temp(s);
+ return rp;
}
-/*
- * This allocates a node with defined lnode and rnode.
- * This should only be used by yyparse+co while reading in the program
- */
-NODE *
-node(left, op, right)
-NODE *left, *right;
-NODETYPE op;
+FILE *
+nextfile()
{
- register NODE *r;
+ static int i = 1;
+ static int files = 0;
+ char *arg;
+ char *cp;
+ FILE *fp;
- r = node_common(op);
- r->lnode = left;
- r->rnode = right;
- return r;
+ for (; i < (int) (ARGC_node->lnode->numbr); i++) {
+ arg = (*assoc_lookup(ARGV_node, tmp_number((AWKNUM) i)))->stptr;
+ if (*arg == '\0')
+ continue;
+ cp = index(arg, '=');
+ if (cp != NULL) {
+ *cp++ = '\0';
+ variable(arg)->var_value = make_string(cp, strlen(cp));
+ } else {
+ extern NODE *deref;
+
+ files++;
+ if (STREQ(arg, "-"))
+ fp = stdin;
+ else
+ fp = fopen(arg, "r");
+ if (fp == NULL)
+ fatal("cannot open file `%s' for reading (%s)",
+ arg, sys_errlist[errno]);
+ /* NOTREACHED */
+ /* This is a kludge. */
+ deref = FILENAME_node->var_value;
+ do_deref();
+ FILENAME_node->var_value =
+ make_string(arg, strlen(arg));
+ FNR_node->var_value->numbr = 0.0;
+ i++;
+ return fp;
+ }
+ }
+ if (files == 0) {
+ files++;
+ /* no args. -- use stdin */
+ /* FILENAME is init'ed to "-" */
+ /* FNR is init'ed to 0 */
+ return stdin;
+ }
+ return NULL;
}
-/*
- * This allocates a node with defined subnode and proc
- * Otherwise like node()
- */
+/* Name points to a variable name. Make sure its in the symbol table */
NODE *
-snode(subn, op, procp)
-NODETYPE op;
-NODE *(*procp) ();
-NODE *subn;
+variable(name)
+char *name;
{
register NODE *r;
- r = node_common(op);
- r->subnode = subn;
- r->proc = procp;
+ if ((r = lookup(variables, name)) == NULL)
+ r = install(variables, name,
+ node(Nnull_string, Node_var, (NODE *) NULL));
return r;
}
-/*
- * This allocates a Node_line_range node with defined condpair and
- * zeroes the trigger word to avoid the temptation of assuming that calling
- * 'node( foo, Node_line_range, 0)' will properly initialize 'triggered'.
- */
-/* Otherwise like node() */
+/* Create a special variable */
NODE *
-mkrangenode(cpair)
-NODE *cpair;
+spc_var(name, value)
+char *name;
+NODE *value;
{
register NODE *r;
- emalloc(r, NODE *, sizeof(NODE), "mkrangenode");
- r->type = Node_line_range;
- r->condpair = cpair;
- r->triggered = 0;
+ if ((r = lookup(variables, name)) == NULL)
+ r = install(variables, name, node(value, Node_var, (NODE *) NULL));
return r;
}
struct re_pattern_buffer *
-mk_re_parse(s)
+mk_re_parse(s, ignorecase)
char *s;
+int ignorecase;
{
register char *src, *dest;
int c;
@@ -481,6 +533,12 @@ char *s;
if (*src == '\\') {
c = *++src;
switch (c) {
+ case 'a':
+ if (strict)
+ goto def;
+ else
+ *dest++ = BELL;
+ break;
case 'b':
*dest++ = '\b';
break;
@@ -497,7 +555,30 @@ char *s;
*dest++ = '\t';
break;
case 'v':
- *dest++ = '\v';
+ if (strict)
+ goto def;
+ else
+ *dest++ = '\v';
+ break;
+ case 'x':
+ if (strict)
+ goto def;
+ else {
+ register int i = 0;
+ register int c;
+
+ while ((c = *++src)) {
+ if (! isxdigit(c))
+ break;
+ if (isdigit(c))
+ i += c - '0';
+ else if (isupper(c))
+ i += c - 'A' + 10;
+ else
+ i += c - 'a' + 10;
+ }
+ *dest++ = i;
+ }
break;
case '0':
case '1':
@@ -522,6 +603,7 @@ char *s;
}
break;
default:
+ def:
*dest++ = '\\';
*dest++ = c;
break;
@@ -531,310 +613,25 @@ char *s;
else
*dest++ = *src;
}
- return make_regexp(tmp_string(s, dest-s));
+ return make_regexp(tmp_string(s, dest-s), ignorecase);
}
-/* Generate compiled regular expressions */
-struct re_pattern_buffer *
-make_regexp(s)
-NODE *s;
+copyleft ()
{
- struct re_pattern_buffer *rp;
- char *err;
-
- emalloc(rp, struct re_pattern_buffer *, sizeof(*rp), "make_regexp");
- bzero((char *) rp, sizeof(*rp));
- emalloc(rp->buffer, char *, 8, "make_regexp");
- rp->allocated = 8;
- emalloc(rp->fastmap, char *, 256, "make_regexp");
-
- if ((err = re_compile_pattern(s->stptr, s->stlen, rp)) != NULL)
- fatal("%s: /%s/", err, s->stptr);
- free_temp(s);
- return rp;
-}
-
-/* Build a for loop */
-NODE *
-make_for_loop(init, cond, incr)
-NODE *init, *cond, *incr;
-{
- register FOR_LOOP_HEADER *r;
- NODE *n;
-
- emalloc(r, FOR_LOOP_HEADER *, sizeof(FOR_LOOP_HEADER), "make_for_loop");
- emalloc(n, NODE *, sizeof(NODE), "make_for_loop");
- r->init = init;
- r->cond = cond;
- r->incr = incr;
- n->type = Node_illegal;
- n->sub.nodep.r.hd = r;
- return n;
-}
-
-/* Name points to a variable name. Make sure its in the symbol table */
-NODE *
-variable(name)
-char *name;
-{
- register NODE *r;
- NODE *lookup(), *install(), *make_name();
-
- if ((r = lookup(variables, name)) == NULL)
- r = install(variables, name,
- node(Nnull_string, Node_var, (NODE *) NULL));
- return r;
-}
-
-/* Create a special variable */
-NODE *
-spc_var(name, value)
-char *name;
-NODE *value;
-{
- register NODE *r;
- NODE *lookup(), *install();
-
- if ((r = lookup(variables, name)) == NULL)
- r = install(variables, name, node(value, Node_var, (NODE *) NULL));
- return r;
-}
-
-
-
-/*
- * Install a name in the hash table specified, even if it is already there.
- * Name stops with first non alphanumeric. Caller must check against
- * redefinition if that is desired.
- */
-NODE *
-install(table, name, value)
-HASHNODE **table;
-char *name;
-NODE *value;
-{
- register HASHNODE *hp;
- register int i, len, bucket;
- register char *p;
-
- len = 0;
- p = name;
- while (is_identchar(*p))
- p++;
- len = p - name;
-
- i = sizeof(HASHNODE) + len + 1;
- emalloc(hp, HASHNODE *, i, "install");
- bucket = hashf(name, len, HASHSIZE);
- hp->next = table[bucket];
- table[bucket] = hp;
- hp->length = len;
- hp->value = value;
- hp->name = ((char *) hp) + sizeof(HASHNODE);
- hp->length = len;
- bcopy(name, hp->name, len);
- hp->name[len] = '\0';
- hp->value->varname = hp->name;
- return hp->value;
-}
-
-/*
- * find the most recent hash node for name name (ending with first
- * non-identifier char) installed by install
- */
-NODE *
-lookup(table, name)
-HASHNODE **table;
-char *name;
-{
- register char *bp;
- register HASHNODE *bucket;
- register int len;
-
- for (bp = name; is_identchar(*bp); bp++)
- ;
- len = bp - name;
- bucket = table[hashf(name, len, HASHSIZE)];
- while (bucket) {
- if (bucket->length == len && strncmp(bucket->name, name, len) == 0)
- return bucket->value;
- bucket = bucket->next;
- }
- return NULL;
-}
-
-#define HASHSTEP(old, c) ((old << 1) + c)
-#define MAKE_POS(v) (v & ~0x80000000) /* make number positive */
-
-/*
- * return hash function on name.
- */
-int
-hashf(name, len, hashsize)
-register char *name;
-register int len;
-int hashsize;
-{
- register int r = 0;
-
- while (len--)
- r = HASHSTEP(r, *name++);
-
- r = MAKE_POS(r) % hashsize;
- return r;
-}
-
-/*
- * Add new to the rightmost branch of LIST. This uses n^2 time, but doesn't
- * get used enough to make optimizing worth it. . .
- */
-/* You don't believe me? Profile it yourself! */
-
-NODE *
-append_right(list, new)
-NODE *list, *new;
-{
- register NODE *oldlist;
-
- oldlist = list;
- while (list->rnode != NULL)
- list = list->rnode;
- list->rnode = new;
- return oldlist;
-}
-
-/*
- * check if name is already installed; if so, it had better have Null value,
- * in which case def is added as the value. Otherwise, install name with def
- * as value.
- */
-func_install(params, def)
-NODE *params;
-NODE *def;
-{
- NODE *r;
- NODE *lookup();
-
- pop_params(params);
- r = lookup(variables, params->param);
- if (r != NULL) {
- fatal("function name `%s' previously defined", params->param);
- } else
- (void) install(variables, params->param,
- node(params, Node_func, def));
-}
-
-NODE *
-pop_var(name)
-char *name;
-{
- register char *bp;
- register HASHNODE *bucket, **save;
- register int len;
-
- for (bp = name; is_identchar(*bp); bp++)
- ;
- len = bp - name;
- save = &(variables[hashf(name, len, HASHSIZE)]);
- bucket = *save;
- while (bucket) {
- if (strncmp(bucket->name, name, len) == 0) {
- *save = bucket->next;
- return bucket->value;
- }
- save = &(bucket->next);
- bucket = bucket->next;
- }
- return NULL;
-}
-
-pop_params(params)
-NODE *params;
-{
- register NODE *np;
-
- for (np = params; np != NULL; np = np->rnode)
- pop_var(np->param);
-}
-
-NODE *
-make_name(name, type)
-char *name;
-NODETYPE type;
-{
- register char *p;
- register NODE *r;
- register int len;
-
- p = name;
- while (is_identchar(*p))
- p++;
- len = p - name;
- emalloc(r, NODE *, sizeof(NODE), "make_name");
- emalloc(r->param, char *, len + 1, "make_name");
- bcopy(name, r->param, len);
- r->param[len] = '\0';
- r->rnode = NULL;
- r->type = type;
- return (install(variables, name, r));
-}
-
-NODE *make_param(name)
-char *name;
-{
- NODE *r;
-
- r = make_name(name, Node_param_list);
- r->param_cnt = param_counter++;
- return r;
-}
-
-FILE *
-nextfile()
-{
- static int i = 1;
- static int files = 0;
- char *arg;
+ extern char *version_string;
char *cp;
- FILE *fp;
- extern NODE **assoc_lookup();
-
- for (; i < (int) (ARGC_node->lnode->numbr); i++) {
- arg = (*assoc_lookup(ARGV_node, tmp_number((AWKNUM) i)))->stptr;
- if (*arg == '\0')
- continue;
- cp = index(arg, '=');
- if (cp != NULL) {
- *cp++ = '\0';
- variable(arg)->var_value = make_string(cp, strlen(cp));
- } else {
- extern NODE *deref;
-
- files++;
- if (strcmp(arg, "-") == 0)
- fp = stdin;
- else
- fp = fopen(arg, "r");
- if (fp == NULL)
- fatal("cannot open file `%s' for reading (%s)",
- arg, sys_errlist[errno]);
- /* NOTREACHED */
- /* This is a kludge. */
- deref = FILENAME_node->var_value;
- do_deref();
- FILENAME_node->var_value =
- make_string(arg, strlen(arg));
- FNR_node->var_value->numbr = 0.0;
- i++;
- return fp;
- }
- }
- if (files == 0) {
- files++;
- /* no args. -- use stdin */
- /* FILENAME is init'ed to "-" */
- /* FNR is init'ed to 0 */
- return stdin;
- }
- return NULL;
+ static char blurb[] =
+".\nCopyright (C) 1989, Free Software Foundation.\n\
+GNU Awk comes with ABSOLUTELY NO WARRANTY. This is free software, and\n\
+you are welcome to distribute it under the terms of the GNU General\n\
+Public License, which covers both the warranty information and the\n\
+terms for redistribution.\n\
+\n\
+You should have received a copy of the GNU General Public License along\n\
+with this program; if not, write to the Free Software Foundation, Inc.,\n\
+675 Mass Ave, Cambridge, MA 02139, USA.\n";
+
+ for (cp = version_string; *cp && *cp != '\n'; cp++)
+ putc (*cp, stderr);
+ fprintf(stderr, blurb);
}