]> sjero.net Git - wget/commitdiff
[svn] Update ansi2knr.c and ansi2knr.1.
authorhniksic <devnull@localhost>
Sat, 4 Oct 2003 10:34:10 +0000 (03:34 -0700)
committerhniksic <devnull@localhost>
Sat, 4 Oct 2003 10:34:10 +0000 (03:34 -0700)
Update log.c to use `...' in function definition argument lists
unconditionally.

doc/ansi2knr.1
src/ChangeLog
src/ansi2knr.c
src/log.c

index 434ce8f042436aaabe216835dbc51d82e8195504..f9ee5a631c2ee870819fefe6c1c701eb426d1508 100644 (file)
@@ -1,19 +1,36 @@
-.TH ANSI2KNR 1 "31 December 1990" 
+.TH ANSI2KNR 1 "19 Jan 1996"
 .SH NAME
 ansi2knr \- convert ANSI C to Kernighan & Ritchie C
 .SH SYNOPSIS
 .I ansi2knr
-input_file output_file
+[--varargs] input_file [output_file]
 .SH DESCRIPTION
 If no output_file is supplied, output goes to stdout.
 .br
 There are no error messages.
 .sp
 .I ansi2knr
-recognizes functions by seeing a non-keyword identifier at the left margin, followed by a left parenthesis, with a right parenthesis as the last character on the line.  It will recognize a multi-line header if the last character on each line but the last is a left parenthesis or comma.  These algorithms ignore whitespace and comments, except that the function name must be the first thing on the line.
+recognizes function definitions by seeing a non-keyword identifier at the left
+margin, followed by a left parenthesis, with a right parenthesis as the last
+character on the line, and with a left brace as the first token on the
+following line (ignoring possible intervening comments).  It will recognize a
+multi-line header provided that no intervening line ends with a left or right
+brace or a semicolon.  These algorithms ignore whitespace and comments, except
+that the function name must be the first thing on the line.
 .sp
 The following constructs will confuse it:
 .br
-     - Any other construct that starts at the left margin and follows the above syntax (such as a macro or function call).
+     - Any other construct that starts at the left margin and follows the
+above syntax (such as a macro or function call).
 .br
-     - Macros that tinker with the syntax of the function header.
+     - Some macros that tinker with the syntax of the function header.
+.sp
+The --varargs switch is obsolete, and is recognized only for
+backwards compatibility.  The present version of
+.I ansi2knr
+will always attempt to convert a ... argument to va_alist and va_dcl.
+.SH AUTHOR
+L. Peter Deutsch <ghost@aladdin.com> wrote the original ansi2knr and
+continues to maintain the current version; most of the code in the current
+version is his work.  ansi2knr also includes contributions by Francois
+Pinard <pinard@iro.umontreal.ca> and Jim Avera <jima@netcom.com>.
index 8328e6a84ba0a2eec47a008c0ae4540752dd9d71..4661d25bf3ec05f548708030c4c7ca2e5737b400 100644 (file)
@@ -1,3 +1,9 @@
+2003-10-04  Hrvoje Niksic  <hniksic@xemacs.org>
+
+       * log.c: Use `...' in function definitions; ansi2knr will convert
+       them to va_dcl.  This allowed removal of the ugly VA_START_1 and
+       VA_START_2 macros.
+
 2003-10-03  Gisle Vanem  <giva@bgnett.no>
 
        * connect.c: And don't include them here.
