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

Diff for /src/usr.bin/lex/filter.c between version 1.3 and 1.4

version 1.3, 2015/11/19 22:25:53 version 1.4, 2015/11/19 22:52:40
Line 24 
Line 24 
 /*  PURPOSE. */  /*  PURPOSE. */
   
 #include "flexdef.h"  #include "flexdef.h"
 static const char * check_4_gnu_m4 =  static const char *check_4_gnu_m4 =
     "m4_dnl ifdef(`__gnu__', ,"  "m4_dnl ifdef(`__gnu__', ,"
     "`errprint(Flex requires GNU M4. Set the PATH or set the M4 environment variable to its path name.)"  "`errprint(Flex requires GNU M4. Set the PATH or set the M4 environment variable to its path name.)"
     " m4exit(2)')\n";  " m4exit(2)')\n";
   
   
 /** global chain. */  /** global chain. */
Line 40 
Line 40 
  *            not including argv[0].   *            not including argv[0].
  * @return newest filter in chain   * @return newest filter in chain
  */   */
 struct filter *filter_create_ext (struct filter *chain, const char *cmd,  struct filter *
                                   ...)  filter_create_ext(struct filter * chain, const char *cmd,
       ...)
 {  {
         struct filter *f;          struct filter *f;
         int     max_args;          int max_args;
         const char *s;          const char *s;
         va_list ap;          va_list ap;
   
         /* allocate and initialize new filter */          /* allocate and initialize new filter */
         f = (struct filter *) flex_alloc (sizeof (struct filter));          f = (struct filter *) flex_alloc(sizeof(struct filter));
         if (!f)          if (!f)
                 flexerror (_("flex_alloc failed (f) in filter_create_ext"));                  flexerror(_("flex_alloc failed (f) in filter_create_ext"));
         memset (f, 0, sizeof (*f));          memset(f, 0, sizeof(*f));
         f->filter_func = NULL;          f->filter_func = NULL;
         f->extra = NULL;          f->extra = NULL;
         f->next = NULL;          f->next = NULL;
Line 64 
Line 65 
                         chain = chain->next;                          chain = chain->next;
                 chain->next = f;                  chain->next = f;
         }          }
   
   
         /* allocate argv, and populate it with the argument list. */          /* allocate argv, and populate it with the argument list. */
         max_args = 8;          max_args = 8;
         f->argv = flex_alloc (sizeof (char *) * (max_args + 1));          f->argv = flex_alloc(sizeof(char *) * (max_args + 1));
         if (!f->argv)          if (!f->argv)
                 flexerror (_("flex_alloc failed (f->argv) in filter_create_ext"));                  flexerror(_("flex_alloc failed (f->argv) in filter_create_ext"));
         f->argv[f->argc++] = cmd;          f->argv[f->argc++] = cmd;
   
         va_start (ap, cmd);          va_start(ap, cmd);
         while ((s = va_arg (ap, const char *)) != NULL) {          while ((s = va_arg(ap, const char *)) != NULL) {
                 if (f->argc >= max_args) {                  if (f->argc >= max_args) {
                         max_args += 8;                          max_args += 8;
                         f->argv = flex_realloc (f->argv,                          f->argv = flex_realloc(f->argv,
                               sizeof (char *) * (max_args + 1));                              sizeof(char *) * (max_args + 1));
                 }                  }
                 f->argv[f->argc++] = s;                  f->argv[f->argc++] = s;
         }          }
         f->argv[f->argc] = NULL;          f->argv[f->argc] = NULL;
   
         va_end (ap);          va_end(ap);
         return f;          return f;
 }  }
   
Line 96 
Line 95 
  * @param extra optional user-defined data to pass to the filter.   * @param extra optional user-defined data to pass to the filter.
  * @return newest filter in chain   * @return newest filter in chain
  */   */
 struct filter *filter_create_int (struct filter *chain,  struct filter *
                                   int (*filter_func) (struct filter *),  filter_create_int(struct filter * chain,
                                   void *extra)      int (*filter_func) (struct filter *),
       void *extra)
 {  {
         struct filter *f;          struct filter *f;
   
         /* allocate and initialize new filter */          /* allocate and initialize new filter */
         f = (struct filter *) flex_alloc (sizeof (struct filter));          f = (struct filter *) flex_alloc(sizeof(struct filter));
         if (!f)          if (!f)
                 flexerror (_("flex_alloc failed in filter_create_int"));                  flexerror(_("flex_alloc failed in filter_create_int"));
         memset (f, 0, sizeof (*f));          memset(f, 0, sizeof(*f));
         f->next = NULL;          f->next = NULL;
         f->argc = 0;          f->argc = 0;
         f->argv = NULL;          f->argv = NULL;
Line 120 
Line 120 
                         chain = chain->next;                          chain = chain->next;
                 chain->next = f;                  chain->next = f;
         }          }
   
         return f;          return f;
 }  }
   
