home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / tn3270 / tools / mkmake.y < prev    next >
Encoding:
Lex Description  |  1991-04-26  |  20.2 KB  |  1,098 lines

  1. %{
  2.  
  3. /*-
  4.  * Copyright (c) 1988 The Regents of the University of California.
  5.  * All rights reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  * 1. Redistributions of source code must retain the above copyright
  11.  *    notice, this list of conditions and the following disclaimer.
  12.  * 2. Redistributions in binary form must reproduce the above copyright
  13.  *    notice, this list of conditions and the following disclaimer in the
  14.  *    documentation and/or other materials provided with the distribution.
  15.  * 3. All advertising materials mentioning features or use of this software
  16.  *    must display the following acknowledgement:
  17.  *    This product includes software developed by the University of
  18.  *    California, Berkeley and its contributors.
  19.  * 4. Neither the name of the University nor the names of its contributors
  20.  *    may be used to endorse or promote products derived from this software
  21.  *    without specific prior written permission.
  22.  *
  23.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  24.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  25.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  26.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  27.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  28.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  29.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  30.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  32.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  33.  * SUCH DAMAGE.
  34.  */
  35.  
  36. #ifndef lint
  37. static char sccsid[] = "@(#)mkmake.y    4.2 (Berkeley) 4/26/91";
  38. #endif /* not lint */
  39.  
  40. typedef struct string {
  41.     int
  42.     hashval,
  43.     length;
  44.     char
  45.     *string;
  46.     struct string
  47.     *next;
  48. } string_t;
  49.  
  50. /*
  51.  * The deal with these is that they exist on various lists.
  52.  *
  53.  * First off, they are on a temporary list during the time they
  54.  * are in the active focus of the parser.
  55.  *
  56.  * Secondly, they live on one of three queues:
  57.  *    1.  Variables
  58.  *    2.  Targets
  59.  *    3.  Actions
  60.  * (and, we restrict any given one to live on one and only one such list)
  61.  *
  62.  * Also, they may live on the list of values for someone else's variable,
  63.  * or as someone's dependancy.
  64.  */
  65.  
  66. typedef struct same {
  67.     string_t
  68.     *string;            /* My name */
  69.     struct same
  70.     *nexttoken,            /* Next pointer */
  71.     *lasttoken,            /* Back pointer */
  72.     *depend_list,            /* If target, dependancies */
  73.     *action_list,            /* If target, actions */
  74.     *value_list,            /* If variable, value list */
  75.     *shell_item;            /* If a shell variable, current value */
  76. } same_t;
  77.  
  78. %}
  79.  
  80. %union {
  81.     string_t *string;
  82.     same_t *same;
  83.     int    intval;
  84.     }
  85.  
  86. %start makefile
  87. %token <string> TOKEN QUOTED_STRING
  88. %token <intval>    FOR IN DO DONE
  89. %token <intval> MACRO_CHAR NL WHITE_SPACE
  90. %token <intval> ':' '=' '$' '{' '}' ';' '-' '@' '(' ')' ' ' '\t'
  91. %type <same> target target1 assignment assign1 actions action
  92. %type <same> command_list list list_element
  93. %type <same> for_statement maybe_at_minus tokens token
  94. %type <same> maybe_white_space
  95. %type <intval> white_space macro_char
  96. %%
  97.  
  98. makefile : lines;
  99.  
  100. lines : line
  101.     | lines line
  102.     ;
  103.  
  104. line : NL
  105.     | assignment
  106.     | target_action
  107.     ;
  108.  
  109. assignment : assign1 tokens NL
  110.     {
  111.     assign($1, $2);
  112.     }
  113.     | assign1 NL
  114.     {
  115.     assign($1, same_copy(null));
  116.     }
  117.     ;
  118.  
  119. assign1: token maybe_white_space '=' maybe_white_space
  120.     ;
  121.  
  122. target_action: target actions
  123.     {
  124.     add_targets_actions($1, $2);
  125.     }
  126.     | target
  127.     {
  128.     add_targets_actions($1, 0);
  129.     }
  130.     ;
  131.  
  132. target : target1 tokens NL
  133.     {
  134.     $$ = add_depends($1, $2);
  135.     }
  136.     | target1 NL
  137.     {
  138.     $$ = add_depends($1, same_copy(null));
  139.     }
  140.     ;
  141.  
  142. target1: tokens maybe_white_space ':' maybe_white_space
  143.     {
  144.     $$ = ws_merge($1);
  145.     }
  146.     ;
  147.  
  148. actions: action
  149.     | actions action
  150.     {
  151.     $$ = same_cat(same_cat($1, same_copy(newline)), $2);
  152.     }
  153.     ;
  154.  
  155. action:    white_space command_list NL
  156.     {
  157.     $$ = $2;
  158.     }
  159.     | white_space for_statement do command_list semi_colon done NL
  160.     {
  161.     $$ = do_command($2, $4);
  162.     }
  163.     ;
  164.  
  165. for_statement: maybe_at_minus FOR white_space token
  166.         in tokens semi_colon
  167.     {
  168.     $$ = for_statement($1, $4, ws_merge(expand_variables($6, 0)));
  169.     }
  170.     ;
  171.  
  172. in:    white_space IN white_space
  173. do:    white_space DO white_space
  174.     ;
  175.  
  176. done:    white_space DONE
  177.     ;
  178.  
  179. semi_colon:    ';'
  180.     ;
  181.  
  182. command_list: list
  183.     | '(' list maybe_white_space ')'
  184.     {
  185.     $$ = same_cat($2, same_copy(cwd_line));
  186.     }
  187.     ;
  188.  
  189. list: token
  190.     | list list_element
  191.     {
  192.     $$ = same_cat($1, $2);
  193.     }
  194.     | list white_space list_element
  195.     {
  196.     $$ = same_cat($1, same_cat(same_copy(blank), $3));
  197.     }
  198.     ;
  199.  
  200. list_element: token
  201.     | semi_colon
  202.     {
  203.     $$ = same_copy(newline);
  204.     }
  205.     ;
  206.  
  207. maybe_at_minus: /* empty */
  208.     {
  209.     $$ = same_copy(null);
  210.     }
  211.     | '@'
  212.     {
  213.     char buffer[2];
  214.  
  215.     buffer[0] = $1;
  216.     buffer[1] = 0;
  217.     $$ = same_item(string_lookup(buffer));
  218.     }
  219.     | '-'
  220.     {
  221.     char buffer[2];
  222.  
  223.     buffer[0] = $1;
  224.     buffer[1] = 0;
  225.     $$ = same_item(string_lookup(buffer));
  226.     }
  227.     ;
  228.  
  229. tokens : token
  230.     | tokens maybe_white_space token
  231.     {
  232.     $$ = same_cat($1, same_cat($2, $3));
  233.     }
  234.     ;
  235.  
  236. token: TOKEN
  237.     {
  238.     $$ = same_item($1);
  239.     }
  240.     | QUOTED_STRING
  241.     {
  242.     $$ = same_item($1);
  243.     }
  244.     | '$' macro_char
  245.     {
  246.     char buffer[3];
  247.  
  248.     buffer[0] = '$';
  249.     buffer[1] = $2;
  250.     buffer[2] = 0;
  251.  
  252.     $$ = same_item(string_lookup(buffer));
  253.     }
  254.     | '$' '$' TOKEN
  255.     {
  256.     $$ = shell_variable(same_item($3));
  257.     }
  258.     | MACRO_CHAR
  259.     {
  260.     $$ = same_char($1);
  261.     }
  262.     | '$' '{' TOKEN '}'
  263.     {
  264.     $$ = variable(same_item($3));
  265.     }
  266.     | '$' '(' TOKEN ')'
  267.     {
  268.     $$ = variable(same_item($3));
  269.     }
  270.     | '$' TOKEN
  271.     {
  272.     $$ = variable(same_item($2));
  273.     }
  274.     | '-'
  275.     {
  276.     $$ = same_char('-');
  277.     }
  278.     | '@'
  279.     {
  280.     $$ = same_char('@');
  281.     }
  282.     ;
  283.  
  284. macro_char: MACRO_CHAR
  285.     | '@'
  286.     ;
  287.  
  288. maybe_white_space:
  289.     {
  290.     $$ = same_copy(null);
  291.     }
  292.     | white_space
  293.     {
  294.     $$ = same_char($1);
  295.     }
  296.     ;
  297.  
  298. white_space : WHITE_SPACE
  299.     | white_space WHITE_SPACE
  300.     ;
  301. %%
  302. #include <stdio.h>
  303. #include <ctype.h>
  304.  
  305. static int last_char, last_saved = 0;
  306. static int column = 0, lineno = 1;
  307.  
  308.  
  309. static string_t
  310.     *strings = 0;
  311.  
  312. static same_t
  313.     *shell_variables = 0,
  314.     *shell_special = 0,
  315.     *variables = 0,
  316.     *targets = 0,
  317.     *actions = 0;
  318.  
  319. static same_t
  320.     *null,
  321.     *blank,
  322.     *cwd_line,
  323.     *newline;
  324.  
  325. extern char *malloc();
  326.  
  327. static unsigned int
  328.     clock = -1;
  329.  
  330. struct {
  331.     same_t *first;
  332.     int next;
  333. } visit_stack[20];        /* 20 maximum */
  334.  
  335. #define    visit(what,via) \
  336.     (visit_stack[++clock].next = 0, visit_stack[clock].first = via = what)
  337. #define    visited(via)    (visitcheck(via) || ((via) == 0) \
  338.     || (visit_stack[clock].next && (via == visit_stack[clock].first)))
  339. #define    visit_next(via)    (visit_stack[clock].next = 1, (via) = (via)->nexttoken)
  340. #define    visit_end()    (clock--)
  341.  
  342. yyerror(s)
  343. char *s;
  344. {
  345.     fprintf(stderr, "line %d, character %d: %s\n", lineno, column, s);
  346.     do_dump();
  347. }
  348.  
  349. int
  350. visitcheck(same)
  351. same_t *same;
  352. {
  353.     if (same->string == 0) {
  354.     yyerror("BUG - freed 'same' in use...");
  355.     exit(1);
  356.     }
  357.     return 0;
  358. }
  359.  
  360. int
  361. string_hashof(string, length)
  362. char *string;
  363. int length;
  364. {
  365.     register int i = 0;
  366.  
  367.     while (length--) {
  368.     i = (i<<3) + *string ^ ((i>>28)&0x7);
  369.     }
  370.     return i;
  371. }
  372.  
  373. int
  374. string_same(s1, s2)
  375. string_t
  376.     *s1, *s2;
  377. {
  378.     if ((s1->hashval == s2->hashval) && (s1->length == s2->length)
  379.         && (memcmp(s1->string, s2->string, s1->length) == 0)) {
  380.     return 1;
  381.     } else {
  382.     return 0;
  383.     }
  384. }
  385.  
  386. string_t *
  387. string_lookup(string)
  388. char *string;
  389. {
  390.     string_t ours;
  391.     string_t *ptr;
  392.  
  393.     ours.length = strlen(string);
  394.     ours.hashval = string_hashof(string, ours.length);
  395.     ours.string = string;
  396.  
  397.     for (ptr = strings; ptr; ptr = ptr->next) {
  398.     if (string_same(&ours, ptr)) {
  399.         return ptr;
  400.     }
  401.     }
  402.     if ((ptr = (string_t *)malloc(sizeof *ptr)) == 0) {
  403.     fprintf(stderr, "No space to add string *%s*!\n", string);
  404.     exit(1);
  405.     }
  406.     ptr->hashval = ours.hashval;
  407.     ptr->length = ours.length;
  408.     if ((ptr->string = malloc(ours.length+1)) == 0) {
  409.     fprintf(stderr, "No space to add literal *%s*!\n", string);
  410.     exit(1);
  411.     }
  412.     memcpy(ptr->string, string, ours.length+1);
  413.     ptr->next = strings;
  414.     strings = ptr;
  415.     return ptr;
  416. }
  417.  
  418. #define    same_singleton(s)    ((s)->nexttoken == (s))
  419.  
  420. same_t *
  421. same_search(list, token)
  422. same_t
  423.     *list,
  424.     *token;
  425. {
  426.     same_t *ptr;
  427.  
  428.     ptr = list;
  429.     for (visit(list, ptr); !visited(ptr); visit_next(ptr)) {
  430.     string_t *string;
  431.  
  432.     string = ptr->string;
  433.     if (string_same(string, token->string)) {
  434.         visit_end();
  435.         return ptr;
  436.     }
  437.     }
  438.     visit_end();
  439.     return 0;
  440. }
  441.  
  442. same_t *
  443. same_cat(list, tokens)
  444. same_t
  445.     *list,
  446.     *tokens;
  447. {
  448.     same_t *last;
  449.  
  450.     if (tokens == 0) {
  451.     return list;
  452.     }
  453.     if (list) {
  454.     last = tokens->lasttoken;
  455.     tokens->lasttoken = list->lasttoken;
  456.     list->lasttoken = last;
  457.     tokens->lasttoken->nexttoken = tokens;
  458.     last->nexttoken = list;
  459.     return list;
  460.     } else {
  461.     return tokens;
  462.     }
  463. }
  464.  
  465. same_t *
  466. same_item(string)
  467. string_t *string;
  468. {
  469.     same_t *ptr;
  470.  
  471.     if ((ptr = (same_t *)malloc(sizeof *ptr)) == 0) {
  472.     fprintf(stderr, "No more space for tokens!\n");
  473.     exit(1);
  474.     }
  475.     memset((char *)ptr, 0, sizeof *ptr);
  476.     ptr->nexttoken = ptr->lasttoken = ptr;
  477.     ptr->string = string;
  478.     return ptr;
  479. }
  480.  
  481. same_t *
  482. same_copy(same)
  483. same_t *same;
  484. {
  485.     same_t *head, *copy;
  486.  
  487.     head = 0;
  488.     for (visit(same, copy); !visited(copy); visit_next(copy)) {
  489.     same_t *ptr;
  490.  
  491.     ptr = same_item(copy->string);
  492.     head = same_cat(head, ptr);
  493.     }
  494.     visit_end();
  495.     return head;
  496. }
  497.  
  498.  
  499. same_t *
  500. same_merge(t1, t2)
  501. same_t
  502.     *t1,
  503.     *t2;
  504. {
  505.     if (same_singleton(t1) && same_singleton(t2)) {
  506.     int length = strlen(t1->string->string)+strlen(t2->string->string);
  507.     char *buffer = malloc(length+1);
  508.     same_t *value;
  509.  
  510.     if (buffer == 0) {
  511.         yyerror("No space to merge strings in same_merge!");
  512.         exit(1);
  513.     }
  514.     strcpy(buffer, t1->string->string);
  515.     strcat(buffer, t2->string->string);
  516.     value = same_item(string_lookup(buffer));
  517.     free(buffer);
  518.     return value;
  519.     } else {
  520.     yyerror("Internal error - same_merge with non-singletons");
  521.     exit(1);
  522.     }
  523. }
  524.  
  525.  
  526. void
  527. same_free(list)
  528. same_t *list;
  529. {
  530.     same_t *token, *ptr;
  531.  
  532.     if (list == 0) {
  533.     return;
  534.     }
  535.  
  536.     token = list;
  537.     do {
  538.     ptr = token->nexttoken;
  539.     token->string = 0;
  540.     (void) free((char *)token);
  541.     token = ptr;
  542.     } while (token != list);
  543. }
  544.  
  545. same_t *
  546. same_unlink(token)
  547. same_t
  548.     *token;
  549. {
  550.     same_t *tmp;
  551.  
  552.     if (token == 0) {
  553.     return 0;
  554.     }
  555.     if ((tmp = token->nexttoken) == token) {
  556.     tmp = 0;
  557.     }
  558.     token->lasttoken->nexttoken = token->nexttoken;
  559.     token->nexttoken->lasttoken = token->lasttoken;
  560.     token->nexttoken = token->lasttoken = token;
  561.     return tmp;
  562. }
  563.  
  564. void
  565. same_replace(old, new)
  566. same_t
  567.     *old,
  568.     *new;
  569. {
  570.     new->lasttoken->nexttoken = old->nexttoken;
  571.     old->nexttoken->lasttoken = new->lasttoken;
  572.     new->lasttoken = old->lasttoken;
  573.     /* rather than
  574.      * old->lasttoken->nexttoken = new
  575.      * we update in place (for the case where there isn't anything else)
  576.      */
  577.     *old = *new;
  578. }
  579.  
  580.  
  581. same_t *
  582. same_char(ch)
  583. char ch;
  584. {
  585.     char buffer[2];
  586.  
  587.     buffer[0] = ch;
  588.     buffer[1] = 0;
  589.  
  590.     return same_item(string_lookup(buffer));
  591. }
  592.  
  593.  
  594. void
  595. add_target(target, actions)
  596. same_t
  597.     *target,
  598.     *actions;
  599. {
  600.     same_t *ptr;
  601.  
  602.     if ((ptr = same_search(targets, target)) == 0) {
  603.     targets = same_cat(targets, target);
  604.     ptr = target;
  605.     } else {
  606.     ptr->depend_list = same_cat(ptr->depend_list, target->depend_list);
  607.     }
  608.     if (actions) {
  609.     if (ptr->action_list) {
  610.         same_free(ptr->action_list);
  611.     }
  612.     ptr->action_list = same_copy(actions);
  613.     }
  614. }
  615.  
  616.  
  617. same_t *
  618. add_targets_actions(target, actions)
  619. same_t
  620.     *target,
  621.     *actions;
  622. {
  623.     same_t *ptr;
  624.  
  625.     if (target == 0) {
  626.     return 0;
  627.     }
  628.     do {
  629.     ptr = same_unlink(target);
  630.     add_target(target, actions);
  631.     target = ptr;
  632.     } while (target);
  633.  
  634.     same_free(actions);
  635.     return 0;
  636. }
  637.  
  638. same_t *
  639. add_depends(target, depends)
  640. same_t
  641.     *target,
  642.     *depends;
  643. {
  644.     same_t *original = target;
  645.  
  646.     depends = same_cat(depends, same_copy(blank));    /* Separator */
  647.  
  648.     for (visit(original, target); !visited(target); visit_next(target)) {
  649.     target->depend_list = same_cat(target->depend_list, same_copy(depends));
  650.     }
  651.     visit_end();
  652.     same_free(depends);
  653.  
  654.     return original;
  655. }
  656.  
  657.  
  658. /*
  659.  * We know that variable is a singleton
  660.  */
  661.  
  662. void
  663. assign(variable, value)
  664. same_t
  665.     *variable,
  666.     *value;
  667. {
  668.     same_t *ptr;
  669.  
  670.     if ((ptr = same_search(variables, variable)) != 0) {
  671.     same_free(ptr->value_list);
  672.     variables = same_unlink(ptr);
  673.     same_free(ptr);
  674.     }
  675.     variable->value_list = value;
  676.     variables = same_cat(variables, variable);
  677. }
  678.  
  679. same_t *
  680. value_of(variable)
  681. same_t *variable;
  682. {
  683.     same_t *ptr = same_search(variables, variable);
  684.  
  685.     if (ptr == 0) {
  686.     return same_copy(null);
  687.     } else {
  688.     return same_copy(ptr->value_list);
  689.     }
  690. }
  691.  
  692.  
  693. same_t *
  694. expand_variables(token, free)
  695. same_t *token;
  696. int    free;
  697. {
  698.     same_t *head = 0;
  699.  
  700.     if (!free) {
  701.     token = same_copy(token);        /* Get our private copy */
  702.     }
  703.  
  704.     while (token) {
  705.     char *string = token->string->string;
  706.     same_t *tmp = same_unlink(token);
  707.  
  708.     if ((string[0] == '$') && (string[1] == '{')) {    /* Expand time */
  709.         int len = strlen(string);
  710.  
  711.         string[len-1] = 0;
  712.         head = same_cat(head, expand_variables(
  713.             value_of(same_item(string_lookup(string+2))), 1));
  714.         string[len-1] = '}';
  715.     } else {
  716.         head = same_cat(head, token);
  717.     }
  718.     token = tmp;
  719.     }
  720.     return head;
  721. }
  722.  
  723.  
  724. same_t *
  725. ws_merge(list)
  726. same_t *list;
  727. {
  728.     same_t *newlist = 0, *item;
  729.     int what = 0;
  730.  
  731.     while (list) {
  732.     switch (what) {
  733.     case 0:
  734.         if (isspace(list->string->string[0])) {
  735.         ;
  736.         } else {
  737.         item = same_item(list->string);
  738.         what = 1;
  739.         }
  740.         break;
  741.     case 1:
  742.         if (isspace(list->string->string[0])) {
  743.         newlist = same_cat(newlist, item);
  744.         item = 0;
  745.         what = 0;
  746.         } else {
  747.         item = same_merge(item, same_item(list->string));
  748.         what = 1;
  749.         }
  750.         break;
  751.     }
  752.     list = same_unlink(list);
  753.     }
  754.     return same_cat(newlist, item);
  755. }
  756.  
  757.  
  758. same_t *
  759. variable(var_name)
  760. same_t *var_name;
  761. {
  762.     int length = strlen(var_name->string->string);
  763.     same_t *resolved;
  764.     char *newname;
  765.  
  766.     if ((newname = malloc(length+1+3)) == 0) {
  767.     fprintf("Out of space for a variable name.\n");
  768.     exit(1);
  769.     }
  770.     newname[0] = '$';
  771.     newname[1] = '{';
  772.     strcpy(newname+2, var_name->string->string);
  773.     strcat(newname, "}");
  774.     resolved = same_item(string_lookup(newname));
  775.     free(newname);
  776.  
  777.     return resolved;
  778. }
  779.  
  780.  
  781. same_t *
  782. shell_variable(var_name)
  783. same_t *var_name;
  784. {
  785.     int length = strlen(var_name->string->string);
  786.     same_t *resolved;
  787.     char *newname;
  788.  
  789.     if ((newname = malloc(length+1+2)) == 0) {
  790.     fprintf("Out of space for a variable name.\n");
  791.     exit(1);
  792.     }
  793.     newname[0] = '$';
  794.     newname[1] = '$';
  795.     strcpy(newname+2, var_name->string->string);
  796.     resolved = same_item(string_lookup(newname));
  797.     free(newname);
  798.  
  799.     return resolved;
  800. }
  801.  
  802. same_t *
  803. for_statement(special, variable, list)
  804. same_t
  805.     *special,
  806.     *variable,
  807.     *list;
  808. {
  809.     variable->shell_item = special;
  810.     variable->value_list = list;
  811.     return variable;
  812. }
  813.  
  814. same_t *
  815. do_command(forlist, commands)
  816. same_t
  817.     *forlist,
  818.     *commands;
  819. {
  820.     same_t
  821.     *special,
  822.     *command_list = 0,
  823.     *new_commands,
  824.     *tmp,
  825.     *shell_item,
  826.     *value_list = forlist->value_list;
  827.     char
  828.     *tmpstr,
  829.     *variable_name = forlist->string->string;
  830.  
  831.     special = forlist->shell_item;
  832.     if (same_unlink(forlist->shell_item) != 0) {
  833.     yyerror("Unexpected second item in special part of do_command");
  834.     exit(1);
  835.     }
  836.  
  837.     while ((shell_item = value_list) != 0) {
  838.     value_list = same_unlink(shell_item);
  839.     /* Visit each item in commands.  For each shell variable which
  840.      * matches ours, replace it with ours.
  841.      */
  842.     new_commands = same_copy(commands);
  843.     for (visit(new_commands, tmp); !visited(tmp); visit_next(tmp)) {
  844.         tmpstr = tmp->string->string;
  845.         if ((tmpstr[0] == '$') && (tmpstr[1] == '$')) {
  846.         if (strcmp(tmpstr+2, variable_name) == 0) {
  847.             same_replace(tmp, same_copy(shell_item));
  848.         }
  849.         }
  850.     }
  851.     visit_end();
  852.     command_list = same_cat(command_list, new_commands);
  853.     }
  854.     return same_cat(command_list, same_copy(newline));
  855. }
  856.  
  857.  
  858. int
  859. Getchar()
  860. {
  861.     if (last_saved) {
  862.     last_saved = 0;
  863.     return last_char;
  864.     } else {
  865.     int c;
  866.     c = getchar();
  867.     switch (c) {
  868.     case '\n':
  869.         lineno++;
  870.         column = 0;
  871.         break;
  872.     default:
  873.         column++;
  874.     }
  875.     return c;
  876.     }
  877. }
  878.  
  879.  
  880. int
  881. token_type(string)
  882. char *string;
  883. {
  884.     switch (string[0]) {
  885.     case 'f':
  886.     if (strcmp(string, "for") == 0) {
  887.         return FOR;
  888.     }
  889.     break;
  890.     case 'd':
  891.     if (string[1] == 'o') {
  892.         if (strcmp(string, "do") == 0) {
  893.         return DO;
  894.         } else if (strcmp(string, "done") == 0) {
  895.         return DONE;
  896.         }
  897.     }
  898.     break;
  899.     case 'i':
  900.     if (strcmp(string, "in") == 0) {
  901.         return IN;
  902.     }
  903.     break;
  904.     default:
  905.     break;
  906.     }
  907.     return TOKEN;
  908. }
  909.  
  910.  
  911. yylex()
  912. {
  913. #define    ret_token(c)    if (bufptr != buffer) { \
  914.                 save(c); \
  915.                 *bufptr = 0; \
  916.                 bufptr = buffer; \
  917.                 yylval.string = string_lookup(buffer); \
  918.                 return token_type(buffer); \
  919.             }
  920. #define    save(c)    { last_char = c; last_saved = 1; }
  921. #if    defined(YYDEBUG)
  922. #define    Return(c)    if (yydebug) { \
  923.                 printf("[%d]", c); \
  924.                 fflush(stdout); \
  925.             } \
  926.             yyval.intval = c; \
  927.             return c;
  928. #else    /* defined(YYDEBUG) */
  929. #define    Return(y,c)    { yylval.intval = c; return y; }
  930. #endif    /* defined(YYDEBUG) */
  931.  
  932.  
  933.     static char buffer[500], *bufptr = buffer;
  934.     static int eof_found = 0;
  935.     int c;
  936.  
  937.     if (eof_found != 0) {
  938.     eof_found++;
  939.     if (eof_found > 2) {
  940.         fprintf(stderr, "End of file ignored.\n");
  941.         exit(1);
  942.     }
  943.     Return(EOF,0);
  944.     }
  945.     while ((c = Getchar()) != EOF) {
  946.     switch (c) {
  947.     case '#':
  948.         ret_token(c);
  949.         while (((c = Getchar()) != EOF) && (c != '\n')) {
  950.         ;
  951.         }
  952.         save(c);
  953.         break;
  954.     case '<':
  955.     case '?':
  956.         ret_token(c);
  957.         Return(MACRO_CHAR, c);
  958.     case '\t':
  959.     case ' ':
  960.         ret_token(c);
  961.         Return(WHITE_SPACE, c);
  962.     case '-':
  963.     case '@':
  964.     case ':':
  965.     case ';':
  966.     case '=':
  967.     case '$':
  968.     case '{':
  969.     case '}':
  970.     case '(':
  971.     case ')':
  972.         ret_token(c);
  973.         Return(c,c);
  974.     case '\'':
  975.     case '"':
  976.         if (bufptr != buffer) {
  977.         if (bufptr[-1] == '\\') {
  978.             bufptr[-1] = c;
  979.         }
  980.         break;
  981.         } else {
  982.         int newc;
  983.  
  984.         ret_token(c);
  985.         *bufptr++ = c;
  986.         while (((newc = Getchar()) != EOF) && (newc != c)) {
  987.             *bufptr++ = newc;
  988.         }
  989.         *bufptr++ = c;
  990.         *bufptr = 0;
  991.         bufptr = buffer;
  992.         yylval.string = string_lookup(buffer);
  993.         return QUOTED_STRING;
  994.         }
  995.     case '\n':
  996.         if (bufptr != buffer) {
  997.         if (bufptr[-1] == '\\') {
  998.             bufptr--;
  999.             if ((c = Getchar()) != '\t') {
  1000.             yyerror("continuation line doesn't begin with a tab");
  1001.             save(c);
  1002.             }
  1003.             ret_token(c);
  1004.             Return(WHITE_SPACE, c);
  1005.         }
  1006.         }
  1007.         ret_token(c);
  1008.         Return(NL, 0);
  1009.     default:
  1010.         *bufptr++ = c;
  1011.         break;
  1012.     }
  1013.     }
  1014.  
  1015.     eof_found = 1;
  1016.  
  1017.     ret_token(' ');
  1018.     Return(EOF, 0);
  1019. }
  1020.  
  1021. main()
  1022. {
  1023. #define    YYDEBUG
  1024.     extern int yydebug;
  1025.  
  1026.     null = same_item(string_lookup(""));
  1027.     newline = same_item(string_lookup("\n"));
  1028.     blank = same_item(string_lookup(" "));
  1029.     cwd_line = same_cat(same_copy(newline),
  1030.             same_cat(same_item(string_lookup("cd ${CWD}")),
  1031.                  same_copy(newline)));
  1032.  
  1033.     yyparse();
  1034.  
  1035.     do_dump();
  1036.  
  1037.     return 0;
  1038. }
  1039.  
  1040. #if    defined(YYDEBUG)
  1041. dump_same(same)
  1042. same_t *same;
  1043. {
  1044.     same_t *same2;
  1045.  
  1046.     for (visit(same, same2); !visited(same2); visit_next(same2)) {
  1047.     printf(same2->string->string);
  1048.     }
  1049.     visit_end();
  1050. }
  1051. #endif    /* YYDEBUG */
  1052.  
  1053. do_dump()
  1054. {
  1055.     string_t *string;
  1056.     same_t *same, *same2;
  1057.  
  1058.     if (yydebug > 1) {
  1059.     printf("strings...\n");
  1060.     for (string = strings; string; string = string->next) {
  1061.         printf("\t%s\n", string->string);
  1062.     }
  1063.     }
  1064.  
  1065.     printf("# variables...\n");
  1066.     for (visit(variables, same); !visited(same); visit_next(same)) {
  1067.     printf("%s =\t", same->string->string);
  1068.     for (visit(same->value_list, same2); !visited(same2);
  1069.                         visit_next(same2)) {
  1070.         printf(same2->string->string);
  1071.     }
  1072.     visit_end();
  1073.     printf("\n");
  1074.     }
  1075.     visit_end();
  1076.  
  1077.     printf("\n\n#targets...\n");
  1078.     for (visit(targets, same); !visited(same); visit_next(same)) {
  1079.     printf("\n%s:\t", same->string->string);
  1080.     for (visit(same->depend_list, same2); !visited(same2);
  1081.                         visit_next(same2)) {
  1082.         printf(same2->string->string);
  1083.     }
  1084.     visit_end();
  1085.     printf("\n\t");
  1086.     for (visit(same->action_list, same2); !visited(same2);
  1087.                         visit_next(same2)) {
  1088.         printf(same2->string->string);
  1089.         if (same2->string->string[0] == '\n') {
  1090.         printf("\t");
  1091.         }
  1092.     }
  1093.     visit_end();
  1094.     printf("\n");
  1095.     }
  1096.     visit_end();
  1097. }
  1098.