aboutsummaryrefslogtreecommitdiffstats
path: root/awk.y
diff options
context:
space:
mode:
Diffstat (limited to 'awk.y')
-rw-r--r--awk.y114
1 files changed, 77 insertions, 37 deletions
diff --git a/awk.y b/awk.y
index d2d2dbc5..ee3e60e5 100644
--- a/awk.y
+++ b/awk.y
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991 the Free Software Foundation, Inc.
+ * Copyright (C) 1986, 1988, 1989, 1991, 1992 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Progamming Language.
@@ -29,6 +29,7 @@
#endif
#define YYMAXDEPTH 300
+#define YYSSIZE YYMAXDEPTH
#include "awk.h"
@@ -36,7 +37,7 @@ static void yyerror (); /* va_alist */
static char *get_src_buf P((void));
static int yylex P((void));
static NODE *node_common P((NODETYPE op));
-static NODE *snode P((NODE *subn, NODETYPE op, int index));
+static NODE *snode P((NODE *subn, NODETYPE op, int sindex));
static NODE *mkrangenode P((NODE *cpair));
static NODE *make_for_loop P((NODE *init, NODE *cond, NODE *incr));
static NODE *append_right P((NODE *list, NODE *new));
@@ -93,6 +94,7 @@ extern NODE *end_block;
%type <nodeval> input_redir output_redir
%type <nodetypeval> print
%type <sval> func_name
+%type <lval> lex_builtin
%token <sval> FUNC_CALL NAME REGEXP
%token <lval> ERROR
@@ -239,6 +241,18 @@ func_name
{ $$ = $1; }
| FUNC_CALL
{ $$ = $1; }
+ | lex_builtin
+ {
+ yyerror("%s() is a built-in function, it cannot be redefined",
+ tokstart);
+ errcount++;
+ /* yyerrok; */
+ }
+ ;
+
+lex_builtin
+ : LEX_BUILTIN
+ | LEX_LENGTH
;
function_prologue
@@ -292,9 +306,9 @@ regexp
;
action
- : l_brace statements r_brace opt_semi
+ : l_brace statements r_brace opt_semi opt_nls
{ $$ = $2 ; }
- | l_brace r_brace opt_semi
+ | l_brace r_brace opt_semi opt_nls
{ $$ = NULL; }
;
@@ -366,10 +380,19 @@ statement
$$ = node ($2, $1, $3);
}
- | LEX_NEXT
- { if (! io_allowed) yyerror("next used in BEGIN or END action"); }
- statement_term
- { $$ = node ((NODE *)NULL, Node_K_next, (NODE *)NULL); }
+ | LEX_NEXT opt_exp statement_term
+ { NODETYPE type;
+
+ if (! io_allowed) yyerror("next used in BEGIN or END action");
+ if ($2 && $2 == lookup("file")) {
+ if (do_lint)
+ warning("`next file' is a gawk extension");
+ else if (strict || do_posix)
+ yyerror("`next file' is a gawk extension");
+ type = Node_K_nextfile;
+ } else type = Node_K_next;
+ $$ = node ((NODE *)NULL, type, (NODE *)NULL);
+ }
| LEX_EXIT opt_exp statement_term
{ $$ = node ($2, Node_K_exit, (NODE *)NULL); }
| LEX_RETURN
@@ -514,7 +537,11 @@ expression_list
exp : variable ASSIGNOP
{ want_assign = 0; }
exp
- { $$ = node ($1, $2, $4); }
+ {
+ if (do_lint && $4->type == Node_regex)
+ warning("Regular expression on left of assignment.");
+ $$ = node ($1, $2, $4);
+ }
| '(' expression_list r_paren LEX_IN NAME
{ $$ = node (variable($5,1), Node_in_array, $2); }
| exp '|' LEX_GETLINE opt_variable
@@ -551,7 +578,11 @@ exp : variable ASSIGNOP
| exp LEX_IN NAME
{ $$ = node (variable($3,1), Node_in_array, $1); }
| exp RELOP exp
- { $$ = node ($1, $2, $3); }
+ {
+ if (do_lint && $3->type == Node_regex)
+ warning("Regular expression on left of comparison.");
+ $$ = node ($1, $2, $3);
+ }
| exp '<' exp
{ $$ = node ($1, Node_less, $3); }
| exp '>' exp
@@ -620,19 +651,22 @@ non_post_simp_exp
{ $$ = node ($2, Node_not,(NODE *) NULL); }
| '(' exp r_paren
{ $$ = $2; }
- | LEX_BUILTIN '(' opt_expression_list r_paren
- { $$ = snode ($3, Node_builtin, (int) $1); }
+ | LEX_BUILTIN
+ {
+ if (! io_allowed && strcmp(tokstart, "nextfile") == 0)
+ yyerror("nextfile() is illegal in BEGIN and END");
+ }
+ '(' opt_expression_list r_paren
+ { $$ = snode ($4, Node_builtin, (int) $1); }
| LEX_LENGTH '(' opt_expression_list r_paren
{ $$ = snode ($3, Node_builtin, (int) $1); }
| LEX_LENGTH
{
if (do_lint)
- warning("call of length without parentheses is not portable");
+ warning("call of `length' without parentheses is not portable");
$$ = snode ((NODE *)NULL, Node_builtin, (int) $1);
- if (do_posix) {
- yyerror("POSIX requires parentheses for call to `length'");
- yyerrok;
- }
+ if (do_posix)
+ warning( "call of `length' without parentheses is deprecated by POSIX");
}
| FUNC_CALL '(' opt_expression_list r_paren
{
@@ -726,7 +760,7 @@ struct token {
# define VERSION 0xFF00 /* old awk is zero */
# define NOT_OLD 0x0100 /* feature not in old awk */
# define NOT_POSIX 0x0200 /* feature not in POSIX */
-# define GAWK 0x0400 /* gawk extension */
+# define GAWKX 0x0400 /* gawk extension */
NODE *(*ptr) (); /* function that implements this keyword */
};
@@ -757,7 +791,7 @@ static struct token tokentab[] = {
{"func", Node_K_function, LEX_FUNCTION, NOT_POSIX|NOT_OLD, 0},
{"function", Node_K_function, LEX_FUNCTION, NOT_OLD, 0},
{"getline", Node_K_getline, LEX_GETLINE, NOT_OLD, 0},
-{"gsub", Node_builtin, LEX_BUILTIN, NOT_OLD|A(2)|A(3), do_gsub},
+{"gsub", Node_builtin, LEX_BUILTIN, NOT_OLD|A(2)|A(3), do_gsub},
{"if", Node_K_if, LEX_IF, 0, 0},
{"in", Node_illegal, LEX_IN, 0, 0},
{"index", Node_builtin, LEX_BUILTIN, A(2), do_index},
@@ -774,12 +808,12 @@ static struct token tokentab[] = {
{"split", Node_builtin, LEX_BUILTIN, A(2)|A(3), do_split},
{"sprintf", Node_builtin, LEX_BUILTIN, 0, do_sprintf},
{"sqrt", Node_builtin, LEX_BUILTIN, A(1), do_sqrt},
-{"srand", Node_builtin, LEX_BUILTIN, NOT_OLD|A(0)|A(1), do_srand},
-{"strftime", Node_builtin, LEX_BUILTIN, GAWK|A(1)|A(2), do_strftime},
-{"sub", Node_builtin, LEX_BUILTIN, NOT_OLD|A(2)|A(3), do_sub},
+{"srand", Node_builtin, LEX_BUILTIN, NOT_OLD|A(0)|A(1), do_srand},
+{"strftime", Node_builtin, LEX_BUILTIN, GAWKX|A(1)|A(2), do_strftime},
+{"sub", Node_builtin, LEX_BUILTIN, NOT_OLD|A(2)|A(3), do_sub},
{"substr", Node_builtin, LEX_BUILTIN, A(2)|A(3), do_substr},
{"system", Node_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_system},
-{"systime", Node_builtin, LEX_BUILTIN, GAWK|A(0), do_systime},
+{"systime", Node_builtin, LEX_BUILTIN, GAWKX|A(0), do_systime},
{"tolower", Node_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_tolower},
{"toupper", Node_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_toupper},
{"while", Node_K_while, LEX_WHILE, 0, 0},
@@ -829,9 +863,9 @@ va_dcl
}
va_start(args);
mesg = va_arg(args, char *);
- (void) vsprintf(bp, mesg, args);
+ strcpy(bp, mesg);
+ err("", buf, args);
va_end(args);
- msg(buf);
exit(2);
}
@@ -881,7 +915,7 @@ get_src_buf()
lexptr_begin = buf;
lexend = lexptr + 1;
} else
- lexptr = lexptr_begin = NULL;
+ lexeme = lexptr = lexptr_begin = NULL;
return lexptr;
}
if (!samefile) {
@@ -889,7 +923,7 @@ get_src_buf()
if (source == NULL) {
if (buf)
free(buf);
- return lexptr = lexptr_begin = NULL;
+ return lexeme = lexptr = lexptr_begin = NULL;
}
fd = pathopen(source);
if (fd == -1)
@@ -999,7 +1033,7 @@ yylex()
want_regexp = 0;
token = tokstart;
- while (c = nextc()) {
+ while ((c = nextc()) != 0) {
switch (c) {
case '[':
in_brack = 1;
@@ -1266,6 +1300,13 @@ retry:
pushback();
return '-';
+ case '.':
+ c = nextc();
+ pushback();
+ if (!isdigit(c))
+ return '.';
+ else
+ c = '.'; /* FALL THROUGH */
case '0':
case '1':
case '2':
@@ -1276,7 +1317,6 @@ retry:
case '7':
case '8':
case '9':
- case '.':
/* It's a number */
for (;;) {
int gotnumber = 0;
@@ -1396,7 +1436,7 @@ retry:
low = 0;
high = (sizeof (tokentab) / sizeof (tokentab[0])) - 1;
while (low <= high) {
- int i, c;
+ int i/* , c */;
mid = (low + high) / 2;
c = *tokstart - tokentab[mid].operator[0];
@@ -1408,7 +1448,7 @@ retry:
low = mid + 1;
} else {
if (do_lint) {
- if (tokentab[mid].flags & GAWK)
+ if (tokentab[mid].flags & GAWKX)
warning("%s() is a gawk extension",
tokentab[mid].operator);
if (tokentab[mid].flags & NOT_POSIX)
@@ -1418,7 +1458,7 @@ retry:
warning("%s is not supported in old awk",
tokentab[mid].operator);
}
- if ((strict && (tokentab[mid].flags & GAWK))
+ if ((strict && (tokentab[mid].flags & GAWKX))
|| (do_posix && (tokentab[mid].flags & NOT_POSIX)))
break;
if (tokentab[mid].class == LEX_BUILTIN
@@ -1480,9 +1520,9 @@ NODETYPE op;
* Checks for arg. count and supplies defaults where possible.
*/
static NODE *
-snode(subn, op, index)
+snode(subn, op, idx)
NODETYPE op;
-int index;
+int idx;
NODE *subn;
{
register NODE *r;
@@ -1500,12 +1540,12 @@ NODE *subn;
}
/* check against how many args. are allowed for this builtin */
- args_allowed = tokentab[index].flags & ARGS;
+ args_allowed = tokentab[idx].flags & ARGS;
if (args_allowed && !(args_allowed & A(nexp)))
fatal("%s() cannot have %d argument%c",
- tokentab[index].operator, nexp, nexp == 1 ? ' ' : 's');
+ tokentab[idx].operator, nexp, nexp == 1 ? ' ' : 's');
- r->proc = tokentab[index].ptr;
+ r->proc = tokentab[idx].ptr;
/* special case processing for a few builtins */
if (nexp == 0 && r->proc == do_length) {