index c6ee83309a8239e84270732e7c5ce53b56dba3bf..f8995f458c36149d26371f8852bd19a3f05dbd7c 100644 (file)
@@ -1,4 +1,6 @@
-/* ansi2knr.c */
+/* Copyright (C) 1989, 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved. */
+
+/*$Id: ansi2knr.c 1002 2003-10-04 10:34:10Z hniksic $*/
 /* Convert ANSI C function definitions to K&R ("traditional C") syntax */
 
 /*
@@ -11,9 +13,10 @@ License (the "GPL") for full details.
 Everyone is granted permission to copy, modify and redistribute ansi2knr,
 but only under the conditions described in the GPL.  A copy of this license
 is supposed to have been given to you along with ansi2knr so you can know
-your rights and responsibilities.  It should be in a file named COPYLEFT.
-Among other things, the copyright notice and this notice must be preserved
-on all copies.
+your rights and responsibilities.  It should be in a file named COPYLEFT,
+or, if there is no file named COPYLEFT, a file named COPYING.  Among other
+things, the copyright notice and this notice must be preserved on all
+copies.
 
 We explicitly state here what we believe is already implied by the GPL: if
 the ansi2knr program is distributed as a separate set of sources and a
@@ -26,7 +29,10 @@ program under the GPL.
 
 /*
  * Usage:
-       ansi2knr input_file [output_file]
+       ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]
+ * --filename provides the file name for the #line directive in the output,
+ * overriding input_file (if present).
+ * If no input_file is supplied, input is read from stdin.
  * If no output_file is supplied, output goes to stdout.
  * There are no error messages.
  *
@@ -34,45 +40,71 @@ program under the GPL.
  * identifier at the left margin, followed by a left parenthesis,
  * with a right parenthesis as the last character on the line,
  * and with a left brace as the first token on the following line
- * (ignoring possible intervening comments).
- * It will recognize a multi-line header provided that no intervening
- * line ends with a left or right brace or a semicolon.
+ * (ignoring possible intervening comments), except that a line
+ * consisting of only
+ *     identifier1(identifier2)
+ * will not be considered a function definition unless identifier2 is
+ * the word "void", and a line consisting of
+ *     identifier1(identifier2, <<arbitrary>>)
+ * will not be considered a function definition.
+ * ansi2knr will recognize a multi-line header provided
+ * that no intervening line ends with a left or right brace or a semicolon.
  * These algorithms ignore whitespace and comments, except that
  * the function name must be the first thing on the line.
  * The following constructs will confuse it:
  *     - Any other construct that starts at the left margin and
  *         follows the above syntax (such as a macro or function call).
- *     - Some macros that tinker with the syntax of the function header.
+ *     - Some macros that tinker with the syntax of function headers.
  */
 
 /*
  * The original and principal author of ansi2knr is L. Peter Deutsch
  * <ghost@aladdin.com>.  Other authors are noted in the change history
  * that follows (in reverse chronological order):
-       lpd 96-01-21 added code to cope with not HAVE_CONFIG_H and with
+       lpd 1999-04-12 added minor fixes from Pavel Roskin
+               <pavel_roskin@geocities.com> for clean compilation with
+               gcc -W -Wall
+       lpd 1999-03-22 added hack to recognize lines consisting of
+               identifier1(identifier2, xxx) as *not* being procedures
+       lpd 1999-02-03 made indentation of preprocessor commands consistent
+       lpd 1999-01-28 fixed two bugs: a '/' in an argument list caused an
+               endless loop; quoted strings within an argument list
+               confused the parser
+       lpd 1999-01-24 added a check for write errors on the output,
+               suggested by Jim Meyering <meyering@ascend.com>
+       lpd 1998-11-09 added further hack to recognize identifier(void)
+               as being a procedure
+       lpd 1998-10-23 added hack to recognize lines consisting of
+               identifier1(identifier2) as *not* being procedures
+       lpd 1997-12-08 made input_file optional; only closes input and/or
+               output file if not stdin or stdout respectively; prints
+               usage message on stderr rather than stdout; adds
+               --filename switch (changes suggested by
+               <ceder@lysator.liu.se>)
+       lpd 1996-01-21 added code to cope with not HAVE_CONFIG_H and with
                compilers that don't understand void, as suggested by
                Tom Lane
-       lpd 96-01-15 changed to require that the first non-comment token
+       lpd 1996-01-15 changed to require that the first non-comment token
                on the line following a function header be a left brace,
                to reduce sensitivity to macros, as suggested by Tom Lane
                <tgl@sss.pgh.pa.us>
-       lpd 95-06-22 removed #ifndefs whose sole purpose was to define
+       lpd 1995-06-22 removed #ifndefs whose sole purpose was to define
                undefined preprocessor symbols as 0; changed all #ifdefs
                for configuration symbols to #ifs
-       lpd 95-04-05 changed copyright notice to make it clear that
+       lpd 1995-04-05 changed copyright notice to make it clear that
                including ansi2knr in a program does not bring the entire
                program under the GPL
-       lpd 94-12-18 added conditionals for systems where ctype macros
+       lpd 1994-12-18 added conditionals for systems where ctype macros
                don't handle 8-bit characters properly, suggested by
                Francois Pinard <pinard@iro.umontreal.ca>;
                removed --varargs switch (this is now the default)
-       lpd 94-10-10 removed CONFIG_BROKETS conditional
-       lpd 94-07-16 added some conditionals to help GNU `configure',
+       lpd 1994-10-10 removed CONFIG_BROKETS conditional
+       lpd 1994-07-16 added some conditionals to help GNU `configure',
                suggested by Francois Pinard <pinard@iro.umontreal.ca>;
                properly erase prototype args in function parameters,
                contributed by Jim Avera <jima@netcom.com>;
                correct error in writeblanks (it shouldn't erase EOLs)
-       lpd 89-xx-xx original version
+       lpd 1989-xx-xx original version
  */
 
 /* Most of the conditionals here are to make ansi2knr work with */
