/[bison]/bison/lib/ansi2knr.c
ViewVC logotype

Diff of /bison/lib/ansi2knr.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1 by jthilo, Sun Jan 21 16:43:58 2001 UTC revision 1.1.2.1 by akim, Wed Oct 10 14:39:11 2001 UTC
# Line 1  Line 1 
1  /* Copyright (C) 1989, 1997, 1998 Aladdin Enterprises.  All rights reserved. */  /* Copyright (C) 1989, 2000 Aladdin Enterprises.  All rights reserved. */
2    
3  /*$Id$*/  /*$Id$*/
4  /* Convert ANSI C function definitions to K&R ("traditional C") syntax */  /* Convert ANSI C function definitions to K&R ("traditional C") syntax */
# Line 37  program under the GPL. Line 37  program under the GPL.
37   * There are no error messages.   * There are no error messages.
38   *   *
39   * ansi2knr recognizes function definitions by seeing a non-keyword   * ansi2knr recognizes function definitions by seeing a non-keyword
40   * identifier at the left margin, followed by a left parenthesis,   * identifier at the left margin, followed by a left parenthesis, with a
41   * with a right parenthesis as the last character on the line,   * right parenthesis as the last character on the line, and with a left
42   * and with a left brace as the first token on the following line   * brace as the first token on the following line (ignoring possible
43   * (ignoring possible intervening comments), except that a line   * intervening comments and/or preprocessor directives), except that a line
44   * consisting of only   * consisting of only
45   *      identifier1(identifier2)   *      identifier1(identifier2)
46   * will not be considered a function definition unless identifier2 is   * will not be considered a function definition unless identifier2 is
47   * the word "void".  ansi2knr will recognize a multi-line header provided   * the word "void", and a line consisting of
48   * that no intervening line ends with a left or right brace or a semicolon.   *      identifier1(identifier2, <<arbitrary>>)
49   * These algorithms ignore whitespace and comments, except that   * will not be considered a function definition.
50   * the function name must be the first thing on the line.   * ansi2knr will recognize a multi-line header provided that no intervening
51   * The following constructs will confuse it:   * line ends with a left or right brace or a semicolon.  These algorithms
52     * ignore whitespace, comments, and preprocessor directives, except that
53     * the function name must be the first thing on the line.  The following
54     * constructs will confuse it:
55   *      - Any other construct that starts at the left margin and   *      - Any other construct that starts at the left margin and
56   *          follows the above syntax (such as a macro or function call).   *          follows the above syntax (such as a macro or function call).
57   *      - Some macros that tinker with the syntax of the function header.   *      - Some macros that tinker with the syntax of function headers.
58   */   */
59    
60  /*  /*
61   * The original and principal author of ansi2knr is L. Peter Deutsch   * The original and principal author of ansi2knr is L. Peter Deutsch
62   * <ghost@aladdin.com>.  Other authors are noted in the change history   * <ghost@aladdin.com>.  Other authors are noted in the change history
63   * that follows (in reverse chronological order):   * that follows (in reverse chronological order):
64    
65            lpd 2000-04-12 backs out Eggert's changes because of bugs:
66            - concatlits didn't declare the type of its bufend argument;
67            - concatlits didn't't recognize when it was inside a comment;
68            - scanstring could scan backward past the beginning of the string; when
69            - the check for \ + newline in scanstring was unnecessary.
70    
71            2000-03-05  Paul Eggert  <eggert@twinsun.com>
72    
73            Add support for concatenated string literals.
74            * ansi2knr.c (concatlits): New decl.
75            (main): Invoke concatlits to concatenate string literals.
76            (scanstring): Handle backslash-newline correctly.  Work with
77            character constants.  Fix bug when scanning backwards through
78            backslash-quote.  Check for unterminated strings.
79            (convert1): Parse character constants, too.
80            (appendline, concatlits): New functions.
81            * ansi2knr.1: Document this.
82    
83            lpd 1999-08-17 added code to allow preprocessor directives
84                    wherever comments are allowed
85            lpd 1999-04-12 added minor fixes from Pavel Roskin
86                    <pavel_roskin@geocities.com> for clean compilation with
87                    gcc -W -Wall
88            lpd 1999-03-22 added hack to recognize lines consisting of
89                    identifier1(identifier2, xxx) as *not* being procedures
90            lpd 1999-02-03 made indentation of preprocessor commands consistent
91            lpd 1999-01-28 fixed two bugs: a '/' in an argument list caused an
92                    endless loop; quoted strings within an argument list
93                    confused the parser
94            lpd 1999-01-24 added a check for write errors on the output,
95                    suggested by Jim Meyering <meyering@ascend.com>
96          lpd 1998-11-09 added further hack to recognize identifier(void)          lpd 1998-11-09 added further hack to recognize identifier(void)
97                  as being a procedure                  as being a procedure
98          lpd 1998-10-23 added hack to recognize lines consisting of          lpd 1998-10-23 added hack to recognize lines consisting of
# Line 153  program under the GPL. Line 188  program under the GPL.
188    
189  #endif  #endif
190    
191    /* Define NULL (for *very* old compilers). */
192    #ifndef NULL
193    # define NULL (0)
194    #endif
195    
196  /*  /*
197   * The ctype macros don't always handle 8-bit characters correctly.   * The ctype macros don't always handle 8-bit characters correctly.
198   * Compensate for this here.   * Compensate for this here.
199   */   */
200  #ifdef isascii  #ifdef isascii
201  #  undef HAVE_ISASCII           /* just in case */  # undef HAVE_ISASCII            /* just in case */
202  #  define HAVE_ISASCII 1  # define HAVE_ISASCII 1
203  #else  #else
204  #endif  #endif
205  #if STDC_HEADERS || !HAVE_ISASCII  #if STDC_HEADERS || !HAVE_ISASCII
206  #  define is_ascii(c) 1  # define is_ascii(c) 1
207  #else  #else
208  #  define is_ascii(c) isascii(c)  # define is_ascii(c) isascii(c)
209  #endif  #endif
210    
211  #define is_space(c) (is_ascii(c) && isspace(c))  #define is_space(c) (is_ascii(c) && isspace(c))
# Line 177  program under the GPL. Line 217  program under the GPL.
217  #define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_')  #define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_')
218    
219  /* Forward references */  /* Forward references */
220    char *ppdirforward();
221    char *ppdirbackward();
222  char *skipspace();  char *skipspace();
223    char *scanstring();
224  int writeblanks();  int writeblanks();
225  int test1();  int test1();
226  int convert1();  int convert1();
# Line 190  main(argc, argv) Line 233  main(argc, argv)
233  {       FILE *in = stdin;  {       FILE *in = stdin;
234          FILE *out = stdout;          FILE *out = stdout;
235          char *filename = 0;          char *filename = 0;
236            char *program_name = argv[0];
237            char *output_name = 0;
238  #define bufsize 5000                    /* arbitrary size */  #define bufsize 5000                    /* arbitrary size */
239          char *buf;          char *buf;
240          char *line;          char *line;
# Line 205  main(argc, argv) Line 250  main(argc, argv)
250           * check for this switch for backward compatibility.           * check for this switch for backward compatibility.
251           */           */
252          int convert_varargs = 1;          int convert_varargs = 1;
253            int output_error;
254    
255          while ( argc > 1 && argv[1][0] == '-' ) {          while ( argc > 1 && argv[1][0] == '-' ) {
256            if ( !strcmp(argv[1], "--varargs") ) {            if ( !strcmp(argv[1], "--varargs") ) {
# Line 219  main(argc, argv) Line 265  main(argc, argv)
265              argv += 2;              argv += 2;
266              continue;              continue;
267            }            }
268            fprintf(stderr, "Unrecognized switch: %s\n", argv[1]);            fprintf(stderr, "%s: Unrecognized switch: %s\n", program_name,
269                      argv[1]);
270            fprintf(stderr, usage);            fprintf(stderr, usage);
271            exit(1);            exit(1);
272          }          }
# Line 229  main(argc, argv) Line 276  main(argc, argv)
276                  fprintf(stderr, usage);                  fprintf(stderr, usage);
277                  exit(0);                  exit(0);
278          case 3:          case 3:
279                  out = fopen(argv[2], "w");                  output_name = argv[2];
280                    out = fopen(output_name, "w");
281                  if ( out == NULL ) {                  if ( out == NULL ) {
282                    fprintf(stderr, "Cannot open output file %s\n", argv[2]);                    fprintf(stderr, "%s: Cannot open output file %s\n",
283                              program_name, output_name);
284                    exit(1);                    exit(1);
285                  }                  }
286                  /* falls through */                  /* falls through */
287          case 2:          case 2:
288                  in = fopen(argv[1], "r");                  in = fopen(argv[1], "r");
289                  if ( in == NULL ) {                  if ( in == NULL ) {
290                    fprintf(stderr, "Cannot open input file %s\n", argv[1]);                    fprintf(stderr, "%s: Cannot open input file %s\n",
291                              program_name, argv[1]);
292                    exit(1);                    exit(1);
293                  }                  }
294                  if ( filename == 0 )                  if ( filename == 0 )
# Line 250  main(argc, argv) Line 300  main(argc, argv)
300          if ( filename )          if ( filename )
301            fprintf(out, "#line 1 \"%s\"\n", filename);            fprintf(out, "#line 1 \"%s\"\n", filename);
302          buf = malloc(bufsize);          buf = malloc(bufsize);
303            if ( buf == NULL )
304               {
305                    fprintf(stderr, "Unable to allocate read buffer!\n");
306                    exit(1);
307               }
308          line = buf;          line = buf;
309          while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )          while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
310             {             {
# Line 266  f:                     if ( line >= buf + (bufsize - 1) ) Line 321  f:                     if ( line >= buf + (bufsize - 1) )
321                            goto wl;                            goto wl;
322                          if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL )                          if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL )
323                            goto wl;                            goto wl;
324                          switch ( *skipspace(more, 1) )                          switch ( *skipspace(ppdirforward(more), 1) )
325                            {                            {
326                            case '{':                            case '{':
327                              /* Definitely a function header. */                              /* Definitely a function header. */
# Line 300  wl:                    fputs(buf, out); Line 355  wl:                    fputs(buf, out);
355          if ( line != buf )          if ( line != buf )
356            fputs(buf, out);            fputs(buf, out);
357          free(buf);          free(buf);
358          if ( out != stdout )          if ( output_name ) {
359            fclose(out);            output_error = ferror(out);
360              output_error |= fclose(out);
361            } else {                /* out == stdout */
362              fflush(out);
363              output_error = ferror(out);
364            }
365            if ( output_error ) {
366              fprintf(stderr, "%s: error writing to %s\n", program_name,
367                      (output_name ? output_name : "stdout"));
368              exit(1);
369            }
370          if ( in != stdin )          if ( in != stdin )
371            fclose(in);            fclose(in);
372          return 0;          return 0;
373  }  }
374    
375  /* Skip over space and comments, in either direction. */  /*
376     * Skip forward or backward over one or more preprocessor directives.
377     */
378    char *
379    ppdirforward(p)
380        char *p;
381    {
382        for (; *p == '#'; ++p) {
383            for (; *p != '\r' && *p != '\n'; ++p)
384                if (*p == 0)
385                    return p;
386            if (*p == '\r' && p[1] == '\n')
387                ++p;
388        }
389        return p;
390    }
391    char *
392    ppdirbackward(p, limit)
393        char *p;
394        char *limit;
395    {
396        char *np = p;
397    
398        for (;; p = --np) {
399            if (*np == '\n' && np[-1] == '\r')
400                --np;
401            for (; np > limit && np[-1] != '\r' && np[-1] != '\n'; --np)
402                if (np[-1] == 0)
403                    return np;
404            if (*np != '#')
405                return p;
406        }
407    }
408    
409    /*
410     * Skip over whitespace, comments, and preprocessor directives,
411     * in either direction.
412     */
413  char *  char *
414  skipspace(p, dir)  skipspace(p, dir)
415      register char *p;      char *p;
416      register int dir;                   /* 1 for forward, -1 for backward */      int dir;                    /* 1 for forward, -1 for backward */
417  {       for ( ; ; )  {
418             {    while ( is_space(*p) )      for ( ; ; ) {
419                    p += dir;          while ( is_space(*p) )
420                  if ( !(*p == '/' && p[dir] == '*') )              p += dir;
421                    break;          if ( !(*p == '/' && p[dir] == '*') )
422                  p += dir;  p += dir;              break;
423                  while ( !(*p == '*' && p[dir] == '/') )          p += dir;  p += dir;
424                     {    if ( *p == 0 )          while ( !(*p == '*' && p[dir] == '/') ) {
425                            return p;     /* multi-line comment?? */              if ( *p == 0 )
426                          p += dir;                  return p;       /* multi-line comment?? */
427                     }              p += dir;
428                  p += dir;  p += dir;          }
429             }          p += dir;  p += dir;
430          return p;      }
431        return p;
432    }
433    
434    /* Scan over a quoted string, in either direction. */
435    char *
436    scanstring(p, dir)
437        char *p;
438        int dir;
439    {
440        for (p += dir; ; p += dir)
441            if (*p == '"' && p[-dir] != '\\')
442                return p + dir;
443  }  }
444    
445  /*  /*
# Line 359  writeblanks(start, end) Line 473  writeblanks(start, end)
473  int  int
474  test1(buf)  test1(buf)
475      char *buf;      char *buf;
476  {       register char *p = buf;  {       char *p = buf;
477          char *bend;          char *bend;
478          char *endfn;          char *endfn;
479          int contin;          int contin;
480    
481          if ( !isidfirstchar(*p) )          if ( !isidfirstchar(*p) )
482            return 0;             /* no name at left margin */            return 0;             /* no name at left margin */
483          bend = skipspace(buf + strlen(buf) - 1, -1);          bend = skipspace(ppdirbackward(buf + strlen(buf) - 1, buf), -1);
484          switch ( *bend )          switch ( *bend )
485             {             {
486             case ';': contin = 0 /*2*/; break;             case ';': contin = 0 /*2*/; break;
# Line 396  test1(buf) Line 510  test1(buf)
510                     };                     };
511                  char **key = words;                  char **key = words;
512                  char *kp;                  char *kp;
513                  int len = endfn - buf;                  unsigned len = endfn - buf;
514    
515                  while ( (kp = *key) != 0 )                  while ( (kp = *key) != 0 )
516                     {    if ( strlen(kp) == len && !strncmp(kp, buf, len) )                     {    if ( strlen(kp) == len && !strncmp(kp, buf, len) )
# Line 409  test1(buf) Line 523  test1(buf)
523                 int len;                 int len;
524                 /*                 /*
525                  * Check for identifier1(identifier2) and not                  * Check for identifier1(identifier2) and not
526                  * identifier1(void).                  * identifier1(void), or identifier1(identifier2, xxxx).
527                  */                  */
528    
529                 while ( isidchar(*p) )                 while ( isidchar(*p) )
530                     p++;                     p++;
531                 len = p - id;                 len = p - id;
532                 p = skipspace(p, 1);                 p = skipspace(p, 1);
533                 if ( *p == ')' && (len != 4 || strncmp(id, "void", 4)) )                 if (*p == ',' ||
534                       (*p == ')' && (len != 4 || strncmp(id, "void", 4)))
535                       )
536                     return 0;    /* not a function */                     return 0;    /* not a function */
537             }             }
538          /*          /*
# Line 443  convert1(buf, out, header, convert_varar Line 559  convert1(buf, out, header, convert_varar
559      int header;                 /* Boolean */      int header;                 /* Boolean */
560      int convert_varargs;        /* Boolean */      int convert_varargs;        /* Boolean */
561  {       char *endfn;  {       char *endfn;
562          register char *p;          char *p;
563          /*          /*
564           * The breaks table contains pointers to the beginning and end           * The breaks table contains pointers to the beginning and end
565           * of each argument.           * of each argument.
# Line 461  convert1(buf, out, header, convert_varar Line 577  convert1(buf, out, header, convert_varar
577            ;            ;
578  top:    p = endfn;  top:    p = endfn;
579          breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);          breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
580          if ( breaks == 0 )          if ( breaks == NULL )
581             {    /* Couldn't allocate break table, give up */             {    /* Couldn't allocate break table, give up */
582                  fprintf(stderr, "Unable to allocate break table!\n");                  fprintf(stderr, "Unable to allocate break table!\n");
583                  fputs(buf, out);                  fputs(buf, out);
# Line 473  top:   p = endfn; Line 589  top:   p = endfn;
589          do          do
590             {    int level = 0;             {    int level = 0;
591                  char *lp = NULL;                  char *lp = NULL;
592                  char *rp;                  char *rp = NULL;
593                  char *end = NULL;                  char *end = NULL;
594    
595                  if ( bp >= btop )                  if ( bp >= btop )
# Line 500  top:   p = endfn; Line 616  top:   p = endfn;
616                                  else rp = p;                                  else rp = p;
617                                  break;                                  break;
618                             case '/':                             case '/':
619                                  p = skipspace(p, 1) - 1;                                  if (p[1] == '*')
620                                        p = skipspace(p, 1) - 1;
621                                  break;                                  break;
622                               case '"':
623                                   p = scanstring(p, 1) - 1;
624                                   break;
625                             default:                             default:
626                                  ;                                  ;
627                             }                             }
628                     }                     }
629                  /* Erase any embedded prototype parameters. */                  /* Erase any embedded prototype parameters. */
630                  if ( lp )                  if ( lp && rp )
631                    writeblanks(lp + 1, rp);                    writeblanks(lp + 1, rp);
632                  p--;                    /* back up over terminator */                  p--;                    /* back up over terminator */
633                  /* Find the name being declared. */                  /* Find the name being declared. */
# Line 523  top:   p = endfn; Line 643  top:   p = endfn;
643                                  while ( level )                                  while ( level )
644                                   switch ( *--p )                                   switch ( *--p )
645                                     {                                     {
646                                     case ']': case ')': level++; break;                                     case ']': case ')':
647                                     case '[': case '(': level--; break;                                         level++;
648                                     case '/': p = skipspace(p, -1) + 1; break;                                         break;
649                                       case '[': case '(':
650                                           level--;
651                                           break;
652                                       case '/':
653                                           if (p > buf && p[-1] == '*')
654                                               p = skipspace(p, -1) + 1;
655                                           break;
656                                       case '"':
657                                           p = scanstring(p, -1) + 1;
658                                           break;
659                                     default: ;                                     default: ;
660                                     }                                     }
661                             }                             }

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.1.2.1

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26