185587Sobrien/**************************************************************** 285587SobrienCopyright (C) Lucent Technologies 1997 385587SobrienAll Rights Reserved 485587Sobrien 585587SobrienPermission to use, copy, modify, and distribute this software and 685587Sobrienits documentation for any purpose and without fee is hereby 785587Sobriengranted, provided that the above copyright notice appear in all 885587Sobriencopies and that both that the copyright notice and this 985587Sobrienpermission notice and warranty disclaimer appear in supporting 1085587Sobriendocumentation, and that the name Lucent Technologies or any of 1185587Sobrienits entities not be used in advertising or publicity pertaining 1285587Sobriento distribution of the software without specific, written prior 1385587Sobrienpermission. 1485587Sobrien 1585587SobrienLUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1685587SobrienINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 1785587SobrienIN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY 1885587SobrienSPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1985587SobrienWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 2085587SobrienIN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 2185587SobrienARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 2285587SobrienTHIS SOFTWARE. 2385587Sobrien****************************************************************/ 2485587Sobrien 2585587Sobrien%{ 2685587Sobrien#include <stdio.h> 2785587Sobrien#include <string.h> 2885587Sobrien#include "awk.h" 2985587Sobrien 3085587Sobrienvoid checkdup(Node *list, Cell *item); 3185587Sobrienint yywrap(void) { return(1); } 3285587Sobrien 3385587SobrienNode *beginloc = 0; 3485587SobrienNode *endloc = 0; 3585587Sobrienint infunc = 0; /* = 1 if in arglist or body of func */ 3685587Sobrienint inloop = 0; /* = 1 if in while, for, do */ 3785587Sobrienchar *curfname = 0; /* current function name */ 3885587SobrienNode *arglist = 0; /* list of args for current function */ 3985587Sobrien%} 4085587Sobrien 4185587Sobrien%union { 4285587Sobrien Node *p; 4385587Sobrien Cell *cp; 4485587Sobrien int i; 4585587Sobrien char *s; 4685587Sobrien} 4785587Sobrien 4885587Sobrien%token <i> FIRSTTOKEN /* must be first */ 4985587Sobrien%token <p> PROGRAM PASTAT PASTAT2 XBEGIN XEND 5085587Sobrien%token <i> NL ',' '{' '(' '|' ';' '/' ')' '}' '[' ']' 5185587Sobrien%token <i> ARRAY 5285587Sobrien%token <i> MATCH NOTMATCH MATCHOP 53170331Srafan%token <i> FINAL DOT ALL CCL NCCL CHAR OR STAR QUEST PLUS EMPTYRE 5485587Sobrien%token <i> AND BOR APPEND EQ GE GT LE LT NE IN 5585587Sobrien%token <i> ARG BLTIN BREAK CLOSE CONTINUE DELETE DO EXIT FOR FUNC 5685587Sobrien%token <i> SUB GSUB IF INDEX LSUBSTR MATCHFCN NEXT NEXTFILE 5785587Sobrien%token <i> ADD MINUS MULT DIVIDE MOD 5885587Sobrien%token <i> ASSIGN ASGNOP ADDEQ SUBEQ MULTEQ DIVEQ MODEQ POWEQ 5985587Sobrien%token <i> PRINT PRINTF SPRINTF 6085587Sobrien%token <p> ELSE INTEST CONDEXPR 6185587Sobrien%token <i> POSTINCR PREINCR POSTDECR PREDECR 6285587Sobrien%token <cp> VAR IVAR VARNF CALL NUMBER STRING 6385587Sobrien%token <s> REGEXPR 6485587Sobrien 6585587Sobrien%type <p> pas pattern ppattern plist pplist patlist prarg term re 6685587Sobrien%type <p> pa_pat pa_stat pa_stats 6785587Sobrien%type <s> reg_expr 6885587Sobrien%type <p> simple_stmt opt_simple_stmt stmt stmtlist 6985587Sobrien%type <p> var varname funcname varlist 7085587Sobrien%type <p> for if else while 7185587Sobrien%type <i> do st 7285587Sobrien%type <i> pst opt_pst lbrace rbrace rparen comma nl opt_nl and bor 7385587Sobrien%type <i> subop print 7485587Sobrien 7585587Sobrien%right ASGNOP 7685587Sobrien%right '?' 7785587Sobrien%right ':' 7885587Sobrien%left BOR 7985587Sobrien%left AND 8085587Sobrien%left GETLINE 8185587Sobrien%nonassoc APPEND EQ GE GT LE LT NE MATCHOP IN '|' 8285587Sobrien%left ARG BLTIN BREAK CALL CLOSE CONTINUE DELETE DO EXIT FOR FUNC 8385587Sobrien%left GSUB IF INDEX LSUBSTR MATCHFCN NEXT NUMBER 8485587Sobrien%left PRINT PRINTF RETURN SPLIT SPRINTF STRING SUB SUBSTR 8585587Sobrien%left REGEXPR VAR VARNF IVAR WHILE '(' 8685587Sobrien%left CAT 8785587Sobrien%left '+' '-' 8885587Sobrien%left '*' '/' '%' 8985587Sobrien%left NOT UMINUS 9085587Sobrien%right POWER 9185587Sobrien%right DECR INCR 9285587Sobrien%left INDIRECT 9385587Sobrien%token LASTTOKEN /* must be last */ 9485587Sobrien 9585587Sobrien%% 9685587Sobrien 9785587Sobrienprogram: 9885587Sobrien pas { if (errorflag==0) 9985587Sobrien winner = (Node *)stat3(PROGRAM, beginloc, $1, endloc); } 10085587Sobrien | error { yyclearin; bracecheck(); SYNTAX("bailing out"); } 10185587Sobrien ; 10285587Sobrien 10385587Sobrienand: 10485587Sobrien AND | and NL 10585587Sobrien ; 10685587Sobrien 10785587Sobrienbor: 10885587Sobrien BOR | bor NL 10985587Sobrien ; 11085587Sobrien 11185587Sobriencomma: 11285587Sobrien ',' | comma NL 11385587Sobrien ; 11485587Sobrien 11585587Sobriendo: 11685587Sobrien DO | do NL 11785587Sobrien ; 11885587Sobrien 11985587Sobrienelse: 12085587Sobrien ELSE | else NL 12185587Sobrien ; 12285587Sobrien 12385587Sobrienfor: 12485587Sobrien FOR '(' opt_simple_stmt ';' opt_nl pattern ';' opt_nl opt_simple_stmt rparen {inloop++;} stmt 12585587Sobrien { --inloop; $$ = stat4(FOR, $3, notnull($6), $9, $12); } 12685587Sobrien | FOR '(' opt_simple_stmt ';' ';' opt_nl opt_simple_stmt rparen {inloop++;} stmt 12785587Sobrien { --inloop; $$ = stat4(FOR, $3, NIL, $7, $10); } 12885587Sobrien | FOR '(' varname IN varname rparen {inloop++;} stmt 12985587Sobrien { --inloop; $$ = stat3(IN, $3, makearr($5), $8); } 13085587Sobrien ; 13185587Sobrien 13285587Sobrienfuncname: 13385587Sobrien VAR { setfname($1); } 13485587Sobrien | CALL { setfname($1); } 13585587Sobrien ; 13685587Sobrien 13785587Sobrienif: 13885587Sobrien IF '(' pattern rparen { $$ = notnull($3); } 13985587Sobrien ; 14085587Sobrien 14185587Sobrienlbrace: 14285587Sobrien '{' | lbrace NL 14385587Sobrien ; 14485587Sobrien 14585587Sobriennl: 14685587Sobrien NL | nl NL 14785587Sobrien ; 14885587Sobrien 14985587Sobrienopt_nl: 15085587Sobrien /* empty */ { $$ = 0; } 15185587Sobrien | nl 15285587Sobrien ; 15385587Sobrien 15485587Sobrienopt_pst: 15585587Sobrien /* empty */ { $$ = 0; } 15685587Sobrien | pst 15785587Sobrien ; 15885587Sobrien 15985587Sobrien 16085587Sobrienopt_simple_stmt: 16185587Sobrien /* empty */ { $$ = 0; } 16285587Sobrien | simple_stmt 16385587Sobrien ; 16485587Sobrien 16585587Sobrienpas: 16685587Sobrien opt_pst { $$ = 0; } 16785587Sobrien | opt_pst pa_stats opt_pst { $$ = $2; } 16885587Sobrien ; 16985587Sobrien 17085587Sobrienpa_pat: 17185587Sobrien pattern { $$ = notnull($1); } 17285587Sobrien ; 17385587Sobrien 17485587Sobrienpa_stat: 17585587Sobrien pa_pat { $$ = stat2(PASTAT, $1, stat2(PRINT, rectonode(), NIL)); } 17685587Sobrien | pa_pat lbrace stmtlist '}' { $$ = stat2(PASTAT, $1, $3); } 177224731Sru | pa_pat ',' opt_nl pa_pat { $$ = pa2stat($1, $4, stat2(PRINT, rectonode(), NIL)); } 178224731Sru | pa_pat ',' opt_nl pa_pat lbrace stmtlist '}' { $$ = pa2stat($1, $4, $6); } 17985587Sobrien | lbrace stmtlist '}' { $$ = stat2(PASTAT, NIL, $2); } 18085587Sobrien | XBEGIN lbrace stmtlist '}' 18185587Sobrien { beginloc = linkum(beginloc, $3); $$ = 0; } 18285587Sobrien | XEND lbrace stmtlist '}' 18385587Sobrien { endloc = linkum(endloc, $3); $$ = 0; } 18485587Sobrien | FUNC funcname '(' varlist rparen {infunc++;} lbrace stmtlist '}' 18585587Sobrien { infunc--; curfname=0; defn((Cell *)$2, $4, $8); $$ = 0; } 18685587Sobrien ; 18785587Sobrien 18885587Sobrienpa_stats: 18985587Sobrien pa_stat 19085587Sobrien | pa_stats opt_pst pa_stat { $$ = linkum($1, $3); } 19185587Sobrien ; 19285587Sobrien 19385587Sobrienpatlist: 19485587Sobrien pattern 19585587Sobrien | patlist comma pattern { $$ = linkum($1, $3); } 19685587Sobrien ; 19785587Sobrien 19885587Sobrienppattern: 19985587Sobrien var ASGNOP ppattern { $$ = op2($2, $1, $3); } 20085587Sobrien | ppattern '?' ppattern ':' ppattern %prec '?' 20185587Sobrien { $$ = op3(CONDEXPR, notnull($1), $3, $5); } 20285587Sobrien | ppattern bor ppattern %prec BOR 20385587Sobrien { $$ = op2(BOR, notnull($1), notnull($3)); } 20485587Sobrien | ppattern and ppattern %prec AND 20585587Sobrien { $$ = op2(AND, notnull($1), notnull($3)); } 20685587Sobrien | ppattern MATCHOP reg_expr { $$ = op3($2, NIL, $1, (Node*)makedfa($3, 0)); } 20785587Sobrien | ppattern MATCHOP ppattern 20885587Sobrien { if (constnode($3)) 20985587Sobrien $$ = op3($2, NIL, $1, (Node*)makedfa(strnode($3), 0)); 21085587Sobrien else 21185587Sobrien $$ = op3($2, (Node *)1, $1, $3); } 21285587Sobrien | ppattern IN varname { $$ = op2(INTEST, $1, makearr($3)); } 21385587Sobrien | '(' plist ')' IN varname { $$ = op2(INTEST, $2, makearr($5)); } 21485587Sobrien | ppattern term %prec CAT { $$ = op2(CAT, $1, $2); } 21585587Sobrien | re 21685587Sobrien | term 21785587Sobrien ; 21885587Sobrien 21985587Sobrienpattern: 22085587Sobrien var ASGNOP pattern { $$ = op2($2, $1, $3); } 22185587Sobrien | pattern '?' pattern ':' pattern %prec '?' 22285587Sobrien { $$ = op3(CONDEXPR, notnull($1), $3, $5); } 22385587Sobrien | pattern bor pattern %prec BOR 22485587Sobrien { $$ = op2(BOR, notnull($1), notnull($3)); } 22585587Sobrien | pattern and pattern %prec AND 22685587Sobrien { $$ = op2(AND, notnull($1), notnull($3)); } 22785587Sobrien | pattern EQ pattern { $$ = op2($2, $1, $3); } 22885587Sobrien | pattern GE pattern { $$ = op2($2, $1, $3); } 22985587Sobrien | pattern GT pattern { $$ = op2($2, $1, $3); } 23085587Sobrien | pattern LE pattern { $$ = op2($2, $1, $3); } 23185587Sobrien | pattern LT pattern { $$ = op2($2, $1, $3); } 23285587Sobrien | pattern NE pattern { $$ = op2($2, $1, $3); } 23385587Sobrien | pattern MATCHOP reg_expr { $$ = op3($2, NIL, $1, (Node*)makedfa($3, 0)); } 23485587Sobrien | pattern MATCHOP pattern 23585587Sobrien { if (constnode($3)) 23685587Sobrien $$ = op3($2, NIL, $1, (Node*)makedfa(strnode($3), 0)); 23785587Sobrien else 23885587Sobrien $$ = op3($2, (Node *)1, $1, $3); } 23985587Sobrien | pattern IN varname { $$ = op2(INTEST, $1, makearr($3)); } 24085587Sobrien | '(' plist ')' IN varname { $$ = op2(INTEST, $2, makearr($5)); } 24185587Sobrien | pattern '|' GETLINE var { 24285587Sobrien if (safe) SYNTAX("cmd | getline is unsafe"); 24385587Sobrien else $$ = op3(GETLINE, $4, itonp($2), $1); } 24485587Sobrien | pattern '|' GETLINE { 24585587Sobrien if (safe) SYNTAX("cmd | getline is unsafe"); 24685587Sobrien else $$ = op3(GETLINE, (Node*)0, itonp($2), $1); } 24785587Sobrien | pattern term %prec CAT { $$ = op2(CAT, $1, $2); } 24885587Sobrien | re 24985587Sobrien | term 25085587Sobrien ; 25185587Sobrien 25285587Sobrienplist: 25385587Sobrien pattern comma pattern { $$ = linkum($1, $3); } 25485587Sobrien | plist comma pattern { $$ = linkum($1, $3); } 25585587Sobrien ; 25685587Sobrien 25785587Sobrienpplist: 25885587Sobrien ppattern 25985587Sobrien | pplist comma ppattern { $$ = linkum($1, $3); } 26085587Sobrien ; 26185587Sobrien 26285587Sobrienprarg: 26385587Sobrien /* empty */ { $$ = rectonode(); } 26485587Sobrien | pplist 26585587Sobrien | '(' plist ')' { $$ = $2; } 26685587Sobrien ; 26785587Sobrien 26885587Sobrienprint: 26985587Sobrien PRINT | PRINTF 27085587Sobrien ; 27185587Sobrien 27285587Sobrienpst: 27385587Sobrien NL | ';' | pst NL | pst ';' 27485587Sobrien ; 27585587Sobrien 27685587Sobrienrbrace: 27785587Sobrien '}' | rbrace NL 27885587Sobrien ; 27985587Sobrien 28085587Sobrienre: 28185587Sobrien reg_expr 28285587Sobrien { $$ = op3(MATCH, NIL, rectonode(), (Node*)makedfa($1, 0)); } 28385587Sobrien | NOT re { $$ = op1(NOT, notnull($2)); } 28485587Sobrien ; 28585587Sobrien 28685587Sobrienreg_expr: 28785587Sobrien '/' {startreg();} REGEXPR '/' { $$ = $3; } 28885587Sobrien ; 28985587Sobrien 29085587Sobrienrparen: 29185587Sobrien ')' | rparen NL 29285587Sobrien ; 29385587Sobrien 29485587Sobriensimple_stmt: 29585587Sobrien print prarg '|' term { 29685587Sobrien if (safe) SYNTAX("print | is unsafe"); 29785587Sobrien else $$ = stat3($1, $2, itonp($3), $4); } 29885587Sobrien | print prarg APPEND term { 29985587Sobrien if (safe) SYNTAX("print >> is unsafe"); 30085587Sobrien else $$ = stat3($1, $2, itonp($3), $4); } 30185587Sobrien | print prarg GT term { 30285587Sobrien if (safe) SYNTAX("print > is unsafe"); 30385587Sobrien else $$ = stat3($1, $2, itonp($3), $4); } 30485587Sobrien | print prarg { $$ = stat3($1, $2, NIL, NIL); } 30585587Sobrien | DELETE varname '[' patlist ']' { $$ = stat2(DELETE, makearr($2), $4); } 30685587Sobrien | DELETE varname { $$ = stat2(DELETE, makearr($2), 0); } 30785587Sobrien | pattern { $$ = exptostat($1); } 30885587Sobrien | error { yyclearin; SYNTAX("illegal statement"); } 30985587Sobrien ; 31085587Sobrien 31185587Sobrienst: 31285587Sobrien nl 31385587Sobrien | ';' opt_nl 31485587Sobrien ; 31585587Sobrien 31685587Sobrienstmt: 31785587Sobrien BREAK st { if (!inloop) SYNTAX("break illegal outside of loops"); 31885587Sobrien $$ = stat1(BREAK, NIL); } 31985587Sobrien | CONTINUE st { if (!inloop) SYNTAX("continue illegal outside of loops"); 32085587Sobrien $$ = stat1(CONTINUE, NIL); } 32185587Sobrien | do {inloop++;} stmt {--inloop;} WHILE '(' pattern ')' st 32285587Sobrien { $$ = stat2(DO, $3, notnull($7)); } 32385587Sobrien | EXIT pattern st { $$ = stat1(EXIT, $2); } 32485587Sobrien | EXIT st { $$ = stat1(EXIT, NIL); } 32585587Sobrien | for 32685587Sobrien | if stmt else stmt { $$ = stat3(IF, $1, $2, $4); } 32785587Sobrien | if stmt { $$ = stat3(IF, $1, $2, NIL); } 32885587Sobrien | lbrace stmtlist rbrace { $$ = $2; } 32985587Sobrien | NEXT st { if (infunc) 33085587Sobrien SYNTAX("next is illegal inside a function"); 33185587Sobrien $$ = stat1(NEXT, NIL); } 33285587Sobrien | NEXTFILE st { if (infunc) 33385587Sobrien SYNTAX("nextfile is illegal inside a function"); 33485587Sobrien $$ = stat1(NEXTFILE, NIL); } 33585587Sobrien | RETURN pattern st { $$ = stat1(RETURN, $2); } 33685587Sobrien | RETURN st { $$ = stat1(RETURN, NIL); } 33785587Sobrien | simple_stmt st 33885587Sobrien | while {inloop++;} stmt { --inloop; $$ = stat2(WHILE, $1, $3); } 33985587Sobrien | ';' opt_nl { $$ = 0; } 34085587Sobrien ; 34185587Sobrien 34285587Sobrienstmtlist: 34385587Sobrien stmt 34485587Sobrien | stmtlist stmt { $$ = linkum($1, $2); } 34585587Sobrien ; 34685587Sobrien 34785587Sobriensubop: 34885587Sobrien SUB | GSUB 34985587Sobrien ; 35085587Sobrien 35185587Sobrienterm: 35285587Sobrien term '/' ASGNOP term { $$ = op2(DIVEQ, $1, $4); } 35385587Sobrien | term '+' term { $$ = op2(ADD, $1, $3); } 35485587Sobrien | term '-' term { $$ = op2(MINUS, $1, $3); } 35585587Sobrien | term '*' term { $$ = op2(MULT, $1, $3); } 35685587Sobrien | term '/' term { $$ = op2(DIVIDE, $1, $3); } 35785587Sobrien | term '%' term { $$ = op2(MOD, $1, $3); } 35885587Sobrien | term POWER term { $$ = op2(POWER, $1, $3); } 35985587Sobrien | '-' term %prec UMINUS { $$ = op1(UMINUS, $2); } 36085587Sobrien | '+' term %prec UMINUS { $$ = $2; } 36185587Sobrien | NOT term %prec UMINUS { $$ = op1(NOT, notnull($2)); } 36285587Sobrien | BLTIN '(' ')' { $$ = op2(BLTIN, itonp($1), rectonode()); } 36385587Sobrien | BLTIN '(' patlist ')' { $$ = op2(BLTIN, itonp($1), $3); } 36485587Sobrien | BLTIN { $$ = op2(BLTIN, itonp($1), rectonode()); } 36585587Sobrien | CALL '(' ')' { $$ = op2(CALL, celltonode($1,CVAR), NIL); } 36685587Sobrien | CALL '(' patlist ')' { $$ = op2(CALL, celltonode($1,CVAR), $3); } 36785587Sobrien | CLOSE term { $$ = op1(CLOSE, $2); } 36885587Sobrien | DECR var { $$ = op1(PREDECR, $2); } 36985587Sobrien | INCR var { $$ = op1(PREINCR, $2); } 37085587Sobrien | var DECR { $$ = op1(POSTDECR, $1); } 37185587Sobrien | var INCR { $$ = op1(POSTINCR, $1); } 37285587Sobrien | GETLINE var LT term { $$ = op3(GETLINE, $2, itonp($3), $4); } 37385587Sobrien | GETLINE LT term { $$ = op3(GETLINE, NIL, itonp($2), $3); } 37485587Sobrien | GETLINE var { $$ = op3(GETLINE, $2, NIL, NIL); } 37585587Sobrien | GETLINE { $$ = op3(GETLINE, NIL, NIL, NIL); } 37685587Sobrien | INDEX '(' pattern comma pattern ')' 37785587Sobrien { $$ = op2(INDEX, $3, $5); } 37885587Sobrien | INDEX '(' pattern comma reg_expr ')' 37985587Sobrien { SYNTAX("index() doesn't permit regular expressions"); 38085587Sobrien $$ = op2(INDEX, $3, (Node*)$5); } 38185587Sobrien | '(' pattern ')' { $$ = $2; } 38285587Sobrien | MATCHFCN '(' pattern comma reg_expr ')' 38385587Sobrien { $$ = op3(MATCHFCN, NIL, $3, (Node*)makedfa($5, 1)); } 38485587Sobrien | MATCHFCN '(' pattern comma pattern ')' 38585587Sobrien { if (constnode($5)) 38685587Sobrien $$ = op3(MATCHFCN, NIL, $3, (Node*)makedfa(strnode($5), 1)); 38785587Sobrien else 38885587Sobrien $$ = op3(MATCHFCN, (Node *)1, $3, $5); } 38985587Sobrien | NUMBER { $$ = celltonode($1, CCON); } 39085587Sobrien | SPLIT '(' pattern comma varname comma pattern ')' /* string */ 39185587Sobrien { $$ = op4(SPLIT, $3, makearr($5), $7, (Node*)STRING); } 39285587Sobrien | SPLIT '(' pattern comma varname comma reg_expr ')' /* const /regexp/ */ 39385587Sobrien { $$ = op4(SPLIT, $3, makearr($5), (Node*)makedfa($7, 1), (Node *)REGEXPR); } 39485587Sobrien | SPLIT '(' pattern comma varname ')' 39585587Sobrien { $$ = op4(SPLIT, $3, makearr($5), NIL, (Node*)STRING); } /* default */ 39685587Sobrien | SPRINTF '(' patlist ')' { $$ = op1($1, $3); } 39785587Sobrien | STRING { $$ = celltonode($1, CCON); } 39885587Sobrien | subop '(' reg_expr comma pattern ')' 39985587Sobrien { $$ = op4($1, NIL, (Node*)makedfa($3, 1), $5, rectonode()); } 40085587Sobrien | subop '(' pattern comma pattern ')' 40185587Sobrien { if (constnode($3)) 40285587Sobrien $$ = op4($1, NIL, (Node*)makedfa(strnode($3), 1), $5, rectonode()); 40385587Sobrien else 40485587Sobrien $$ = op4($1, (Node *)1, $3, $5, rectonode()); } 40585587Sobrien | subop '(' reg_expr comma pattern comma var ')' 40685587Sobrien { $$ = op4($1, NIL, (Node*)makedfa($3, 1), $5, $7); } 40785587Sobrien | subop '(' pattern comma pattern comma var ')' 40885587Sobrien { if (constnode($3)) 40985587Sobrien $$ = op4($1, NIL, (Node*)makedfa(strnode($3), 1), $5, $7); 41085587Sobrien else 41185587Sobrien $$ = op4($1, (Node *)1, $3, $5, $7); } 41285587Sobrien | SUBSTR '(' pattern comma pattern comma pattern ')' 41385587Sobrien { $$ = op3(SUBSTR, $3, $5, $7); } 41485587Sobrien | SUBSTR '(' pattern comma pattern ')' 41585587Sobrien { $$ = op3(SUBSTR, $3, $5, NIL); } 41685587Sobrien | var 41785587Sobrien ; 41885587Sobrien 41985587Sobrienvar: 42085587Sobrien varname 42185587Sobrien | varname '[' patlist ']' { $$ = op2(ARRAY, makearr($1), $3); } 42285587Sobrien | IVAR { $$ = op1(INDIRECT, celltonode($1, CVAR)); } 42385587Sobrien | INDIRECT term { $$ = op1(INDIRECT, $2); } 42485587Sobrien ; 42585587Sobrien 42685587Sobrienvarlist: 42785587Sobrien /* nothing */ { arglist = $$ = 0; } 42885587Sobrien | VAR { arglist = $$ = celltonode($1,CVAR); } 42985587Sobrien | varlist comma VAR { 43085587Sobrien checkdup($1, $3); 43185587Sobrien arglist = $$ = linkum($1,celltonode($3,CVAR)); } 43285587Sobrien ; 43385587Sobrien 43485587Sobrienvarname: 43585587Sobrien VAR { $$ = celltonode($1, CVAR); } 43685587Sobrien | ARG { $$ = op1(ARG, itonp($1)); } 43785587Sobrien | VARNF { $$ = op1(VARNF, (Node *) $1); } 43885587Sobrien ; 43985587Sobrien 44085587Sobrien 44185587Sobrienwhile: 44285587Sobrien WHILE '(' pattern rparen { $$ = notnull($3); } 44385587Sobrien ; 44485587Sobrien 44585587Sobrien%% 44685587Sobrien 44785587Sobrienvoid setfname(Cell *p) 44885587Sobrien{ 44985587Sobrien if (isarr(p)) 45085587Sobrien SYNTAX("%s is an array, not a function", p->nval); 45185587Sobrien else if (isfcn(p)) 45285587Sobrien SYNTAX("you can't define function %s more than once", p->nval); 45385587Sobrien curfname = p->nval; 45485587Sobrien} 45585587Sobrien 45685587Sobrienint constnode(Node *p) 45785587Sobrien{ 45885587Sobrien return isvalue(p) && ((Cell *) (p->narg[0]))->csub == CCON; 45985587Sobrien} 46085587Sobrien 46185587Sobrienchar *strnode(Node *p) 46285587Sobrien{ 46385587Sobrien return ((Cell *)(p->narg[0]))->sval; 46485587Sobrien} 46585587Sobrien 46685587SobrienNode *notnull(Node *n) 46785587Sobrien{ 46885587Sobrien switch (n->nobj) { 46985587Sobrien case LE: case LT: case EQ: case NE: case GT: case GE: 47085587Sobrien case BOR: case AND: case NOT: 47185587Sobrien return n; 47285587Sobrien default: 47385587Sobrien return op2(NE, n, nullnode); 47485587Sobrien } 47585587Sobrien} 47685587Sobrien 47785587Sobrienvoid checkdup(Node *vl, Cell *cp) /* check if name already in list */ 47885587Sobrien{ 47985587Sobrien char *s = cp->nval; 48085587Sobrien for ( ; vl; vl = vl->nnext) { 48185587Sobrien if (strcmp(s, ((Cell *)(vl->narg[0]))->nval) == 0) { 48285587Sobrien SYNTAX("duplicate argument %s", s); 48385587Sobrien break; 48485587Sobrien } 48585587Sobrien } 48685587Sobrien} 487