@@ -135,19 +167,24 @@ program under the GPL.
 
 #endif
 
+/* Define NULL (for *very* old compilers). */
+#ifndef NULL
+# define NULL (0)
+#endif
+
 /*
  * The ctype macros don't always handle 8-bit characters correctly.
  * Compensate for this here.
  */
 #ifdef isascii
-#  undef HAVE_ISASCII          /* just in case */
-#  define HAVE_ISASCII 1
+# undef HAVE_ISASCII           /* just in case */
+# define HAVE_ISASCII 1
 #else
 #endif
 #if STDC_HEADERS || !HAVE_ISASCII
-#  define is_ascii(c) 1
+# define is_ascii(c) 1
 #else
-#  define is_ascii(c) isascii(c)
+# define is_ascii(c) isascii(c)
 #endif
 
 #define is_space(c) (is_ascii(c) && isspace(c))
@@ -160,6 +197,7 @@ program under the GPL.
 
 /* Forward references */
 char *skipspace();
+char *scanstring();
 int writeblanks();
 int test1();
 int convert1();
@@ -169,11 +207,17 @@ int
 main(argc, argv)
     int argc;
     char *argv[];
-{      FILE *in, *out;
+{      FILE *in = stdin;
+       FILE *out = stdout;
+       char *filename = 0;
+       char *program_name = argv[0];
+       char *output_name = 0;
 #define bufsize 5000                   /* arbitrary size */
        char *buf;
        char *line;
        char *more;
+       char *usage =
+         "Usage: ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]\n";
        /*
         * In previous versions, ansi2knr recognized a --varargs switch.
         * If this switch was supplied, ansi2knr would attempt to convert
@@ -183,44 +227,61 @@ main(argc, argv)
         * check for this switch for backward compatibility.
         */
        int convert_varargs = 1;
+       int output_error;
 
-       if ( argc > 1 && argv[1][0] == '-' )
-         {     if ( !strcmp(argv[1], "--varargs") )
-                 {     convert_varargs = 1;
-                       argc--;
-                       argv++;
-                 }
-               else
-                 {     fprintf(stderr, "Unrecognized switch: %s\n", argv[1]);
-                       exit(1);
-                 }
+       while ( argc > 1 && argv[1][0] == '-' ) {
+         if ( !strcmp(argv[1], "--varargs") ) {
+           convert_varargs = 1;
+           argc--;
+           argv++;
+           continue;
          }
-       if (argc < 2 || argc > 3)
+         if ( !strcmp(argv[1], "--filename") && argc > 2 ) {
+           filename = argv[2];
+           argc -= 2;
+           argv += 2;
+           continue;
+         }
+         fprintf(stderr, "%s: Unrecognized switch: %s\n", program_name,
+                 argv[1]);
+         fprintf(stderr, usage);
+         exit(1);
+       }
+       switch ( argc )
           {
-               printf("Usage: ansi2knr input_file [output_file]\n");
-                       exit(1);
-                  }
-       in = fopen(argv[1], "r");
-       if ( in == NULL )
-         {
-           fprintf(stderr, "Cannot open input file %s\n", argv[1]);
-               exit(1);
+       default:
+               fprintf(stderr, usage);
+               exit(0);
+       case 3:
+               output_name = argv[2];
+               out = fopen(output_name, "w");
+               if ( out == NULL ) {
+                 fprintf(stderr, "%s: Cannot open output file %s\n",
+                         program_name, output_name);
+                 exit(1);
+               }
+               /* falls through */
+       case 2:
+               in = fopen(argv[1], "r");
+               if ( in == NULL ) {
+                 fprintf(stderr, "%s: Cannot open input file %s\n",
+                         program_name, argv[1]);
+                 exit(1);
+               }
+               if ( filename == 0 )
+                 filename = argv[1];
+               /* falls through */
+       case 1:
+               break;
           }
-       if (argc == 3)
-         {
-           out = fopen(argv[2], "w");
-           if ( out == NULL )
-             {
-               fprintf(stderr, "Cannot open output file %s\n", argv[2]);
-               exit(1);
-             }
-         }
-       else
-         {
-           out = stdout;
-         }
-       fprintf(out, "#line 1 \"%s\"\n", argv[1]);
+       if ( filename )
+         fprintf(out, "#line 1 \"%s\"\n", filename);
        buf = malloc(bufsize);
+       if ( buf == NULL )
+          {
+               fprintf(stderr, "Unable to allocate read buffer!\n");
+               exit(1);
+          }
        line = buf;
        while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
           {
@@ -271,12 +332,24 @@ wl:                       fputs(buf, out);
        if ( line != buf )
          fputs(buf, out);
        free(buf);
-       fclose(out);
-       fclose(in);
+       if ( output_name ) {
+         output_error = ferror(out);
+         output_error |= fclose(out);
+       } else {                /* out == stdout */
+         fflush(out);
+         output_error = ferror(out);
+       }
+       if ( output_error ) {
+         fprintf(stderr, "%s: error writing to %s\n", program_name,
+                 (output_name ? output_name : "stdout"));
+         exit(1);
+       }
+       if ( in != stdin )
+         fclose(in);
        return 0;
 }
 
-/* Skip over space and comments, in either direction. */
+/* Skip over whitespace and comments, in either direction. */
 char *
 skipspace(p, dir)
     register char *p;
@@ -297,6 +370,17 @@ skipspace(p, dir)
        return p;
 }
 
+/* Scan over a quoted string, in either direction. */
+char *
+scanstring(p, dir)
+    register char *p;
+    register int dir;
+{
+    for (p += dir; ; p += dir)
+       if (*p == '"' && p[-dir] != '\\')
+           return p + dir;
+}
+
 /*
  * Write blanks over part of a string.
  * Don't overwrite end-of-line characters.
@@ -365,7 +449,7 @@ test1(buf)
                   };
                char **key = words;
                char *kp;
-               int len = endfn - buf;
+               unsigned len = endfn - buf;
 
                while ( (kp = *key) != 0 )
                   {    if ( strlen(kp) == len && !strncmp(kp, buf, len) )
@@ -373,6 +457,36 @@ test1(buf)
                        key++;
                   }
           }
+          {
+              char *id = p;
+              int len;
+              /*
+               * Check for identifier1(identifier2) and not
+               * identifier1(void), or identifier1(identifier2, xxxx).
+               */
+
+              while ( isidchar(*p) )
+                  p++;
+              len = p - id;
+              p = skipspace(p, 1);
+              if (*p == ',' ||
+                  (*p == ')' && (len != 4 || strncmp(id, "void", 4)))
+                  )
+                  return 0;    /* not a function */
+          }
+       /*
+        * If the last significant character was a ), we need to count
+        * parentheses, because it might be part of a formal parameter
+        * that is a procedure.
+        */
+       if (contin > 0) {
+           int level = 0;
+
+           for (p = skipspace(buf, 1); *p; p = skipspace(p + 1, 1))
+               level += (*p == '(' ? 1 : *p == ')' ? -1 : 0);
+           if (level > 0)
+               contin = -1;
+       }
        return contin;
 }
 
