📄 awk.y
字号:
case '+': if ((c = nextc()) == '=') { yylval.nodetypeval = Node_assign_plus; return ASSIGNOP; } if (c == '+') return INCREMENT; pushback(); return '+'; case '!': if ((c = nextc()) == '=') { yylval.nodetypeval = Node_notequal; return RELOP; } if (c == '~') { yylval.nodetypeval = Node_nomatch; want_assign = 0; return MATCHOP; } pushback(); return '!'; case '<': if (nextc() == '=') { yylval.nodetypeval = Node_leq; return RELOP; } yylval.nodetypeval = Node_less; pushback(); return '<'; case '=': if (nextc() == '=') { yylval.nodetypeval = Node_equal; return RELOP; } yylval.nodetypeval = Node_assign; pushback(); return ASSIGNOP; case '>': if ((c = nextc()) == '=') { yylval.nodetypeval = Node_geq; return RELOP; } else if (c == '>') { yylval.nodetypeval = Node_redirect_append; return APPEND_OP; } yylval.nodetypeval = Node_greater; pushback(); return '>'; case '~': yylval.nodetypeval = Node_match; want_assign = 0; return MATCHOP; case '}': /* * Added did newline stuff. Easier than * hacking the grammar */ if (did_newline) { did_newline = 0; return c; } did_newline++; --lexptr; /* pick up } next time */ return NEWLINE; case '"': esc_seen = 0; while ((c = nextc()) != '"') { if (c == '\n') { pushback(); yyerror("unterminated string"); } if (c == '\\') { c = nextc(); if (c == '\n') { sourceline++; continue; } esc_seen = 1; tokadd('\\'); } if (c == '\0') { pushback(); yyerror("unterminated string"); } tokadd(c); } yylval.nodeval = make_str_node(tokstart, token - tokstart, esc_seen ? SCAN : 0); yylval.nodeval->flags |= PERM; return YSTRING; case '-': if ((c = nextc()) == '=') { yylval.nodetypeval = Node_assign_minus; return ASSIGNOP; } if (c == '-') return DECREMENT; pushback(); return '-'; case '.': c = nextc(); pushback(); if (!isdigit(c)) return '.'; else c = '.'; /* FALL THROUGH */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* It's a number */ for (;;) { int gotnumber = 0; tokadd(c); switch (c) { case '.': if (seen_point) { gotnumber++; break; } ++seen_point; break; case 'e': case 'E': if (seen_e) { gotnumber++; break; } ++seen_e; if ((c = nextc()) == '-' || c == '+') tokadd(c); else pushback(); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': break; default: gotnumber++; } if (gotnumber) break; c = nextc(); } pushback(); yylval.nodeval = make_number(atof(tokstart)); yylval.nodeval->flags |= PERM; return YNUMBER; case '&': if ((c = nextc()) == '&') { yylval.nodetypeval = Node_and; for (;;) { c = nextc(); if (c == '\0') break; if (c == '#') { while ((c = nextc()) != '\n' && c != '\0') ; if (c == '\0') break; } if (c == '\n') sourceline++; if (! isspace(c)) { pushback(); break; } } want_assign = 0; return LEX_AND; } pushback(); return '&'; case '|': if ((c = nextc()) == '|') { yylval.nodetypeval = Node_or; for (;;) { c = nextc(); if (c == '\0') break; if (c == '#') { while ((c = nextc()) != '\n' && c != '\0') ; if (c == '\0') break; } if (c == '\n') sourceline++; if (! isspace(c)) { pushback(); break; } } want_assign = 0; return LEX_OR; } pushback(); return '|'; } if (c != '_' && ! isalpha(c)) yyerror("Invalid char '%c' in expression\n", c); /* it's some type of name-type-thing. Find its length */ token = tokstart; while (is_identchar(c)) { tokadd(c); c = nextc(); } tokadd('\0'); emalloc(tokkey, char *, token - tokstart, "yylex"); memcpy(tokkey, tokstart, token - tokstart); pushback(); /* See if it is a special token. */ low = 0; high = (sizeof (tokentab) / sizeof (tokentab[0])) - 1; while (low <= high) { int i/* , c */; mid = (low + high) / 2; c = *tokstart - tokentab[mid].operator[0]; i = c ? c : strcmp (tokstart, tokentab[mid].operator); if (i < 0) { /* token < mid */ high = mid - 1; } else if (i > 0) { /* token > mid */ low = mid + 1; } else { if (do_lint) { if (tokentab[mid].flags & GAWKX) warning("%s() is a gawk extension", tokentab[mid].operator); if (tokentab[mid].flags & NOT_POSIX) warning("POSIX does not allow %s", tokentab[mid].operator); if (tokentab[mid].flags & NOT_OLD) warning("%s is not supported in old awk", tokentab[mid].operator); } if ((do_unix && (tokentab[mid].flags & GAWKX)) || (do_posix && (tokentab[mid].flags & NOT_POSIX))) break; if (tokentab[mid].class == LEX_BUILTIN || tokentab[mid].class == LEX_LENGTH ) yylval.lval = mid; else yylval.nodetypeval = tokentab[mid].value; return tokentab[mid].class; } } yylval.sval = tokkey; if (*lexptr == '(') return FUNC_CALL; else { want_assign = 1; return NAME; }}static NODE *node_common(op)NODETYPE op;{ register NODE *r; getnode(r); r->type = op; r->flags = MALLOC; /* if lookahead is NL, lineno is 1 too high */ if (lexeme && *lexeme == '\n') r->source_line = sourceline - 1; else r->source_line = sourceline; r->source_file = source; return r;}/* * This allocates a node with defined lnode and rnode. */NODE *node(left, op, right)NODE *left, *right;NODETYPE op;{ register NODE *r; r = node_common(op); r->lnode = left; r->rnode = right; return r;}/* * This allocates a node with defined subnode and proc for builtin functions * Checks for arg. count and supplies defaults where possible. */static NODE *snode(subn, op, idx)NODETYPE op;int idx;NODE *subn;{ register NODE *r; register NODE *n; int nexp = 0; int args_allowed; r = node_common(op); /* traverse expression list to see how many args. given */ for (n= subn; n; n= n->rnode) { nexp++; if (nexp > 3) break; } /* check against how many args. are allowed for this builtin */ args_allowed = tokentab[idx].flags & ARGS; if (args_allowed && !(args_allowed & A(nexp))) fatal("%s() cannot have %d argument%c", tokentab[idx].operator, nexp, nexp == 1 ? ' ' : 's'); r->proc = tokentab[idx].ptr; /* special case processing for a few builtins */ if (nexp == 0 && r->proc == do_length) { subn = node(node(make_number(0.0),Node_field_spec,(NODE *)NULL), Node_expression_list, (NODE *) NULL); } else if (r->proc == do_match) { if (subn->rnode->lnode->type != Node_regex) subn->rnode->lnode = mk_rexp(subn->rnode->lnode); } else if (r->proc == do_sub || r->proc == do_gsub) { if (subn->lnode->type != Node_regex) subn->lnode = mk_rexp(subn->lnode); if (nexp == 2) append_right(subn, node(node(make_number(0.0), Node_field_spec, (NODE *) NULL), Node_expression_list, (NODE *) NULL)); else if (do_lint && subn->rnode->rnode->lnode->type == Node_val) warning("string literal as last arg of substitute"); } else if (r->proc == do_split) { if (nexp == 2) append_right(subn, node(FS_node, Node_expression_list, (NODE *) NULL)); n = subn->rnode->rnode->lnode; if (n->type != Node_regex) subn->rnode->rnode->lnode = mk_rexp(n); if (nexp == 2) subn->rnode->rnode->lnode->re_flags |= FS_DFLT; } r->subnode = subn; 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() */static NODE *mkrangenode(cpair)NODE *cpair;{ register NODE *r; getnode(r); r->type = Node_line_range; r->condpair = cpair; r->triggered = 0; return r;}/* Build a for loop */static 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"); getnode(n); n->type = Node_illegal; r->init = init; r->cond = cond; r->incr = incr; n->sub.nodep.r.hd = r; return n;}/* * Install a name in the symbol table, even if it is already there. * Caller must check against redefinition if that is desired. */NODE *install(name, value)char *name;NODE *value;{ register NODE *hp; register int len, bucket; len = strlen(name); bucket = hash(name, len); getnode(hp); hp->type = Node_hashnode; hp->hnext = variables[bucket]; variables[bucket] = hp; hp->hlength = len; hp->hvalue = value; hp->hname = name; hp->hvalue->vname = name; return hp->hvalue;}/* find the most recent hash node for name installed by install */NODE *lookup(name)char *name;{ register NODE *bucket; register int len; len = strlen(name); bucket = variables[hash(name, len)]; while (bucket) { if (bucket->hlength == len && STREQN(bucket->hname, name, len)) return bucket->hvalue; bucket = bucket->hnext; } return NULL;}/* * Add new to the rightmost branch of LIST. This uses n^2 time, so we make * a simple attempt at optimizing it. */static NODE *append_right(list, new)NODE *list, *new;{ register NODE *oldlist; static NODE *savefront = NULL, *savetail = NULL; oldlist = list; if (savefront == oldlist) { savetail = savetail->rnode = new; return oldlist; } else savefront = oldlist; while (list->rnode != NULL) list = list->rnode; savetail = 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. */static voidfunc_install(params, def)NODE *params;NODE *def;{ NODE *r; pop_params(params->rnode); pop_var(params, 0); r = lookup(params->param); if (r != NULL) { fatal("function name `%s' previously defined", params->param); } else (void) install(params->param, node(params, Node_func, def));}static voidpop_var(np, freeit)NODE *np;int freeit;{ register NODE *bucket, **save; register int len; char *name; name = np->param; len = strlen(name); save = &(variables[hash(name, len)]); for (bucket = *save; bucket; bucket = bucket->hnext) { if (len == bucket->hlength && STREQN(bucket->hname, name, len)) { *save = bucket->hnext; freenode(bucket); if (freeit) free(np->param); return; } save = &(bucket->hnext); }}static voidpop_params(params)NODE *params;{ register NODE *np; for (np = params; np != NULL; np = np->rnode) pop_var(np, 1);}static NODE *make_param(name)char *name;{ NODE *r; getnode(r); r->type = Node_param_list; r->rnode = NULL; r->param = name; r->param_cnt = param_counter++; return (install(name, r));}/* Name points to a variable name. Make sure its in the symbol table */NODE *variable(name, can_free)char *name;int can_free;{ register NODE *r; static int env_loaded = 0; if (!env_loaded && STREQ(name, "ENVIRON")) { load_environ(); env_loaded = 1; } if ((r = lookup(name)) == NULL) r = install(name, node(Nnull_string, Node_var, (NODE *) NULL)); else if (can_free) free(name); return r;}static NODE *mk_rexp(exp)NODE *exp;{ if (exp->type == Node_regex) return exp; else { NODE *n; getnode(n); n->type = Node_regex; n->re_exp = exp; n->re_text = NULL; n->re_reg = NULL; n->re_flags = 0; n->re_cnt = 1; return n; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -