summaryrefslogtreecommitdiff
path: root/usr/src/cmd/awk/awk.g.y
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/awk/awk.g.y')
-rw-r--r--usr/src/cmd/awk/awk.g.y109
1 files changed, 72 insertions, 37 deletions
diff --git a/usr/src/cmd/awk/awk.g.y b/usr/src/cmd/awk/awk.g.y
index 872f452a12..3b5efb3d7d 100644
--- a/usr/src/cmd/awk/awk.g.y
+++ b/usr/src/cmd/awk/awk.g.y
@@ -55,11 +55,14 @@
%{
#include "awk.h"
+
+void checkdup(Node *list, Cell *item);
int yywrap(void) { return(1); }
Node *beginloc = NULL;
Node *endloc = NULL;
-int infunc = 0; /* = 1 if in arglist or body of func */
+int infunc = 0; /* = 1 if in arglist or body of func */
+int inloop = 0; /* = 1 if in while, for, do */
char *curfname = NULL; /* current function name */
Node *arglist = NULL; /* list of args for current function */
static void setfname(Cell *);
@@ -80,10 +83,10 @@ static Node *notnull(Node *);
%token <i> NL ',' '{' '(' '|' ';' '/' ')' '}' '[' ']'
%token <i> ARRAY
%token <i> MATCH NOTMATCH MATCHOP
-%token <i> FINAL DOT ALL CCL NCCL CHAR OR STAR QUEST PLUS
+%token <i> FINAL DOT ALL CCL NCCL CHAR OR STAR QUEST PLUS EMPTYRE
%token <i> AND BOR APPEND EQ GE GT LE LT NE IN
%token <i> ARG BLTIN BREAK CLOSE CONTINUE DELETE DO EXIT FOR FUNC
-%token <i> SUB GSUB IF INDEX LSUBSTR MATCHFCN NEXT
+%token <i> SUB GSUB IF INDEX LSUBSTR MATCHFCN NEXT NEXTFILE
%token <i> ADD MINUS MULT DIVIDE MOD
%token <i> ASSIGN ASGNOP ADDEQ SUBEQ MULTEQ DIVEQ MODEQ POWEQ
%token <i> PRINT PRINTF SPRINTF
@@ -92,13 +95,14 @@ static Node *notnull(Node *);
%token <cp> VAR IVAR VARNF CALL NUMBER STRING
%token <s> REGEXPR
-%type <p> pas pattern ppattern plist pplist patlist prarg term
+%type <p> pas pattern ppattern plist pplist patlist prarg term re
%type <p> pa_pat pa_stat pa_stats
%type <s> reg_expr
%type <p> simple_stmt opt_simple_stmt stmt stmtlist
%type <p> var varname funcname varlist
-%type <p> for if while
-%type <i> pst opt_pst lbrace rparen comma nl opt_nl and bor
+%type <p> for if else while
+%type <i> do st
+%type <i> pst opt_pst lbrace rbrace rparen comma nl opt_nl and bor
%type <i> subop print
%right ASGNOP
@@ -115,7 +119,7 @@ static Node *notnull(Node *);
%left CAT
%left '+' '-'
%left '*' '/' '%'
-%left NOT UMINUS
+%left NOT UMINUS UPLUS
%right POWER
%right DECR INCR
%left INDIRECT
@@ -150,12 +154,12 @@ else:
;
for:
- FOR '(' opt_simple_stmt ';' pattern ';' opt_simple_stmt rparen stmt
- { $$ = stat4(FOR, $3, notnull($5), $7, $9); }
- | FOR '(' opt_simple_stmt ';' ';' opt_simple_stmt rparen stmt
- { $$ = stat4(FOR, $3, NIL, $6, $8); }
- | FOR '(' varname IN varname rparen stmt
- { $$ = stat3(IN, $3, makearr($5), $7); }
+ FOR '(' opt_simple_stmt ';' opt_nl pattern ';' opt_nl opt_simple_stmt rparen {inloop++;} stmt
+ { --inloop; $$ = stat4(FOR, $3, notnull($6), $9, $12); }
+ | FOR '(' opt_simple_stmt ';' ';' opt_nl opt_simple_stmt rparen {inloop++;} stmt
+ { --inloop; $$ = stat4(FOR, $3, NIL, $7, $10); }
+ | FOR '(' varname IN varname rparen {inloop++;} stmt
+ { --inloop; $$ = stat3(IN, $3, makearr($5), $8); }
;
funcname:
@@ -203,8 +207,8 @@ pa_pat:
pa_stat:
pa_pat { $$ = stat2(PASTAT, $1, stat2(PRINT, rectonode(), NIL)); }
| pa_pat lbrace stmtlist '}' { $$ = stat2(PASTAT, $1, $3); }
- | pa_pat ',' pa_pat { $$ = pa2stat($1, $3, stat2(PRINT, rectonode(), NIL)); }
- | pa_pat ',' pa_pat lbrace stmtlist '}' { $$ = pa2stat($1, $3, $5); }
+ | pa_pat ',' opt_nl pa_pat { $$ = pa2stat($1, $4, stat2(PRINT, rectonode(), NIL)); }
+ | pa_pat ',' opt_nl pa_pat lbrace stmtlist '}' { $$ = pa2stat($1, $4, $6); }
| lbrace stmtlist '}' { $$ = stat2(PASTAT, NIL, $2); }
| XBEGIN lbrace stmtlist '}'
{ beginloc = linkum(beginloc, $3); $$ = 0; }
@@ -232,8 +236,6 @@ ppattern:
{ $$ = op2(BOR, notnull($1), notnull($3)); }
| ppattern and ppattern %prec AND
{ $$ = op2(AND, notnull($1), notnull($3)); }
- | NOT ppattern
- { $$ = op1(NOT, notnull($2)); }
| ppattern MATCHOP reg_expr { $$ = op3($2, NIL, $1, (Node*)makedfa($3, 0)); }
| ppattern MATCHOP ppattern
{ if (constnode($3))
@@ -243,8 +245,7 @@ ppattern:
| ppattern IN varname { $$ = op2(INTEST, $1, makearr($3)); }
| '(' plist ')' IN varname { $$ = op2(INTEST, $2, makearr($5)); }
| ppattern term %prec CAT { $$ = op2(CAT, $1, $2); }
- | reg_expr
- { $$ = op3(MATCH, NIL, rectonode(), (Node*)makedfa($1, 0)); }
+ | re
| term
;
@@ -256,8 +257,6 @@ pattern:
{ $$ = op2(BOR, notnull($1), notnull($3)); }
| pattern and pattern %prec AND
{ $$ = op2(AND, notnull($1), notnull($3)); }
- | NOT pattern
- { $$ = op1(NOT, op2(NE,$2,celltonode(lookup("$zero&null",symtab),CCON))); }
| pattern EQ pattern { $$ = op2($2, $1, $3); }
| pattern GE pattern { $$ = op2($2, $1, $3); }
| pattern GT pattern { $$ = op2($2, $1, $3); }
@@ -272,11 +271,14 @@ pattern:
$$ = op3($2, (Node *)1, $1, $3); }
| pattern IN varname { $$ = op2(INTEST, $1, makearr($3)); }
| '(' plist ')' IN varname { $$ = op2(INTEST, $2, makearr($5)); }
- | pattern '|' GETLINE var { $$ = op3(GETLINE, $4, (Node*)$2, $1); }
- | pattern '|' GETLINE { $$ = op3(GETLINE, (Node*)0, (Node*)$2, $1); }
+ | pattern '|' GETLINE var {
+ if (safe) SYNTAX("cmd | getline is unsafe");
+ else $$ = op3(GETLINE, $4, itonp($2), $1); }
+ | pattern '|' GETLINE {
+ if (safe) SYNTAX("cmd | getline is unsafe");
+ else $$ = op3(GETLINE, (Node*)0, itonp($2), $1); }
| pattern term %prec CAT { $$ = op2(CAT, $1, $2); }
- | reg_expr
- { $$ = op3(MATCH, NIL, rectonode(), (Node*)makedfa($1, 0)); }
+ | re
| term
;
@@ -308,6 +310,12 @@ rbrace:
'}' | rbrace NL
;
+re:
+ reg_expr
+ { $$ = op3(MATCH, NIL, rectonode(), (Node*)makedfa($1, 0)); }
+ | NOT re { $$ = op1(NOT, notnull($2)); }
+ ;
+
reg_expr:
'/' {startreg();} REGEXPR '/' { $$ = $3; }
;
@@ -317,12 +325,18 @@ rparen:
;
simple_stmt:
- print prarg '|' term { $$ = stat3($1, $2, (Node *) $3, $4); }
- | print prarg APPEND term { $$ = stat3($1, $2, (Node *) $3, $4); }
- | print prarg GT term { $$ = stat3($1, $2, (Node *) $3, $4); }
+ print prarg '|' term {
+ if (safe) SYNTAX("print | is unsafe");
+ else $$ = stat3($1, $2, itonp($3), $4); }
+ | print prarg APPEND term {
+ if (safe) SYNTAX("print >> is unsafe");
+ else $$ = stat3($1, $2, itonp($3), $4); }
+ | print prarg GT term {
+ if (safe) SYNTAX("print > is unsafe");
+ else $$ = stat3($1, $2, itonp($3), $4); }
| print prarg { $$ = stat3($1, $2, NIL, NIL); }
| DELETE varname '[' patlist ']' { $$ = stat2(DELETE, makearr($2), $4); }
- | DELETE varname { yyclearin; SYNTAX("you can only delete array[element]"); $$ = stat1(DELETE, $2); }
+ | DELETE varname { $$ = stat2(DELETE, makearr($2), 0); }
| pattern { $$ = exptostat($1); }
| error { yyclearin; SYNTAX("illegal statement"); }
;
@@ -333,11 +347,12 @@ st:
;
stmt:
- BREAK st { $$ = stat1(BREAK, NIL); }
- | CLOSE pattern st { $$ = stat1(CLOSE, $2); }
- | CONTINUE st { $$ = stat1(CONTINUE, NIL); }
- | do stmt WHILE '(' pattern ')' st
- { $$ = stat2(DO, $2, notnull($5)); }
+ BREAK st { if (!inloop) SYNTAX("break illegal outside of loops");
+ $$ = stat1(BREAK, NIL); }
+ | CONTINUE st { if (!inloop) SYNTAX("continue illegal outside of loops");
+ $$ = stat1(CONTINUE, NIL); }
+ | do {inloop++;} stmt {--inloop;} WHILE '(' pattern ')' st
+ { $$ = stat2(DO, $3, notnull($7)); }
| EXIT pattern st { $$ = stat1(EXIT, $2); }
| EXIT st { $$ = stat1(EXIT, NIL); }
| for
@@ -347,10 +362,13 @@ stmt:
| NEXT st { if (infunc)
SYNTAX("next is illegal inside a function");
$$ = stat1(NEXT, NIL); }
+ | NEXTFILE st { if (infunc)
+ SYNTAX("nextfile is illegal inside a function");
+ $$ = stat1(NEXTFILE, NIL); }
| RETURN pattern st { $$ = stat1(RETURN, $2); }
| RETURN st { $$ = stat1(RETURN, NIL); }
| simple_stmt st
- | while stmt { $$ = stat2(WHILE, $1, $2); }
+ | while {inloop++;} stmt { --inloop; $$ = stat2(WHILE, $1, $3); }
| ';' opt_nl { $$ = 0; }
;
@@ -372,12 +390,14 @@ term:
| term '%' term { $$ = op2(MOD, $1, $3); }
| term POWER term { $$ = op2(POWER, $1, $3); }
| '-' term %prec UMINUS { $$ = op1(UMINUS, $2); }
- | '+' term %prec UMINUS { $$ = $2; }
+ | '+' term %prec UMINUS { $$ = op1(UPLUS, $2); }
+ | NOT term %prec UMINUS { $$ = op1(NOT, notnull($2)); }
| BLTIN '(' ')' { $$ = op2(BLTIN, itonp($1), rectonode()); }
| BLTIN '(' patlist ')' { $$ = op2(BLTIN, itonp($1), $3); }
| BLTIN { $$ = op2(BLTIN, itonp($1), rectonode()); }
| CALL '(' ')' { $$ = op2(CALL, celltonode($1,CVAR), NIL); }
| CALL '(' patlist ')' { $$ = op2(CALL, celltonode($1,CVAR), $3); }
+ | CLOSE term { $$ = op1(CLOSE, $2); }
| DECR var { $$ = op1(PREDECR, $2); }
| INCR var { $$ = op1(PREINCR, $2); }
| var DECR { $$ = op1(POSTDECR, $1); }
@@ -439,7 +459,9 @@ var:
varlist:
/* nothing */ { arglist = $$ = 0; }
| VAR { arglist = $$ = celltonode($1,CVAR); }
- | varlist comma VAR { arglist = $$ = linkum($1,celltonode($3,CVAR)); }
+ | varlist comma VAR {
+ checkdup($1, $3);
+ arglist = $$ = linkum($1,celltonode($3,CVAR)); }
;
varname:
@@ -463,6 +485,7 @@ setfname(Cell *p)
else if (isfcn(p))
SYNTAX("you can't define function %s more than once", p->nval);
curfname = p->nval;
+ p->tval |= FCN;
}
static int
@@ -488,3 +511,15 @@ notnull(Node *n)
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;
+ }
+ }
+}