@@ -402,7 +516,7 @@ convert1(buf, out, header, convert_varargs)
          ;
 top:   p = endfn;
        breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
-       if ( breaks == 0 )
+       if ( breaks == NULL )
           {    /* Couldn't allocate break table, give up */
                fprintf(stderr, "Unable to allocate break table!\n");
                fputs(buf, out);
@@ -414,7 +528,7 @@ top:        p = endfn;
        do
           {    int level = 0;
                char *lp = NULL;
-               char *rp;
+               char *rp = NULL;
                char *end = NULL;
 
                if ( bp >= btop )
@@ -441,14 +555,18 @@ top:      p = endfn;
                                else rp = p;
                                break;
                           case '/':
-                               p = skipspace(p, 1) - 1;
+                               if (p[1] == '*')
+                                   p = skipspace(p, 1) - 1;
                                break;
+                          case '"':
+                              p = scanstring(p, 1) - 1;
+                              break;
                           default:
                                ;
                           }
                   }
                /* Erase any embedded prototype parameters. */
-               if ( lp )
+               if ( lp && rp )
                  writeblanks(lp + 1, rp);
                p--;                    /* back up over terminator */
                /* Find the name being declared. */
@@ -464,9 +582,19 @@ top:       p = endfn;
                                while ( level )
                                 switch ( *--p )
                                   {
-                                  case ']': case ')': level++; break;
-                                  case '[': case '(': level--; break;
-                                  case '/': p = skipspace(p, -1) + 1; break;
+                                  case ']': case ')':
+                                      level++;
+                                      break;
+                                  case '[': case '(':
+                                      level--;
+                                      break;
+                                  case '/':
+                                      if (p > buf && p[-1] == '*')
+                                          p = skipspace(p, -1) + 1;
+                                      break;
+                                  case '"':
+                                      p = scanstring(p, -1) + 1;
+                                      break;
                                   default: ;
                                   }
                           }