Line 128 
Line 127 
  *  @param chain The head of the chain.   *  @param chain The head of the chain.
  *  @return true on success.   *  @return true on success.
  */   */
 bool filter_apply_chain (struct filter * chain)  bool
   filter_apply_chain(struct filter * chain)
 {  {
         int     pid, pipes[2];          int pid, pipes[2];
         int     r;          int r;
         const int readsz = 512;          const int readsz = 512;
         char   *buf;          char *buf;
   
   
         /* Tricky recursion, since we want to begin the chain          /*
          * at the END. Why? Because we need all the forked processes           * Tricky recursion, since we want to begin the chain at the END.
          * to be children of the main flex process.           * Why? Because we need all the forked processes to be children of
            * the main flex process.
          */           */
         if (chain)          if (chain)
                 filter_apply_chain (chain->next);                  filter_apply_chain(chain->next);
         else          else
                 return true;                  return true;
   
         /* Now we are the right-most unprocessed link in the chain.          /*
            * Now we are the right-most unprocessed link in the chain.
          */           */
   
         fflush (stdout);          fflush(stdout);
         fflush (stderr);          fflush(stderr);
   
   
         if (pipe (pipes) == -1)          if (pipe(pipes) == -1)
                 flexerror (_("pipe failed"));                  flexerror(_("pipe failed"));
   
         if ((pid = fork ()) == -1)          if ((pid = fork()) == -1)
                 flexerror (_("fork failed"));                  flexerror(_("fork failed"));
   
         if (pid == 0) {          if (pid == 0) {
                 /* child */                  /* child */
   
         /* We need stdin (the FILE* stdin) to connect to this new pipe.                  /*
          * There is no portable way to set stdin to a new file descriptor,                   * We need stdin (the FILE* stdin) to connect to this new
          * as stdin is not an lvalue on some systems (BSD).                   * pipe. There is no portable way to set stdin to a new file
          * So we dup the new pipe onto the stdin descriptor and use a no-op fseek                   * descriptor, as stdin is not an lvalue on some systems
          * to sync the stream. This is a Hail Mary situation. It seems to work.                   * (BSD). So we dup the new pipe onto the stdin descriptor
          */                   * and use a no-op fseek to sync the stream. This is a Hail
                 close (pipes[1]);                   * Mary situation. It seems to work.
                    */
                   close(pipes[1]);
                 clearerr(stdin);                  clearerr(stdin);
                 if (dup2 (pipes[0], fileno (stdin)) == -1)                  if (dup2(pipes[0], fileno(stdin)) == -1)
                         flexfatal (_("dup2(pipes[0],0)"));                          flexfatal(_("dup2(pipes[0],0)"));
                 close (pipes[0]);                  close(pipes[0]);
                 fseek (stdin, 0, SEEK_CUR);                  fseek(stdin, 0, SEEK_CUR);
   
                 /* run as a filter, either internally or by exec */                  /* run as a filter, either internally or by exec */
                 if (chain->filter_func) {                  if (chain->filter_func) {
                         int     r;                          int r;
   
                         if ((r = chain->filter_func (chain)) == -1)                          if ((r = chain->filter_func(chain)) == -1)
                                 flexfatal (_("filter_func failed"));                                  flexfatal(_("filter_func failed"));
                         exit (0);                          exit(0);
                 }                  } else {
                 else {                          execvp(chain->argv[0],
                         execvp (chain->argv[0],                              (char **const) (chain->argv));
                                 (char **const) (chain->argv));                          lerrsf_fatal(_("exec of %s failed"),
                         lerrsf_fatal ( _("exec of %s failed"),  
                             chain->argv[0]);                              chain->argv[0]);
                 }                  }
   
                 exit (1);                  exit(1);
         }          }
   
         /* Parent */          /* Parent */
         close (pipes[0]);          close(pipes[0]);
         if (dup2 (pipes[1], fileno (stdout)) == -1)          if (dup2(pipes[1], fileno(stdout)) == -1)
                 flexfatal (_("dup2(pipes[1],1)"));                  flexfatal(_("dup2(pipes[1],1)"));
         close (pipes[1]);          close(pipes[1]);
         fseek (stdout, 0, SEEK_CUR);          fseek(stdout, 0, SEEK_CUR);
   
         return true;          return true;
 }  }
