Annotation of coherent/b/bin/sh.420/sh.y, revision 1.1.1.1

1.1       root        1: /*
                      2:  * The Bourne shell.
                      3:  * This shell is dedicated to Ciaran Gerald Aidan O'Donnell.
                      4:  * May he live a thousand minutes (long enough to fix up YACC).
                      5:  * It is also dedicated to Steve Bourne.
                      6:  * May he live a thousand seconds.
                      7:  */
                      8: %{
                      9: #include "sh.h"
                     10: 
                     11: #define YYERROR        { yyerrflag=1; goto YYerract; }
                     12: 
                     13: extern NODE    *node();
                     14: %}
                     15: 
                     16: %union {
                     17:        NODE    *yu_node;
                     18:        char    *yu_strp;
                     19:        int     yu_nval;
                     20: }
                     21: 
                     22: %token _ANDF
                     23: %token _ASGN
                     24: %token _CASE
                     25: %token _CBRAC
                     26: %token _DO
                     27: %token _DONE
                     28: %token _DSEMI
                     29: %token _ELIF
                     30: %token _ELSE
                     31: %token _ESAC
                     32: %token _FI
                     33: %token _FOR
                     34: %token _IF
                     35: %token _IN
                     36: %token _IORS
                     37: %token _NAME
                     38: %token _NULL
                     39: %token _OBRAC
                     40: %token _ORF
                     41: %token _PARENS
                     42: %token _RET
                     43: %token _THEN
                     44: %token _UNTIL
                     45: %token _WHILE
                     46: 
                     47: %type <yu_node>        arg             arg_list        case_line       case_list
                     48: %type <yu_node>        cmd             cmd_line        cmd_list        cmd_seq
                     49: %type <yu_node>        control         do_list         else_part       in_name_list
                     50: %type <yu_node>        logical_cmd     name_list       opt_cmd_seq     pattern_list
                     51: %type <yu_node>        pipe_cmd        sub_shell
                     52: 
                     53: %type <yu_node>        command         simple_command  redirect_list   cmd_prefix
                     54: %type <yu_node>        cmd_word        cmd_suffix      cmd_name        redirect_list
                     55: %type <yu_node>        asgn_node       redirect_node   name_node
                     56: %type <yu_node>        function_definition     compound_command
                     57: %type <yu_node>        non_keyword_name
                     58: 
                     59: %type <yu_strp>        asgn            name            redirect
                     60: 
                     61: %type <yu_nval> whuntile
                     62: 
                     63: %%
                     64: 
                     65: session:
                     66:        '\n' {
                     67:                sesp->s_node = NULL;
                     68:                reset (RCMD);
                     69:                NOTREACHED;
                     70:        }
                     71: |
                     72:        cmd_list {
                     73:                sesp->s_node = $1;
                     74:                reset (errflag ? RERR : RCMD);
                     75:                NOTREACHED;
                     76:        }
                     77: |      error '\n' {
                     78:                keyflush ();
                     79:                keyflag = 1;
                     80:                reset (RERR);
                     81:                NOTREACHED;
                     82:        }
                     83: |
                     84: ;
                     85: 
                     86: if:    _IF optnls ;
                     87: 
                     88: then:  _THEN optnls ;
                     89: 
                     90: elif:  _ELIF optnls ;
                     91: 
                     92: else:  _ELSE optnls ;
                     93: 
                     94: whuntile:
                     95:        _WHILE optnls { $$ = NWHILE; }
                     96: |      _UNTIL optnls { $$ = NUNTIL; }
                     97: ;
                     98: 
                     99: do:    _DO optnls | _DO ';' optnls ;
                    100: 
                    101: in:    _IN | _IN sep ;
                    102: 
                    103: oror:  _ORF optnls;
                    104: 
                    105: andand:        _ANDF optnls;
                    106: 
                    107: or:    '|' optnls;
                    108: 
                    109: oparen:        '(' optnls ;
                    110: 
                    111: obrack:        _OBRAC optnls ;
                    112: 
                    113: cparen:        ')' optnls ;
                    114: 
                    115: dsemi: _DSEMI optnls ;
                    116: 
                    117: cmd_list:
                    118:        logical_cmd {
                    119:                $$ = $1;
                    120:        }
                    121: |      logical_cmd '&' {
                    122:                $$ = node(NBACK, $1, NULL);
                    123:        }
                    124: |      logical_cmd ';' {
                    125:                $$ = $1;
                    126:        }
                    127: |      logical_cmd '&' cmd_list {
                    128:                $$ = node(NBACK, $1, $3);
                    129:        }
                    130: |      logical_cmd ';' cmd_list {
                    131:                $$ = node(NLIST, $1, $3);
                    132:        }
                    133: ;
                    134: 
                    135: logical_cmd:
                    136:        pipe_cmd {
                    137:                $$ = $1;
                    138:        }
                    139: |      pipe_cmd oror logical_cmd {
                    140:                $$ = node(NORF, $1, $3);
                    141:        }
                    142: |      pipe_cmd andand logical_cmd {
                    143:                $$ = node(NANDF, $1, $3);
                    144:        }
                    145: ;
                    146: 
                    147: pipe_cmd:
                    148:        cmd or pipe_cmd {
                    149:                $$ = node(NPIPE, $1, $3);
                    150:        }
                    151: |      cmd {
                    152:                $$ = $1;
                    153:        }
                    154: ;
                    155: 
                    156: /*
                    157:  * In the original grammar, no distinction between simple command and compound
                    158:  * commands was made. This, along with the right-recursive formulation of the
                    159:  * command grammar, created a need for lookahead that defeated the complex
                    160:  * machinery for context-sensitive lexing that is required.
                    161:  */
                    162: 
                    163: cmd:   turn_on_keywords command {
                    164:                $$ = $2;
                    165:                keypop ();
                    166:        }
                    167: ;
                    168: 
                    169: turn_on_keywords: {
                    170:                keypush ();
                    171:                keyflag = 1;
                    172:        }
                    173: ;
                    174: 
                    175: command:
                    176:        simple_command {
                    177:                $$ = node (NCOMS, $1, NULL);
                    178:        }
                    179: |      compound_command {
                    180:                $$ = node (NCOMS, $1, NULL);
                    181:        }
                    182: |      compound_command redirect_list {
                    183:                $1->n_next = $2;
                    184:                $$ = node (NCOMS, $1, NULL);
                    185:        }
                    186: |      function_definition {
                    187:                $$ = node (NCOMS, $1, NULL);
                    188:        }
                    189: |      _RET name {
                    190:                $$ = node (NRET, $2, NULL);
                    191:        }
                    192: |      _RET {
                    193:                $$ = node (NRET, "", NULL);
                    194:        }
                    195: ;
                    196: 
                    197: compound_command:
                    198:        control {
                    199:                $$ = node (NCTRL, $1, NULL);
                    200:        }
                    201: ;
                    202:        
                    203: function_definition:
                    204:        name _PARENS optnls obrack cmd_seq _CBRAC  {
                    205:                $$ = node (NCTRL, node (NFUNC, $1, $5), NULL);
                    206:        }
                    207: ;
                    208: 
                    209: redirect_list:
                    210:        redirect_node {
                    211:                $$ = $1;
                    212:        }
                    213: |      redirect_list redirect_node {
                    214:                ($$ = $1)->n_next = $2;
                    215:        }
                    216: ;
                    217: 
                    218: simple_command:
                    219:        cmd_prefix cmd_word cmd_suffix {
                    220:                NODE          * tmp = $1;
                    221:                /*
                    222:                 * NIGEL: The structure of the nodes that have to be generated
                    223:                 * is flat, but now the grammar is structured; deal with this.
                    224:                 */
                    225: 
                    226:                while (tmp->n_next)
                    227:                        tmp = tmp->n_next;
                    228: 
                    229:                (tmp->n_next = $2)->n_next = $3;
                    230:                $$ = $1;
                    231:        }
                    232: |      cmd_prefix cmd_word {
                    233:                NODE          * tmp = $1;
                    234:                /*
                    235:                 * NIGEL: The structure of the nodes that have to be generated
                    236:                 * is flat, but now the grammar is structured; deal with this.
                    237:                 */
                    238: 
                    239:                while (tmp->n_next)
                    240:                        tmp = tmp->n_next;
                    241: 
                    242:                tmp->n_next = $2;
                    243:                $$ = $1;
                    244:        }
                    245: |      cmd_prefix {
                    246:                $$ = $1;
                    247:        }
                    248: |      cmd_name cmd_suffix {
                    249:                ($$ = $1)->n_next = $2;
                    250:        }
                    251: |      cmd_name {
                    252:                $$ = $1;
                    253:        }
                    254: ;
                    255: 
                    256: cmd_prefix:
                    257:        redirect_node {
                    258:                $$ = $1;
                    259:        }
                    260: |      redirect_node cmd_prefix {
                    261:                ($$ = $1)->n_next = $2;
                    262:        }
                    263: |      asgn_node {
                    264:                $$ = $1;
                    265:        }
                    266: |      asgn_node cmd_prefix {
                    267:                ($$ = $1)->n_next = $2;
                    268:        }
                    269: ;
                    270: 
                    271: cmd_name:
                    272:        name_node {
                    273:                $$ = $1;
                    274:                keyflag = 0;
                    275:        }
                    276: ;
                    277: 
                    278: cmd_word:
                    279:        name_node {
                    280:                $$ = $1;
                    281:                keyflag = 0;
                    282:        }
                    283: ;
                    284: 
                    285: /*
                    286:  * The main part of this shell has some silliness with assignments and some
                    287:  * flag called '-k'. To support this, we allow assignments after the command
                    288:  * name and code elsewhere turns them back into parameters... it seems
                    289:  * preferable to do it here, but because of the '-k' thing we'll just
                    290:  * accept them.
                    291:  */
                    292: 
                    293: cmd_suffix:
                    294:        redirect_node {
                    295:                $$ = $1;
                    296:        }
                    297: |      redirect_node cmd_suffix {
                    298:                ($$ = $1)->n_next = $2;
                    299:        }
                    300: |      non_keyword_name {
                    301:                $$ = $1;
                    302:        }
                    303: |      non_keyword_name cmd_suffix {
                    304:                ($$ = $1)->n_next = $2;
                    305:        }
                    306: |      asgn_node {
                    307:                $$ = $1;
                    308:        }
                    309: |      asgn_node cmd_suffix {
                    310:                ($$ = $1)->n_next = $2;
                    311:        }
                    312: ;
                    313: 
                    314: non_keyword_name:
                    315:        non_keyword_string {
                    316:                $$ = node (NARGS, duplstr (strt, 0), NULL);
                    317:        }
                    318: ;
                    319: 
                    320: /*
                    321:  * Many of the following cause S/R conflicts. This reflects the fact that the
                    322:  * decision about whether to recognise a token in a given place needs some
                    323:  * extra disambiguation or not. In all cases, the correct result is to shift
                    324:  * (treating the reserved word as a normal word), which is the default.
                    325:  */
                    326: non_keyword_string:
                    327:        _NAME
                    328: |      _CASE
                    329: |      _DO
                    330: |      _DONE
                    331: |      _ELIF
                    332: |      _ELSE
                    333: |      _ESAC
                    334: |      _FI
                    335: |      _FOR
                    336: |      _IF
                    337: |      _IN
                    338: |      _RET
                    339: |      _THEN
                    340: |      _UNTIL
                    341: |      _WHILE
                    342: ;
                    343:        
                    344: /*
                    345:  * Replaced by detailed cases above.
                    346: cmd:
                    347:        arg_list_init arg_list {
                    348:                $$ = node(NCOMS, $2, NULL);
                    349:                keypop();
                    350:        }
                    351: |      _RET name {
                    352:                $$ = node(NRET, $2, NULL);
                    353:        }
                    354: |      _RET {
                    355:                $$ = node(NRET, "", NULL);
                    356:        }
                    357: ;
                    358: 
                    359: arg_list_init:
                    360:        {
                    361:                keypush();
                    362:                keyflag = 1;
                    363:        }
                    364: ;
                    365: 
                    366: arg_list:
                    367:        arg arg_list {
                    368:                if (($1->n_type == NCTRL && $2->n_type == NARGS)
                    369:                 || ($1->n_type == NARGS && $2->n_type == NCTRL)) {
                    370:                        YYERROR;
                    371:                }
                    372:                ($$ = $1)->n_next = $2;
                    373:        }
                    374: |      arg {
                    375:                $$ = $1;
                    376:        }
                    377: ;
                    378: 
                    379: arg:
                    380:        redirect_node {
                    381:                $$ = $1;
                    382:        }
                    383: |      name_node {
                    384:                $$ = $1;
                    385:                keyflag = 0;
                    386:        }
                    387: |      asgn_node {
                    388:                $$ = $1;
                    389:        }
                    390: |      control {
                    391:                if (!keyflag) {
                    392:                        YYERROR;
                    393:                }
                    394:                $$ = node(NCTRL, $1, NULL);
                    395:                keyflag = 0;
                    396:        }
                    397: ;
                    398: */
                    399: 
                    400: /*
                    401:  * The form of the following productions arranges for the contents of the
                    402:  * global "strt" to be duplicated ASAP, hopefully before lookahead gets
                    403:  * involved.
                    404:  */
                    405: 
                    406: redirect_node: redirect {
                    407:                $$ = node (NIORS, $1, NULL);
                    408:        }
                    409: ;
                    410: 
                    411: redirect:      _IORS {
                    412:                $$ = duplstr (strt, 0);
                    413:        }
                    414: ;
                    415: 
                    416: name_node: name {
                    417:                $$ = node (NARGS, $1, NULL);
                    418:        }
                    419: ;
                    420: 
                    421: name:  _NAME {
                    422:                $$ = duplstr (strt, 0);
                    423:        }
                    424: ;
                    425: 
                    426: 
                    427: asgn_node: asgn {
                    428:                $$ = node (NASSG, $1, NULL);
                    429:        }
                    430: ;
                    431: 
                    432: asgn:  _ASGN {
                    433:                $$ = duplstr (strt, 0);
                    434:        }
                    435: ;
                    436: 
                    437: control:
                    438:        _FOR name in_name_list sep do_list _DONE {
                    439:                $$ = node(NFOR, $2, node(NFOR2, $3, node(NLIST, $5, NULL)));
                    440:                $$->n_next->n_next->n_next = $$->n_next;
                    441:        }
                    442: |      _FOR name in_name_list do_list _DONE {
                    443:                $$ = node(NFOR, $2, node(NFOR2, $3, node(NLIST, $4, NULL)));
                    444:                $$->n_next->n_next->n_next = $$->n_next;
                    445:        }
                    446: |      _CASE name sep in case_list _ESAC {
                    447:                $$ = node(NCASE, $2, $5);
                    448:        }
                    449: |      _CASE name in case_list _ESAC {
                    450:                $$ = node(NCASE, $2, $4);
                    451:        }
                    452: |      whuntile cmd_seq do_list _DONE {
                    453:                $$ = node($1, $2, node(NLIST, $3, NULL));
                    454:                $$->n_next->n_next = $$;
                    455:        }
                    456: |      if cmd_seq then opt_cmd_seq else_part _FI {
                    457:                $$ = node(NIF, node(NNULL, $2, $4), $5);
                    458:        }
                    459: |      oparen opt_cmd_seq ')' {
                    460:                $$ = node(NPARN, $2, NULL);
                    461:        }
                    462: |      obrack opt_cmd_seq _CBRAC {
                    463:                $$ = node(NBRAC, $2, NULL);
                    464:        }
                    465: ;
                    466: 
                    467: in_name_list:
                    468:        _IN name_list {
                    469:                $$ = $2;
                    470:        }
                    471: |      {
                    472:                $$ = node(NARGS, "\"$@\"", NULL);
                    473:        }
                    474: ;
                    475: 
                    476: name_list:
                    477:        name name_list {
                    478:                $$ = node(NARGS, $1, $2);
                    479:        }
                    480: |      {
                    481:                $$ = NULL;
                    482:        }
                    483: ;
                    484: 
                    485: case_list:
                    486:        case_line dsemi case_list {
                    487:                register NODE *np;
                    488: 
                    489:                for (np=$1; np->n_next; np=np->n_next)
                    490:                        ;
                    491:                np->n_next = $3;
                    492:                $$ = $1;
                    493:        }
                    494: |      case_line {
                    495:                $$ = $1;
                    496:        }
                    497: |      {
                    498:                $$ = NULL;
                    499:        }
                    500: ;
                    501: 
                    502: case_line:
                    503:        pattern_list cparen opt_cmd_seq {
                    504:                $$ = node(NCASE2, $3, $1);
                    505:        }
                    506: ;
                    507: 
                    508: pattern_list:
                    509:        name '|' pattern_list {
                    510:                $$ = node(NCASE3, $1, $3);
                    511:        }
                    512: |      name {
                    513:                $$ = node(NCASE3, $1, NULL);
                    514:        }
                    515: ;
                    516: 
                    517: do_list:
                    518:        do opt_cmd_seq {
                    519:                $$ = $2;
                    520:        }
                    521: |      {
                    522:                $$ = NULL;
                    523:        }
                    524: ;
                    525: 
                    526: else_part:
                    527:        elif cmd_seq then opt_cmd_seq else_part {
                    528:                $$ = node(NIF, node(NNULL, $2, $4), $5);
                    529:        }
                    530: |      else opt_cmd_seq {
                    531:                $$ = node(NELSE, $2, NULL);
                    532:        }
                    533: |      {
                    534:                $$ = NULL;
                    535:        }
                    536: ;
                    537: 
                    538: opt_cmd_seq:
                    539:        cmd_seq {
                    540:                $$ = $1;
                    541:        }
                    542: |
                    543:        {
                    544:                $$ = NULL;
                    545:        }
                    546: ;
                    547: 
                    548: cmd_seq:
                    549:        cmd_list nls cmd_seq {
                    550:                $$ = node(NLIST, $1, $3);
                    551:        }
                    552: |      cmd_list optnls {
                    553:                $$ = $1;
                    554:        }
                    555: ;
                    556: 
                    557: sep:   nls
                    558: |      ';'
                    559: |      ';' nls
                    560: ;
                    561: 
                    562: optnls:        nls
                    563: |
                    564: ;
                    565: 
                    566: nls:   '\n'
                    567: |      nls '\n'
                    568: ;
                    569: 
                    570: %%
                    571: /*
                    572:  * Create a node.
                    573:  */
                    574: NODE *
                    575: node(type, auxp, next)
                    576: NODE *auxp, *next;
                    577: {
                    578:        register NODE *np;
                    579: 
                    580:        np = (NODE *) balloc(sizeof (NODE));
                    581:        np->n_type = type;
                    582:        np->n_auxp = auxp;
                    583:        np->n_next = next;
                    584:        return np;
                    585: }
                    586: 
                    587: #define NBPC 8
                    588: #define NKEY 8
                    589: static char keys[NKEY] = { 0 };
                    590: static int  keyi = NKEY * NBPC;
                    591: 
                    592: keyflush()
                    593: {
                    594:        register char *kp;
                    595: 
                    596:        for (kp = keys+NKEY; kp > keys; *--kp = 0)
                    597:                ;
                    598:        keyi = NKEY * NBPC;
                    599: }
                    600: 
                    601: keypop()
                    602: {
                    603:        register char   *kp;
                    604:        register int    km;
                    605: 
                    606:        if ((km = keyi++) >= NKEY * NBPC) {
                    607:                panic(11);
                    608:                NOTREACHED;
                    609:        }
                    610:        kp = keys + (km / NBPC);
                    611:        km = 1 << (km %= NBPC);
                    612:        keyflag = (*kp & km) ? 1 : 0;
                    613:        *kp &= ~km;
                    614: }
                    615: 
                    616: keypush()
                    617: {
                    618:        register char   *kp;
                    619:        register int    km;
                    620: 
                    621:        if ((km = --keyi) < 0) {
                    622:                panic(12);
                    623:                NOTREACHED;
                    624:        }
                    625:        if (keyflag) {
                    626:                kp = keys + (km / NBPC);
                    627:                km = 1 << (km %= NBPC);
                    628:                *kp |= km;
                    629:        }
                    630: }
                    631: /*
                    632:  * The following fragments might implement named pipes.
                    633:  * The token declaration goes in the header.
                    634:  * The nopen production should go with the others of its ilk.
                    635:  * The production fragment goes into arg:
                    636: %token _NOPEN _NCLOSE
                    637: nopen: _NOPEN optnls ;
                    638: 
                    639: |      nopen pipe_cmd ')' {
                    640:                $$ = node(NRPIPE, $2, NULL);
                    641:        }
                    642: |      oparen pipe_cmd _NCLOSE {
                    643:                $$ = node(NWPIPE, $2, NULL);
                    644:        }
                    645: CLOSE {
                    646:                $$ = node(NWPIPE, $2, NULL);
                    647:        }
                    648:  *
                    649:  */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.