index 1f829e493da2a2945d47ef99769bf3b933a1f3bf..578b0c1f5520e7e5b666473eed6426169fced05e 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -390,10 +390,10 @@ logvprintf (struct logvprintf_state *state, const char *fmt, va_list args)
   /* vsnprintf() will not step over the limit given by available_size.
      If it fails, it will return either -1 (POSIX?) or the number of
      characters that *would have* been written, if there had been
-     enough room.  In the former case, we double the available_size
-     and malloc() to get a larger buffer, and try again.  In the
-     latter case, we use the returned information to build a buffer of
-     the correct size.  */
+     enough room (C99).  In the former case, we double the
+     available_size and malloc to get a larger buffer, and try again.
+     In the latter case, we use the returned information to build a
+     buffer of the correct size.  */
 
   if (numwritten == -1)
     {
@@ -473,46 +473,27 @@ log_set_save_context (int savep)
   return old;
 }
 
+/* Handle difference in va_start between pre-ANSI and ANSI C.  Note
+   that we always use `...' in function definitions and let ansi2knr
+   convert it for us.  */
+
 #ifdef WGET_USE_STDARG
-# define VA_START_1(arg1_type, arg1, args) va_start(args, arg1)
-# define VA_START_2(arg1_type, arg1, arg2_type, arg2, args) va_start(args, arg2)
-#else  /* not WGET_USE_STDARG */
-# define VA_START_1(arg1_type, arg1, args) do {        \
-  va_start (args);                                                     \
-  arg1 = va_arg (args, arg1_type);                                     \
-} while (0)
-# define VA_START_2(arg1_type, arg1, arg2_type, arg2, args) do {       \
-  va_start (args);                                                     \
-  arg1 = va_arg (args, arg1_type);                                     \
-  arg2 = va_arg (args, arg2_type);                                     \
-} while (0)
-#endif /* not WGET_USE_STDARG */
+# define VA_START(args, arg1) va_start (args, arg1)
+#else
+# define VA_START(args, ignored) va_start (args)
+#endif
 
