Annotation of rpl/rplawk/awkgram.y, revision 1.1

1.1     ! bertrand    1: /****************************************************************
        !             2: Copyright (C) Lucent Technologies 1997
        !             3: All Rights Reserved
        !             4: 
        !             5: Permission to use, copy, modify, and distribute this software and
        !             6: its documentation for any purpose and without fee is hereby
        !             7: granted, provided that the above copyright notice appear in all
        !             8: copies and that both that the copyright notice and this
        !             9: permission notice and warranty disclaimer appear in supporting
        !            10: documentation, and that the name Lucent Technologies or any of
        !            11: its entities not be used in advertising or publicity pertaining
        !            12: to distribution of the software without specific, written prior
        !            13: permission.
        !            14: 
        !            15: LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
        !            16: INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
        !            17: IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
        !            18: SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            19: WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
        !            20: IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
        !            21: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
        !            22: THIS SOFTWARE.
        !            23: ****************************************************************/
        !            24: 
        !            25: %{
        !            26: #include <stdio.h>
        !            27: #include <string.h>
        !            28: #include "awk.h"
        !            29: 
        !            30: void checkdup(Node *list, Cell *item);
        !            31: int yywrap(void) { return(1); }
        !            32: 
        !            33: Node   *beginloc = 0;
        !            34: Node   *endloc = 0;
        !            35: int    infunc  = 0;    /* = 1 if in arglist or body of func */
        !            36: int    inloop  = 0;    /* = 1 if in while, for, do */
        !            37: char   *curfname = 0;  /* current function name */
        !            38: Node   *arglist = 0;   /* list of args for current function */
        !            39: %}
        !            40: 
        !            41: %union {
        !            42:    Node    *p;
        !            43:    Cell    *cp;
        !            44:    int i;
        !            45:    char    *s;
        !            46: }
        !            47: 
        !            48: %token <i> FIRSTTOKEN  /* must be first */
        !            49: %token <p> PROGRAM PASTAT PASTAT2 XBEGIN XEND
        !            50: %token <i> NL ',' '{' '(' '|' ';' '/' ')' '}' '[' ']'
        !            51: %token <i> ARRAY
        !            52: %token <i> MATCH NOTMATCH MATCHOP
        !            53: %token <i> FINAL DOT ALL CCL NCCL CHAR OR STAR QUEST PLUS EMPTYRE
        !            54: %token <i> AND BOR APPEND EQ GE GT LE LT NE IN
        !            55: %token <i> ARG BLTIN BREAK CLOSE CONTINUE DELETE DO EXIT FOR FUNC 
        !            56: %token <i> SUB GSUB IF INDEX LSUBSTR MATCHFCN NEXT NEXTFILE
        !            57: %token <i> ADD MINUS MULT DIVIDE MOD
        !            58: %token <i> ASSIGN ASGNOP ADDEQ SUBEQ MULTEQ DIVEQ MODEQ POWEQ
        !            59: %token <i> PRINT PRINTF SPRINTF
        !            60: %token <p> ELSE INTEST CONDEXPR
        !            61: %token <i> POSTINCR PREINCR POSTDECR PREDECR
        !            62: %token <cp>    VAR IVAR VARNF CALL NUMBER STRING
        !            63: %token <s> REGEXPR
        !            64: 
        !            65: %type  <p> pas pattern ppattern plist pplist patlist prarg term re
        !            66: %type  <p> pa_pat pa_stat pa_stats
        !            67: %type  <s> reg_expr
        !            68: %type  <p> simple_stmt opt_simple_stmt stmt stmtlist
        !            69: %type  <p> var varname funcname varlist
        !            70: %type  <p> for if else while
        !            71: %type  <i> do st
        !            72: %type  <i> pst opt_pst lbrace rbrace rparen comma nl opt_nl and bor
        !            73: %type  <i> subop print
        !            74: 
        !            75: %right ASGNOP
        !            76: %right '?'
        !            77: %right ':'
        !            78: %left  BOR
        !            79: %left  AND
        !            80: %left  GETLINE
        !            81: %nonassoc APPEND EQ GE GT LE LT NE MATCHOP IN '|'
        !            82: %left  ARG BLTIN BREAK CALL CLOSE CONTINUE DELETE DO EXIT FOR FUNC 
        !            83: %left  GSUB IF INDEX LSUBSTR MATCHFCN NEXT NUMBER
        !            84: %left  PRINT PRINTF RETURN SPLIT SPRINTF STRING SUB SUBSTR
        !            85: %left  REGEXPR VAR VARNF IVAR WHILE '('
        !            86: %left  CAT
        !            87: %left  '+' '-'
        !            88: %left  '*' '/' '%'
        !            89: %left  NOT UMINUS
        !            90: %right POWER
        !            91: %right DECR INCR
        !            92: %left  INDIRECT
        !            93: %token LASTTOKEN   /* must be last */
        !            94: 
        !            95: %%
        !            96: 
        !            97: program:
        !            98:      pas   { if (errorflag==0)
        !            99:            winner = (Node *)stat3(PROGRAM, beginloc, $1, endloc); }
        !           100:    | error { yyclearin; bracecheck(); SYNTAX("bailing out"); }
        !           101:    ;
        !           102: 
        !           103: and:
        !           104:      AND | and NL
        !           105:    ;
        !           106: 
        !           107: bor:
        !           108:      BOR | bor NL
        !           109:    ;
        !           110: 
        !           111: comma:
        !           112:      ',' | comma NL
        !           113:    ;
        !           114: 
        !           115: do:
        !           116:      DO | do NL
        !           117:    ;
        !           118: 
        !           119: else:
        !           120:      ELSE | else NL
        !           121:    ;
        !           122: 
        !           123: for:
        !           124:      FOR '(' opt_simple_stmt ';' opt_nl pattern ';' opt_nl opt_simple_stmt rparen {inloop++;} stmt
        !           125:        { --inloop; $$ = stat4(FOR, $3, notnull($6), $9, $12); }
        !           126:    | FOR '(' opt_simple_stmt ';'  ';' opt_nl opt_simple_stmt rparen {inloop++;} stmt
        !           127:        { --inloop; $$ = stat4(FOR, $3, NIL, $7, $10); }
        !           128:    | FOR '(' varname IN varname rparen {inloop++;} stmt
        !           129:        { --inloop; $$ = stat3(IN, $3, makearr($5), $8); }
        !           130:    ;
        !           131: 
        !           132: funcname:
        !           133:      VAR   { setfname($1); }
        !           134:    | CALL  { setfname($1); }
        !           135:    ;
        !           136: 
        !           137: if:
        !           138:      IF '(' pattern rparen     { $$ = notnull($3); }
        !           139:    ;
        !           140: 
        !           141: lbrace:
        !           142:      '{' | lbrace NL
        !           143:    ;
        !           144: 
        !           145: nl:
        !           146:      NL | nl NL
        !           147:    ;
        !           148: 
        !           149: opt_nl:
        !           150:      /* empty */   { $$ = 0; }
        !           151:    | nl
        !           152:    ;
        !           153: 
        !           154: opt_pst:
        !           155:      /* empty */   { $$ = 0; }
        !           156:    | pst
        !           157:    ;
        !           158: 
        !           159: 
        !           160: opt_simple_stmt:
        !           161:      /* empty */           { $$ = 0; }
        !           162:    | simple_stmt
        !           163:    ;
        !           164: 
        !           165: pas:
        !           166:      opt_pst           { $$ = 0; }
        !           167:    | opt_pst pa_stats opt_pst  { $$ = $2; }
        !           168:    ;
        !           169: 
        !           170: pa_pat:
        !           171:      pattern   { $$ = notnull($1); }
        !           172:    ;
        !           173: 
        !           174: pa_stat:
        !           175:      pa_pat            { $$ = stat2(PASTAT, $1, stat2(PRINT, rectonode(), NIL)); }
        !           176:    | pa_pat lbrace stmtlist '}'    { $$ = stat2(PASTAT, $1, $3); }
        !           177:    | pa_pat ',' pa_pat     { $$ = pa2stat($1, $3, stat2(PRINT, rectonode(), NIL)); }
        !           178:    | pa_pat ',' pa_pat lbrace stmtlist '}' { $$ = pa2stat($1, $3, $5); }
        !           179:    | lbrace stmtlist '}'       { $$ = stat2(PASTAT, NIL, $2); }
        !           180:    | XBEGIN lbrace stmtlist '}'
        !           181:        { beginloc = linkum(beginloc, $3); $$ = 0; }
        !           182:    | XEND lbrace stmtlist '}'
        !           183:        { endloc = linkum(endloc, $3); $$ = 0; }
        !           184:    | FUNC funcname '(' varlist rparen {infunc++;} lbrace stmtlist '}'
        !           185:        { infunc--; curfname=0; defn((Cell *)$2, $4, $8); $$ = 0; }
        !           186:    ;
        !           187: 
        !           188: pa_stats:
        !           189:      pa_stat
        !           190:    | pa_stats opt_pst pa_stat  { $$ = linkum($1, $3); }
        !           191:    ;
        !           192: 
        !           193: patlist:
        !           194:      pattern
        !           195:    | patlist comma pattern     { $$ = linkum($1, $3); }
        !           196:    ;
        !           197: 
        !           198: ppattern:
        !           199:      var ASGNOP ppattern       { $$ = op2($2, $1, $3); }
        !           200:    | ppattern '?' ppattern ':' ppattern %prec '?'
        !           201:        { $$ = op3(CONDEXPR, notnull($1), $3, $5); }
        !           202:    | ppattern bor ppattern %prec BOR
        !           203:        { $$ = op2(BOR, notnull($1), notnull($3)); }
        !           204:    | ppattern and ppattern %prec AND
        !           205:        { $$ = op2(AND, notnull($1), notnull($3)); }
        !           206:    | ppattern MATCHOP reg_expr { $$ = op3($2, NIL, $1, (Node*)makedfa($3, 0)); }
        !           207:    | ppattern MATCHOP ppattern
        !           208:        { if (constnode($3))
        !           209:            $$ = op3($2, NIL, $1, (Node*)makedfa(strnode($3), 0));
        !           210:          else
        !           211:            $$ = op3($2, (Node *)1, $1, $3); }
        !           212:    | ppattern IN varname       { $$ = op2(INTEST, $1, makearr($3)); }
        !           213:    | '(' plist ')' IN varname  { $$ = op2(INTEST, $2, makearr($5)); }
        !           214:    | ppattern term %prec CAT   { $$ = op2(CAT, $1, $2); }
        !           215:    | re
        !           216:    | term
        !           217:    ;
        !           218: 
        !           219: pattern:
        !           220:      var ASGNOP pattern        { $$ = op2($2, $1, $3); }
        !           221:    | pattern '?' pattern ':' pattern %prec '?'
        !           222:        { $$ = op3(CONDEXPR, notnull($1), $3, $5); }
        !           223:    | pattern bor pattern %prec BOR
        !           224:        { $$ = op2(BOR, notnull($1), notnull($3)); }
        !           225:    | pattern and pattern %prec AND
        !           226:        { $$ = op2(AND, notnull($1), notnull($3)); }
        !           227:    | pattern EQ pattern        { $$ = op2($2, $1, $3); }
        !           228:    | pattern GE pattern        { $$ = op2($2, $1, $3); }
        !           229:    | pattern GT pattern        { $$ = op2($2, $1, $3); }
        !           230:    | pattern LE pattern        { $$ = op2($2, $1, $3); }
        !           231:    | pattern LT pattern        { $$ = op2($2, $1, $3); }
        !           232:    | pattern NE pattern        { $$ = op2($2, $1, $3); }
        !           233:    | pattern MATCHOP reg_expr  { $$ = op3($2, NIL, $1, (Node*)makedfa($3, 0)); }
        !           234:    | pattern MATCHOP pattern
        !           235:        { if (constnode($3))
        !           236:            $$ = op3($2, NIL, $1, (Node*)makedfa(strnode($3), 0));
        !           237:          else
        !           238:            $$ = op3($2, (Node *)1, $1, $3); }
        !           239:    | pattern IN varname        { $$ = op2(INTEST, $1, makearr($3)); }
        !           240:    | '(' plist ')' IN varname  { $$ = op2(INTEST, $2, makearr($5)); }
        !           241:    | pattern '|' GETLINE var   { 
        !           242:            if (safe) SYNTAX("cmd | getline is unsafe");
        !           243:            else $$ = op3(GETLINE, $4, itonp($2), $1); }
        !           244:    | pattern '|' GETLINE       { 
        !           245:            if (safe) SYNTAX("cmd | getline is unsafe");
        !           246:            else $$ = op3(GETLINE, (Node*)0, itonp($2), $1); }
        !           247:    | pattern term %prec CAT    { $$ = op2(CAT, $1, $2); }
        !           248:    | re
        !           249:    | term
        !           250:    ;
        !           251: 
        !           252: plist:
        !           253:      pattern comma pattern     { $$ = linkum($1, $3); }
        !           254:    | plist comma pattern       { $$ = linkum($1, $3); }
        !           255:    ;
        !           256: 
        !           257: pplist:
        !           258:      ppattern
        !           259:    | pplist comma ppattern     { $$ = linkum($1, $3); }
        !           260:    ;
        !           261: 
        !           262: prarg:
        !           263:      /* empty */           { $$ = rectonode(); }
        !           264:    | pplist
        !           265:    | '(' plist ')'         { $$ = $2; }
        !           266:    ;
        !           267: 
        !           268: print:
        !           269:      PRINT | PRINTF
        !           270:    ;
        !           271: 
        !           272: pst:
        !           273:      NL | ';' | pst NL | pst ';'
        !           274:    ;
        !           275: 
        !           276: rbrace:
        !           277:      '}' | rbrace NL
        !           278:    ;
        !           279: 
        !           280: re:
        !           281:       reg_expr
        !           282:        { $$ = op3(MATCH, NIL, rectonode(), (Node*)makedfa($1, 0)); }
        !           283:    | NOT re    { $$ = op1(NOT, notnull($2)); }
        !           284:    ;
        !           285: 
        !           286: reg_expr:
        !           287:      '/' {startreg();} REGEXPR '/'     { $$ = $3; }
        !           288:    ;
        !           289: 
        !           290: rparen:
        !           291:      ')' | rparen NL
        !           292:    ;
        !           293: 
        !           294: simple_stmt:
        !           295:      print prarg '|' term      { 
        !           296:            if (safe) SYNTAX("print | is unsafe");
        !           297:            else $$ = stat3($1, $2, itonp($3), $4); }
        !           298:    | print prarg APPEND term   {
        !           299:            if (safe) SYNTAX("print >> is unsafe");
        !           300:            else $$ = stat3($1, $2, itonp($3), $4); }
        !           301:    | print prarg GT term       {
        !           302:            if (safe) SYNTAX("print > is unsafe");
        !           303:            else $$ = stat3($1, $2, itonp($3), $4); }
        !           304:    | print prarg           { $$ = stat3($1, $2, NIL, NIL); }
        !           305:    | DELETE varname '[' patlist ']' { $$ = stat2(DELETE, makearr($2), $4); }
        !           306:    | DELETE varname         { $$ = stat2(DELETE, makearr($2), 0); }
        !           307:    | pattern           { $$ = exptostat($1); }
        !           308:    | error             { yyclearin; SYNTAX("illegal statement"); }
        !           309:    ;
        !           310: 
        !           311: st:
        !           312:      nl
        !           313:    | ';' opt_nl
        !           314:    ;
        !           315: 
        !           316: stmt:
        !           317:      BREAK st      { if (!inloop) SYNTAX("break illegal outside of loops");
        !           318:                  $$ = stat1(BREAK, NIL); }
        !           319:    | CONTINUE st       {  if (!inloop) SYNTAX("continue illegal outside of loops");
        !           320:                  $$ = stat1(CONTINUE, NIL); }
        !           321:    | do {inloop++;} stmt {--inloop;} WHILE '(' pattern ')' st
        !           322:        { $$ = stat2(DO, $3, notnull($7)); }
        !           323:    | EXIT pattern st   { $$ = stat1(EXIT, $2); }
        !           324:    | EXIT st       { $$ = stat1(EXIT, NIL); }
        !           325:    | for
        !           326:    | if stmt else stmt { $$ = stat3(IF, $1, $2, $4); }
        !           327:    | if stmt       { $$ = stat3(IF, $1, $2, NIL); }
        !           328:    | lbrace stmtlist rbrace { $$ = $2; }
        !           329:    | NEXT st   { if (infunc)
        !           330:                SYNTAX("next is illegal inside a function");
        !           331:              $$ = stat1(NEXT, NIL); }
        !           332:    | NEXTFILE st   { if (infunc)
        !           333:                SYNTAX("nextfile is illegal inside a function");
        !           334:              $$ = stat1(NEXTFILE, NIL); }
        !           335:    | RETURN pattern st { $$ = stat1(RETURN, $2); }
        !           336:    | RETURN st     { $$ = stat1(RETURN, NIL); }
        !           337:    | simple_stmt st
        !           338:    | while {inloop++;} stmt    { --inloop; $$ = stat2(WHILE, $1, $3); }
        !           339:    | ';' opt_nl        { $$ = 0; }
        !           340:    ;
        !           341: 
        !           342: stmtlist:
        !           343:      stmt
        !           344:    | stmtlist stmt     { $$ = linkum($1, $2); }
        !           345:    ;
        !           346: 
        !           347: subop:
        !           348:      SUB | GSUB
        !           349:    ;
        !           350: 
        !           351: term:
        !           352:      term '/' ASGNOP term      { $$ = op2(DIVEQ, $1, $4); }
        !           353:    | term '+' term         { $$ = op2(ADD, $1, $3); }
        !           354:    | term '-' term         { $$ = op2(MINUS, $1, $3); }
        !           355:    | term '*' term         { $$ = op2(MULT, $1, $3); }
        !           356:    | term '/' term         { $$ = op2(DIVIDE, $1, $3); }
        !           357:    | term '%' term         { $$ = op2(MOD, $1, $3); }
        !           358:    | term POWER term       { $$ = op2(POWER, $1, $3); }
        !           359:    | '-' term %prec UMINUS     { $$ = op1(UMINUS, $2); }
        !           360:    | '+' term %prec UMINUS     { $$ = $2; }
        !           361:    | NOT term %prec UMINUS     { $$ = op1(NOT, notnull($2)); }
        !           362:    | BLTIN '(' ')'         { $$ = op2(BLTIN, itonp($1), rectonode()); }
        !           363:    | BLTIN '(' patlist ')'     { $$ = op2(BLTIN, itonp($1), $3); }
        !           364:    | BLTIN             { $$ = op2(BLTIN, itonp($1), rectonode()); }
        !           365:    | CALL '(' ')'          { $$ = op2(CALL, celltonode($1,CVAR), NIL); }
        !           366:    | CALL '(' patlist ')'      { $$ = op2(CALL, celltonode($1,CVAR), $3); }
        !           367:    | CLOSE term            { $$ = op1(CLOSE, $2); }
        !           368:    | DECR var          { $$ = op1(PREDECR, $2); }
        !           369:    | INCR var          { $$ = op1(PREINCR, $2); }
        !           370:    | var DECR          { $$ = op1(POSTDECR, $1); }
        !           371:    | var INCR          { $$ = op1(POSTINCR, $1); }
        !           372:    | GETLINE var LT term       { $$ = op3(GETLINE, $2, itonp($3), $4); }
        !           373:    | GETLINE LT term       { $$ = op3(GETLINE, NIL, itonp($2), $3); }
        !           374:    | GETLINE var           { $$ = op3(GETLINE, $2, NIL, NIL); }
        !           375:    | GETLINE           { $$ = op3(GETLINE, NIL, NIL, NIL); }
        !           376:    | INDEX '(' pattern comma pattern ')'
        !           377:        { $$ = op2(INDEX, $3, $5); }
        !           378:    | INDEX '(' pattern comma reg_expr ')'
        !           379:        { SYNTAX("index() doesn't permit regular expressions");
        !           380:          $$ = op2(INDEX, $3, (Node*)$5); }
        !           381:    | '(' pattern ')'       { $$ = $2; }
        !           382:    | MATCHFCN '(' pattern comma reg_expr ')'
        !           383:        { $$ = op3(MATCHFCN, NIL, $3, (Node*)makedfa($5, 1)); }
        !           384:    | MATCHFCN '(' pattern comma pattern ')'
        !           385:        { if (constnode($5))
        !           386:            $$ = op3(MATCHFCN, NIL, $3, (Node*)makedfa(strnode($5), 1));
        !           387:          else
        !           388:            $$ = op3(MATCHFCN, (Node *)1, $3, $5); }
        !           389:    | NUMBER            { $$ = celltonode($1, CCON); }
        !           390:    | SPLIT '(' pattern comma varname comma pattern ')'     /* string */
        !           391:        { $$ = op4(SPLIT, $3, makearr($5), $7, (Node*)STRING); }
        !           392:    | SPLIT '(' pattern comma varname comma reg_expr ')'    /* const /regexp/ */
        !           393:        { $$ = op4(SPLIT, $3, makearr($5), (Node*)makedfa($7, 1), (Node *)REGEXPR); }
        !           394:    | SPLIT '(' pattern comma varname ')'
        !           395:        { $$ = op4(SPLIT, $3, makearr($5), NIL, (Node*)STRING); }  /* default */
        !           396:    | SPRINTF '(' patlist ')'   { $$ = op1($1, $3); }
        !           397:    | STRING            { $$ = celltonode($1, CCON); }
        !           398:    | subop '(' reg_expr comma pattern ')'
        !           399:        { $$ = op4($1, NIL, (Node*)makedfa($3, 1), $5, rectonode()); }
        !           400:    | subop '(' pattern comma pattern ')'
        !           401:        { if (constnode($3))
        !           402:            $$ = op4($1, NIL, (Node*)makedfa(strnode($3), 1), $5, rectonode());
        !           403:          else
        !           404:            $$ = op4($1, (Node *)1, $3, $5, rectonode()); }
        !           405:    | subop '(' reg_expr comma pattern comma var ')'
        !           406:        { $$ = op4($1, NIL, (Node*)makedfa($3, 1), $5, $7); }
        !           407:    | subop '(' pattern comma pattern comma var ')'
        !           408:        { if (constnode($3))
        !           409:            $$ = op4($1, NIL, (Node*)makedfa(strnode($3), 1), $5, $7);
        !           410:          else
        !           411:            $$ = op4($1, (Node *)1, $3, $5, $7); }
        !           412:    | SUBSTR '(' pattern comma pattern comma pattern ')'
        !           413:        { $$ = op3(SUBSTR, $3, $5, $7); }
        !           414:    | SUBSTR '(' pattern comma pattern ')'
        !           415:        { $$ = op3(SUBSTR, $3, $5, NIL); }
        !           416:    | var
        !           417:    ;
        !           418: 
        !           419: var:
        !           420:      varname
        !           421:    | varname '[' patlist ']'   { $$ = op2(ARRAY, makearr($1), $3); }
        !           422:    | IVAR              { $$ = op1(INDIRECT, celltonode($1, CVAR)); }
        !           423:    | INDIRECT term         { $$ = op1(INDIRECT, $2); }
        !           424:    ;   
        !           425: 
        !           426: varlist:
        !           427:      /* nothing */     { arglist = $$ = 0; }
        !           428:    | VAR           { arglist = $$ = celltonode($1,CVAR); }
        !           429:    | varlist comma VAR {
        !           430:            checkdup($1, $3);
        !           431:            arglist = $$ = linkum($1,celltonode($3,CVAR)); }
        !           432:    ;
        !           433: 
        !           434: varname:
        !           435:      VAR           { $$ = celltonode($1, CVAR); }
        !           436:    | ARG           { $$ = op1(ARG, itonp($1)); }
        !           437:    | VARNF         { $$ = op1(VARNF, (Node *) $1); }
        !           438:    ;
        !           439: 
        !           440: 
        !           441: while:
        !           442:      WHILE '(' pattern rparen  { $$ = notnull($3); }
        !           443:    ;
        !           444: 
        !           445: %%
        !           446: 
        !           447: void setfname(Cell *p)
        !           448: {
        !           449:    if (isarr(p))
        !           450:        SYNTAX("%s is an array, not a function", p->nval);
        !           451:    else if (isfcn(p))
        !           452:        SYNTAX("you can't define function %s more than once", p->nval);
        !           453:    curfname = p->nval;
        !           454: }
        !           455: 
        !           456: int constnode(Node *p)
        !           457: {
        !           458:    return isvalue(p) && ((Cell *) (p->narg[0]))->csub == CCON;
        !           459: }
        !           460: 
        !           461: char *strnode(Node *p)
        !           462: {
        !           463:    return ((Cell *)(p->narg[0]))->sval;
        !           464: }
        !           465: 
        !           466: Node *notnull(Node *n)
        !           467: {
        !           468:    switch (n->nobj) {
        !           469:    case LE: case LT: case EQ: case NE: case GT: case GE:
        !           470:    case BOR: case AND: case NOT:
        !           471:        return n;
        !           472:    default:
        !           473:        return op2(NE, n, nullnode);
        !           474:    }
        !           475: }
        !           476: 
        !           477: void checkdup(Node *vl, Cell *cp)  /* check if name already in list */
        !           478: {
        !           479:    char *s = cp->nval;
        !           480:    for ( ; vl; vl = vl->nnext) {
        !           481:        if (strcmp(s, ((Cell *)(vl->narg[0]))->nval) == 0) {
        !           482:            SYNTAX("duplicate argument %s", s);
        !           483:            break;
        !           484:        }
        !           485:    }
        !           486: }

CVSweb interface <joel.bertrand@systella.fr>