[BACK]Return to for.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / make

Diff for /src/usr.bin/make/for.c between version 1.10 and 1.11

version 1.10, 1999/12/16 17:02:45 version 1.11, 1999/12/16 17:07:20
Line 92 
Line 92 
  * ...   * ...
  * .endfor   * .endfor
  *   *
  * The trick is to look for the matching end inside for for loop   * The trick is to look for the matching .end inside .for loops.
  * To do that, we count the current nesting level of the for loops.   * To do that, we keep track of the nesting level of .for loops
  * and the .endfor statements, accumulating all the statements between   * and matching .endfor statements, accumulating all statements between
  * the initial .for loop and the matching .endfor;   * the initial .for loop and the matching .endfor,
  * then we evaluate the for loop for each variable in the varlist.   * then we evaluate the .for loop for each variable in the varlist.
  */   */
   
 static int        forLevel = 0;         /* Nesting level             */  /* State of a for loop.  */
 static char      *forVar;               /* Iteration variable        */  struct For_ {
 static BUFFER     forBuf;               /* Commands in loop          */      char                *text;          /* unexpanded text              */
 static Lst        forLst;               /* List of items             */      char                *var;           /* Index name                   */
 static unsigned long forLineno;         /* Line at beginning of loop */      Lst                 lst;            /* List of items                */
       BUFFER              buf;            /* Accumulating text            */
       unsigned long       lineno;         /* Line number at start of loop */
       unsigned long       level;          /* Nesting level                */
   };
   
 /*  static int ForExec __P((ClientData, ClientData));
  * State of a for loop.  
  */  
 typedef struct _For {  
     Buffer        buf;                  /* Unexpanded buffer         */  
     char*         var;                  /* Index name                */  
     Lst           lst;                  /* List of variables         */  
     unsigned long lineno;  
 } For;  
   
 static int ForExec      __P((ClientData, ClientData));  
 static void build_words_list __P((Lst, const char *));  static void build_words_list __P((Lst, const char *));
   
 /* Cut a string into words, stuff that into list.  */  /* Cut a string into words, stuff that into list.  */