-/* Portability with pre-ANSI compilers makes these two functions look
-   like @#%#@$@#$.  */
+/* Print a message to the screen or to the log.  The first argument
+   defines the verbosity of the message, and the rest are as in
+   printf(3).  */
 
-#ifdef WGET_USE_STDARG
 void
 logprintf (enum log_options o, const char *fmt, ...)
-#else  /* not WGET_USE_STDARG */
-void
-logprintf (va_alist)
-     va_dcl
-#endif /* not WGET_USE_STDARG */
 {
   va_list args;
   struct logvprintf_state lpstate;
   int done;
 
-#ifndef WGET_USE_STDARG
-  enum log_options o;
-  const char *fmt;
-
-  /* Perform a "dry run" of VA_START_2 to get the value of O. */
-  VA_START_2 (enum log_options, o, char *, fmt, args);
-  va_end (args);
-#endif
-
   check_redirect_output ();
   if (inhibit_logging)
     return;
@@ -521,7 +502,7 @@ logprintf (va_alist)
   memset (&lpstate, '\0', sizeof (lpstate));
   do
     {
-      VA_START_2 (enum log_options, o, char *, fmt, args);
+      VA_START (args, fmt);
       done = logvprintf (&lpstate, fmt, args);
       va_end (args);
     }
@@ -531,21 +512,12 @@ logprintf (va_alist)
 #ifdef DEBUG
 /* The same as logprintf(), but does anything only if opt.debug is
    non-zero.  */
-#ifdef WGET_USE_STDARG
 void
 debug_logprintf (const char *fmt, ...)
-#else  /* not WGET_USE_STDARG */
-void
-debug_logprintf (va_alist)
-     va_dcl
-#endif /* not WGET_USE_STDARG */
 {
   if (opt.debug)
     {
       va_list args;
-#ifndef WGET_USE_STDARG
-      const char *fmt;
-#endif
       struct logvprintf_state lpstate;
       int done;
 
@@ -556,7 +528,7 @@ debug_logprintf (va_alist)
       memset (&lpstate, '\0', sizeof (lpstate));
       do
        {
-         VA_START_1 (char *, fmt, args);
+         VA_START (args, fmt);
          done = logvprintf (&lpstate, fmt, args);
          va_end (args);
        }
@@ -590,9 +562,9 @@ log_init (const char *file, int appendp)
       logfp = stderr;
 
       /* If the output is a TTY, enable storing, which will make Wget
-         remember all the printed messages, to be able to dump them to
-         a log file in case SIGHUP or SIGUSR1 is received (or
-         Ctrl+Break is pressed under Windows).  */
+         remember the last several printed messages, to be able to
+         dump them to a log file in case SIGHUP or SIGUSR1 is received
+         (or Ctrl+Break is pressed under Windows).  */
       if (1
 #ifdef HAVE_ISATTY
          && isatty (fileno (logfp))