Line 207 
Line 209 
  * @param max_len the maximum length of the chain.   * @param max_len the maximum length of the chain.
  * @return the resulting length of the chain.   * @return the resulting length of the chain.
  */   */
 int filter_truncate (struct filter *chain, int max_len)  int
   filter_truncate(struct filter * chain, int max_len)
 {  {
         int     len = 1;          int len = 1;
   
         if (!chain)          if (!chain)
                 return 0;                  return 0;
Line 228 
Line 231 
  *  The header file name is in extra.   *  The header file name is in extra.
  *  @return 0 (zero) on success, and -1 on failure.   *  @return 0 (zero) on success, and -1 on failure.
  */   */
 int filter_tee_header (struct filter *chain)  int
   filter_tee_header(struct filter * chain)
 {  {
         /* This function reads from stdin and writes to both the C file and the          /*
          * header file at the same time.           * This function reads from stdin and writes to both the C file and
            * the header file at the same time.
          */           */
   
         const int readsz = 512;          const int readsz = 512;
         char   *buf;          char *buf;
         int     to_cfd = -1;          int to_cfd = -1;
         FILE   *to_c = NULL, *to_h = NULL;          FILE *to_c = NULL, *to_h = NULL;
         bool    write_header;          bool write_header;
   
         write_header = (chain->extra != NULL);          write_header = (chain->extra != NULL);
   
         /* Store a copy of the stdout pipe, which is already piped to C file          /*
            * Store a copy of the stdout pipe, which is already piped to C file
          * through the running chain. Then create a new pipe to the H file as           * through the running chain. Then create a new pipe to the H file as
          * stdout, and fork the rest of the chain again.           * stdout, and fork the rest of the chain again.
          */           */
   
         if ((to_cfd = dup (1)) == -1)          if ((to_cfd = dup(1)) == -1)
                 flexfatal (_("dup(1) failed"));                  flexfatal(_("dup(1) failed"));
         to_c = fdopen (to_cfd, "w");          to_c = fdopen(to_cfd, "w");
   
         if (write_header) {          if (write_header) {
                 if (freopen ((char *) chain->extra, "w", stdout) == NULL)                  if (freopen((char *) chain->extra, "w", stdout) == NULL)
                         flexfatal (_("freopen(headerfilename) failed"));                          flexfatal(_("freopen(headerfilename) failed"));
   
                 filter_apply_chain (chain->next);                  filter_apply_chain(chain->next);
                 to_h = stdout;                  to_h = stdout;
         }          }
           /*
         /* Now to_c is a pipe to the C branch, and to_h is a pipe to the H branch.           * Now to_c is a pipe to the C branch, and to_h is a pipe to the H
            * branch.
          */           */
   
         if (write_header) {          if (write_header) {
                 fputs (check_4_gnu_m4, to_h);                  fputs(check_4_gnu_m4, to_h);
                 fputs ("m4_changecom`'m4_dnl\n", to_h);                  fputs("m4_changecom`'m4_dnl\n", to_h);
                 fputs ("m4_changequote`'m4_dnl\n", to_h);                  fputs("m4_changequote`'m4_dnl\n", to_h);
                 fputs ("m4_changequote([[,]])[[]]m4_dnl\n", to_h);                  fputs("m4_changequote([[,]])[[]]m4_dnl\n", to_h);
                 fputs ("m4_define([[M4_YY_NOOP]])[[]]m4_dnl\n", to_h);                  fputs("m4_define([[M4_YY_NOOP]])[[]]m4_dnl\n", to_h);
                 fputs ("m4_define( [[M4_YY_IN_HEADER]],[[]])m4_dnl\n",                  fputs("m4_define( [[M4_YY_IN_HEADER]],[[]])m4_dnl\n",
                        to_h);                      to_h);
                 fprintf (to_h, "#ifndef %sHEADER_H\n", prefix);                  fprintf(to_h, "#ifndef %sHEADER_H\n", prefix);
                 fprintf (to_h, "#define %sHEADER_H 1\n", prefix);                  fprintf(to_h, "#define %sHEADER_H 1\n", prefix);
                 fprintf (to_h, "#define %sIN_HEADER 1\n\n", prefix);                  fprintf(to_h, "#define %sIN_HEADER 1\n\n", prefix);
                 fprintf (to_h,                  fprintf(to_h,
                          "m4_define( [[M4_YY_OUTFILE_NAME]],[[%s]])m4_dnl\n",                      "m4_define( [[M4_YY_OUTFILE_NAME]],[[%s]])m4_dnl\n",
                          headerfilename ? headerfilename : "<stdout>");                      headerfilename ? headerfilename : "<stdout>");
   
         }          }
           fputs(check_4_gnu_m4, to_c);
           fputs("m4_changecom`'m4_dnl\n", to_c);
           fputs("m4_changequote`'m4_dnl\n", to_c);
           fputs("m4_changequote([[,]])[[]]m4_dnl\n", to_c);
           fputs("m4_define([[M4_YY_NOOP]])[[]]m4_dnl\n", to_c);
           fprintf(to_c, "m4_define( [[M4_YY_OUTFILE_NAME]],[[%s]])m4_dnl\n",
               outfilename ? outfilename : "<stdout>");
   
         fputs (check_4_gnu_m4, to_c);          buf = (char *) flex_alloc(readsz);
         fputs ("m4_changecom`'m4_dnl\n", to_c);  
         fputs ("m4_changequote`'m4_dnl\n", to_c);  
         fputs ("m4_changequote([[,]])[[]]m4_dnl\n", to_c);  
         fputs ("m4_define([[M4_YY_NOOP]])[[]]m4_dnl\n", to_c);  
         fprintf (to_c, "m4_define( [[M4_YY_OUTFILE_NAME]],[[%s]])m4_dnl\n",  
                  outfilename ? outfilename : "<stdout>");  
   
         buf = (char *) flex_alloc (readsz);  
         if (!buf)          if (!buf)
                 flexerror (_("flex_alloc failed in filter_tee_header"));                  flexerror(_("flex_alloc failed in filter_tee_header"));
         while (fgets (buf, readsz, stdin)) {          while (fgets(buf, readsz, stdin)) {
                 fputs (buf, to_c);                  fputs(buf, to_c);
                 if (write_header)                  if (write_header)
                         fputs (buf, to_h);                          fputs(buf, to_h);
         }          }
   
         if (write_header) {          if (write_header) {
                 fprintf (to_h, "\n");                  fprintf(to_h, "\n");
   
                 /* write a fake line number. It will get fixed by the linedir filter. */                  /*
                 fprintf (to_h, "#line 4000 \"M4_YY_OUTFILE_NAME\"\n");                   * write a fake line number. It will get fixed by the linedir
                    * filter.
                    */
                   fprintf(to_h, "#line 4000 \"M4_YY_OUTFILE_NAME\"\n");
   
                 fprintf (to_h, "#undef %sIN_HEADER\n", prefix);                  fprintf(to_h, "#undef %sIN_HEADER\n", prefix);
                 fprintf (to_h, "#endif /* %sHEADER_H */\n", prefix);                  fprintf(to_h, "#endif /* %sHEADER_H */\n", prefix);
                 fputs ("m4_undefine( [[M4_YY_IN_HEADER]])m4_dnl\n", to_h);                  fputs("m4_undefine( [[M4_YY_IN_HEADER]])m4_dnl\n", to_h);
   
                 fflush (to_h);                  fflush(to_h);
                 if (ferror (to_h))                  if (ferror(to_h))
                         lerrsf (_("error writing output file %s"),                          lerrsf(_("error writing output file %s"),
                                 (char *) chain->extra);                              (char *) chain->extra);
   
                 else if (fclose (to_h))                  else if (fclose(to_h))
                         lerrsf (_("error closing output file %s"),                          lerrsf(_("error closing output file %s"),
                                 (char *) chain->extra);                              (char *) chain->extra);
         }          }
           fflush(to_c);
           if (ferror(to_c))
                   lerrsf(_("error writing output file %s"),
                       outfilename ? outfilename : "<stdout>");
   
         fflush (to_c);          else if (fclose(to_c))
         if (ferror (to_c))                  lerrsf(_("error closing output file %s"),
                 lerrsf (_("error writing output file %s"),                      outfilename ? outfilename : "<stdout>");
                         outfilename ? outfilename : "<stdout>");  
   
         else if (fclose (to_c))          while (wait(0) > 0);
                 lerrsf (_("error closing output file %s"),  
                         outfilename ? outfilename : "<stdout>");  
   
         while (wait (0) > 0) ;          exit(0);
   
         exit (0);  
         return 0;          return 0;
 }  }
   
Line 337 
Line 345 
  * not user code. This also happens to be a good place to squeeze multiple   * not user code. This also happens to be a good place to squeeze multiple
  * blank lines into a single blank line.   * blank lines into a single blank line.
  */   */
 int filter_fix_linedirs (struct filter *chain)  int
   filter_fix_linedirs(struct filter * chain)
 {  {
         char   *buf;          char *buf;
         const int readsz = 512;          const int readsz = 512;
         int     lineno = 1;          int lineno = 1;
         bool    in_gen = true;  /* in generated code */          bool in_gen = true;     /* in generated code */
         bool    last_was_blank = false;          bool last_was_blank = false;
   
         if (!chain)          if (!chain)
                 return 0;                  return 0;
   
         buf = (char *) flex_alloc (readsz);          buf = (char *) flex_alloc(readsz);
         if (!buf)          if (!buf)
                 flexerror (_("flex_alloc failed in filter_fix_linedirs"));                  flexerror(_("flex_alloc failed in filter_fix_linedirs"));
   
         while (fgets (buf, readsz, stdin)) {          while (fgets(buf, readsz, stdin)) {
   
                 regmatch_t m[10];                  regmatch_t m[10];
   
                 /* Check for #line directive. */                  /* Check for #line directive. */
                 if (buf[0] == '#'                  if (buf[0] == '#'
                         && regexec (&regex_linedir, buf, 3, m, 0) == 0) {                      && regexec(&regex_linedir, buf, 3, m, 0) == 0) {
   
                         int     num;                          int num;
                         char   *fname;                          char *fname;
   
                         /* extract the line number and filename */                          /* extract the line number and filename */
                         num = regmatch_strtol (&m[1], buf, NULL, 0);                          num = regmatch_strtol(&m[1], buf, NULL, 0);
                         fname = regmatch_dup (&m[2], buf);                          fname = regmatch_dup(&m[2], buf);
   
                         if (strcmp (fname,                          if (strcmp(fname,
                             outfilename ? outfilename : "<stdout>") == 0 ||                                  outfilename ? outfilename : "<stdout>") == 0 ||
                             strcmp (fname, headerfilename ? headerfilename :                              strcmp(fname, headerfilename ? headerfilename :
                             "<stdout>") == 0) {                                  "<stdout>") == 0) {
   
                                 char    *s1, *s2;                                  char *s1, *s2;
                                 char    filename[MAXLINE];                                  char filename[MAXLINE];
   
                                 s1 = fname;                                  s1 = fname;
                                 s2 = filename;                                  s2 = filename;
Line 393 
Line 402 
   
                                 /* Adjust the line directives. */                                  /* Adjust the line directives. */
                                 in_gen = true;                                  in_gen = true;
                                 snprintf (buf, readsz, "#line %d \"%s\"\n",                                  snprintf(buf, readsz, "#line %d \"%s\"\n",
                                           lineno + 1, filename);                                      lineno + 1, filename);
                         }                          } else {
                         else {                                  /*
                                 /* it's a #line directive for code we didn't write */                                   * it's a #line directive for code we didn't
                                    * write
                                    */
                                 in_gen = false;                                  in_gen = false;
                         }                          }
   
                         free (fname);                          free(fname);
                         last_was_blank = false;                          last_was_blank = false;
                 }                  }
   
                 /* squeeze blank lines from generated code */                  /* squeeze blank lines from generated code */
                 else if (in_gen &&                  else if (in_gen &&
                     regexec (&regex_blank_line, buf, 0, NULL, 0) == 0) {                      regexec(&regex_blank_line, buf, 0, NULL, 0) == 0) {
                         if (last_was_blank)                          if (last_was_blank)
                                 continue;                                  continue;
                         else                          else
                                 last_was_blank = true;                                  last_was_blank = true;
                 }                  } else {
   
                 else {  
                         /* it's a line of normal, non-empty code. */                          /* it's a line of normal, non-empty code. */
                         last_was_blank = false;                          last_was_blank = false;
                 }                  }
   
                 fputs (buf, stdout);                  fputs(buf, stdout);
                 lineno++;                  lineno++;
         }          }
         fflush (stdout);          fflush(stdout);
         if (ferror (stdout))          if (ferror(stdout))
                 lerrsf (_("error writing output file %s"),                  lerrsf(_("error writing output file %s"),
                         outfilename ? outfilename : "<stdout>");                      outfilename ? outfilename : "<stdout>");
   
         else if (fclose (stdout))          else if (fclose(stdout))
                 lerrsf (_("error closing output file %s"),                  lerrsf(_("error closing output file %s"),
                         outfilename ? outfilename : "<stdout>");                      outfilename ? outfilename : "<stdout>");
   
         return 0;          return 0;
 }  }

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.4