Line 133 
Line 127 
             break;              break;
         for (wrd = s; *s != '\0' && !isspace(*s); s++)          for (wrd = s; *s != '\0' && !isspace(*s); s++)
             continue;              continue;
             /* note that we fill the list backward, since          /* note that we fill the list backward, since
              * Parse_FromString stacks strings.  */           * Parse_FromString stacks strings.  */
         Lst_AtFront(lst, (ClientData)interval_dup(wrd, s));          Lst_AtFront(lst, (ClientData)interval_dup(wrd, s));
     }      }
 }  }
   
   /*
 /*-  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  * For_Eval --   * For_Eval --
  *      Evaluate the for loop in the passed line. The line   *      Evaluate the for loop in the passed line. The line
Line 148 
Line 141 
  *          .for <variable> in <varlist>   *          .for <variable> in <varlist>
  *   *
  * Results:   * Results:
  *      TRUE: We found a for loop, or we are inside a for loop   *      Loop structure, to accumulate further lines.
  *      FALSE: We did not find a for loop, or we found the end of the for   *      NULL if this was not a for loop after all.
  *             for loop.  
  *  
  * Side Effects:  
  *      None.  
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 int  
 For_Eval (line)  For *
   For_Eval(line)
     char            *line;    /* Line to parse */      char            *line;    /* Line to parse */
 {  {
     char            *ptr = line;      char        *ptr = line;
     int             level;      /* Level at which to report errors. */      char        *wrd;
       char        *sub;
       char        *endVar;
       For         *arg;
   
     level = PARSE_FATAL;      for (ptr++; *ptr && isspace(*ptr); ptr++)
           continue;
       /* If we are not in a for loop quickly determine if the statement is
        * a for.  */
       if (ptr[0] != 'f' || ptr[1] != 'o' || ptr[2] != 'r' ||
           !isspace(ptr[3]))
           return NULL;
       ptr += 4;
   
       while (*ptr && isspace(*ptr))
           ptr++;
   
     if (forLevel == 0) {      /* We found a for loop, and now we are going to parse it.  */
         char        *endVar;  
         char        *sub;  
         char        *wrd;  
   
         for (ptr++; *ptr && isspace((unsigned char) *ptr); ptr++)      /* Grab the variable.  */
             continue;      for (wrd = ptr; *ptr && !isspace(*ptr); ptr++)
         /* If we are not in a for loop quickly determine if the statement is          continue;
          * a for.  */      if (ptr - wrd == 0) {
         if (ptr[0] != 'f' || ptr[1] != 'o' || ptr[2] != 'r' ||          Parse_Error(PARSE_FATAL, "missing variable in for");
             !isspace((unsigned char) ptr[3]))          return 0;
             return FALSE;      }
         ptr += 3;      endVar = ptr++;
   
         /* We found a for loop, and now we are going to parse it.  */      while (*ptr && isspace(*ptr))
         while (*ptr && isspace((unsigned char) *ptr))          ptr++;
             ptr++;  
   
         /* Grab the variable.  */      /* Grab the `in'.  */
         for (wrd = ptr; *ptr && !isspace((unsigned char) *ptr); ptr++)      if (ptr[0] != 'i' || ptr[1] != 'n' ||
             continue;          !isspace(ptr[2])) {
           Parse_Error(PARSE_FATAL, "missing `in' in for");
           printf("%s\n", ptr);
           return NULL;
       }
       ptr += 3;
   
         if (ptr - wrd == 0) {      /* .for loop is go, collate what we need.  */
             Parse_Error(level, "missing variable in for");      arg = emalloc(sizeof(*arg));
             return 0;      arg->var = interval_dup(wrd, endVar);
         }  
         endVar = ptr++;  
   
         while (*ptr && isspace((unsigned char) *ptr))      /* Make a list with the remaining words.  */
             ptr++;      sub = Var_Subst(NULL, ptr, VAR_GLOBAL, FALSE);
       if (DEBUG(FOR))
           (void)fprintf(stderr, "For: Iterator %s List %s\n", arg->var, sub);
   
         /* Grab the `in'.  */      arg->lst = Lst_Init(FALSE);
         if (ptr[0] != 'i' || ptr[1] != 'n' ||      build_words_list(arg->lst, sub);
             !isspace((unsigned char) ptr[2])) {      free(sub);
             Parse_Error(level, "missing `in' in for");      arg->lineno = Parse_Getlineno();
             printf("%s\n", ptr);      arg->level = 1;
             return 0;      Buf_Init(&arg->buf, 0);
         }  
         ptr += 3;  
   
         /* .for loop is go, collate what we need.  */      return arg;
         forVar = interval_dup(wrd, endVar);  }
   
         /* Make a list with the remaining words.  */  
         sub = Var_Subst(NULL, ptr, VAR_GLOBAL, FALSE);  /*-
         if (DEBUG(FOR))   *-----------------------------------------------------------------------
             (void)fprintf(stderr, "For: Iterator %s List %s\n", forVar, sub);   * For_Accumulate --
    *      Accumulate lines in a for loop, until we find the matching endfor.
    *
    * Results:
    *      TRUE: keep accumulating lines.
    *      FALSE: We found the matching .endfor
    *
    * Side Effects:
    *      Accumulate lines in arg.
    *-----------------------------------------------------------------------
    */
   Boolean
   For_Accumulate(arg, line)
       For             *arg;
       const char      *line;    /* Line to parse */
   {
       const char      *ptr = line;
   
         forLst = Lst_Init(FALSE);      assert(arg->level > 0);
         build_words_list(forLst, sub);  
         free(sub);  
         forLineno = Parse_Getlineno();  
         Buf_Init(&forBuf, 0);  
         forLevel++;  
         return 1;  
     }  
     else if (*ptr == '.') {  
   
         for (ptr++; *ptr && isspace((unsigned char) *ptr); ptr++)      if (*ptr == '.') {
   
           for (ptr++; *ptr && isspace(*ptr); ptr++)
             continue;              continue;
   
         if (strncmp(ptr, "endfor", 6) == 0 &&          if (strncmp(ptr, "endfor", 6) == 0 &&
             (isspace((unsigned char) ptr[6]) || !ptr[6])) {              (isspace(ptr[6]) || !ptr[6])) {
             if (DEBUG(FOR))              if (DEBUG(FOR))
                 (void) fprintf(stderr, "For: end for %d\n", forLevel);                  (void)fprintf(stderr, "For: end for %lu\n", arg->level);
             if (--forLevel < 0) {              /* If matching endfor, don't add line to buffer.  */
                 Parse_Error(level, "for-less endfor");              if (--arg->level == 0)
                 return 0;                  return FALSE;
             }  
         }          }
         else if (strncmp(ptr, "for", 3) == 0 &&          else if (strncmp(ptr, "for", 3) == 0 &&
                  isspace((unsigned char) ptr[3])) {                   isspace(ptr[3])) {
             forLevel++;              arg->level++;
             if (DEBUG(FOR))              if (DEBUG(FOR))
                 (void) fprintf(stderr, "For: new loop %d\n", forLevel);                  (void)fprintf(stderr, "For: new loop %lu\n", arg->level);
         }          }
     }      }
       Buf_AddString(&arg->buf, line);
     if (forLevel != 0) {      Buf_AddChar(&arg->buf, '\n');
         Buf_AddString(&forBuf, line);      return TRUE;
         Buf_AddChar(&forBuf, '\n');  
         return 1;  
     }  
     else {  
         return 0;  
     }  
 }  }
   
   
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  * ForExec --   * ForExec --
  *      Expand the for loop for this index and push it in the Makefile   *      Expand the for loop for this index and push it in the Makefile
  *  
  * Results:  
  *      None.  
  *  
  * Side Effects:  
  *      None.  
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static int  static int
Line 273 
Line 270 
     ClientData namep;      ClientData namep;
     ClientData argp;      ClientData argp;
 {  {
     char *name = (char *) namep;      char *name = (char *)namep;
     For *arg = (For *) argp;      For *arg = (For *)argp;
   
     Var_Set(arg->var, name, VAR_GLOBAL);      Var_Set(arg->var, name, VAR_GLOBAL);
     if (DEBUG(FOR))      if (DEBUG(FOR))
         (void) fprintf(stderr, "--- %s = %s\n", arg->var, name);          (void)fprintf(stderr, "--- %s = %s\n", arg->var, name);
     Parse_FromString(Var_Subst(arg->var, Buf_Retrieve(arg->buf),      Parse_FromString(Var_Subst(arg->var, arg->text, VAR_GLOBAL, FALSE),
                                VAR_GLOBAL, FALSE), arg->lineno);          arg->lineno);
     Var_Delete(arg->var, VAR_GLOBAL);      Var_Delete(arg->var, VAR_GLOBAL);
   
     return 0;      return 0;
 }  }
   
Line 289 
Line 286 
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  * For_Run --   * For_Run --
  *      Run the for loop, immitating the actions of an include file   *      Run the for loop, pushing expanded lines for reparse
  *  
  * Results:  
  *      None.  
  *  
  * Side Effects:  
  *      None.  
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
   
 void  void
 For_Run()  For_Run(arg)
       For *arg;
 {  {
     For arg;      arg->text = Buf_Retrieve(&arg->buf);
   
     if (forVar == NULL || forLst == NULL)      Lst_ForEach(arg->lst, ForExec, (ClientData)arg);
         return;      free(arg->var);
     arg.var = forVar;      free(arg->text);
     arg.buf = &forBuf;      Lst_Destroy(arg->lst, (void (*) __P((ClientData)))free);
     arg.lst = forLst;      free(arg);
     arg.lineno = forLineno;  
     forVar = NULL;  
     forLst = NULL;  
   
     Lst_ForEach(arg.lst, ForExec, (ClientData) &arg);  
   
     free((Address)arg.var);  
     Lst_Destroy(arg.lst, (void (*) __P((ClientData))) free);  
     Buf_Destroy(arg.buf);  
 }  }

Legend:
Removed from v.1.10  
changed lines
  Added in v.1.11