"Fossies" - the Fresh Open Source Software Archive

Member "Pansophica-src-1.3/BAF_modules/wget_mod/src/ansi2knr.c" (31 Jan 2008, 13302 Bytes) of package /linux/www/old/Pansophica-src-1.3-1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /* Copyright (C) 1989, 1991, 1993, 1994, 1995 Aladdin Enterprises. All rights reserved. */
    2 
    3 /* ansi2knr.c */
    4 /* Convert ANSI C function definitions to K&R ("traditional C") syntax */
    5 
    6 /*
    7 ansi2knr is distributed in the hope that it will be useful, but WITHOUT ANY
    8 WARRANTY.  No author or distributor accepts responsibility to anyone for the
    9 consequences of using it or for whether it serves any particular purpose or
   10 works at all, unless he says so in writing.  Refer to the GNU General Public
   11 License (the "GPL") for full details.
   12 
   13 Everyone is granted permission to copy, modify and redistribute ansi2knr,
   14 but only under the conditions described in the GPL.  A copy of this license
   15 is supposed to have been given to you along with ansi2knr so you can know
   16 your rights and responsibilities.  It should be in a file named COPYLEFT.
   17 Among other things, the copyright notice and this notice must be preserved
   18 on all copies.
   19 
   20 We explicitly state here what we believe is already implied by the GPL: if
   21 the ansi2knr program is distributed as a separate set of sources and a
   22 separate executable file which are aggregated on a storage medium together
   23 with another program, this in itself does not bring the other program under
   24 the GPL, nor does the mere fact that such a program or the procedures for
   25 constructing it invoke the ansi2knr executable bring any other part of the
   26 program under the GPL.
   27 */
   28 
   29 /*
   30  * Usage:
   31     ansi2knr input_file [output_file]
   32  * If no output_file is supplied, output goes to stdout.
   33  * There are no error messages.
   34  *
   35  * ansi2knr recognizes function definitions by seeing a non-keyword
   36  * identifier at the left margin, followed by a left parenthesis,
   37  * with a right parenthesis as the last character on the line.
   38  * It will recognize a multi-line header provided that the last character
   39  * of the last line of the header is a right parenthesis,
   40  * and no intervening line ends with a left or right brace or a semicolon.
   41  * These algorithms ignore whitespace and comments, except that
   42  * the function name must be the first thing on the line.
   43  * The following constructs will confuse it:
   44  *  - Any other construct that starts at the left margin and
   45  *      follows the above syntax (such as a macro or function call).
   46  *  - Macros that tinker with the syntax of the function header.
   47  */
   48 
   49 /*
   50  * The original and principal author of ansi2knr is L. Peter Deutsch
   51  * <ghost@aladdin.com>.  Other authors are noted in the change history
   52  * that follows (in reverse chronological order):
   53     lpd 95-06-22 removed #ifndefs whose sole purpose was to define
   54         undefined preprocessor symbols as 0; changed all #ifdefs
   55         for configuration symbols to #ifs
   56     lpd 95-04-05 changed copyright notice to make it clear that
   57         including ansi2knr in a program does not bring the entire
   58         program under the GPL
   59     lpd 94-12-18 added conditionals for systems where ctype macros
   60         don't handle 8-bit characters properly, suggested by
   61         Francois Pinard <pinard@iro.umontreal.ca>;
   62         removed --varargs switch (this is now the default)
   63     lpd 94-10-10 removed CONFIG_BROKETS conditional
   64     lpd 94-07-16 added some conditionals to help GNU `configure',
   65         suggested by Francois Pinard <pinard@iro.umontreal.ca>;
   66         properly erase prototype args in function parameters,
   67         contributed by Jim Avera <jima@netcom.com>;
   68         correct error in writeblanks (it shouldn't erase EOLs)
   69     lpd 89-xx-xx original version
   70  */
   71 
   72 /* Most of the conditionals here are to make ansi2knr work with */
   73 /* the GNU configure machinery. */
   74 
   75 #if HAVE_CONFIG_H
   76 # include <config.h>
   77 #endif
   78 
   79 #include <stdio.h>
   80 #include <ctype.h>
   81 
   82 #if HAVE_CONFIG_H
   83 
   84 /*
   85    For properly autoconfiguring ansi2knr, use AC_CONFIG_HEADER(config.h).
   86    This will define HAVE_CONFIG_H and so, activate the following lines.
   87  */
   88 
   89 # if STDC_HEADERS || HAVE_STRING_H
   90 #  include <string.h>
   91 # else
   92 #  include <strings.h>
   93 # endif
   94 
   95 #else /* not HAVE_CONFIG_H */
   96 
   97 /*
   98    Without AC_CONFIG_HEADER, merely use <string.h> as in the original
   99    Ghostscript distribution.  This loses on older BSD systems.
  100  */
  101 
  102 # include <string.h>
  103 
  104 #endif /* not HAVE_CONFIG_H */
  105 
  106 #if STDC_HEADERS
  107 # include <stdlib.h>
  108 #else
  109 /*
  110    malloc and free should be declared in stdlib.h,
  111    but if you've got a K&R compiler, they probably aren't.
  112  */
  113 char *malloc();
  114 void free();
  115 #endif
  116 
  117 /*
  118  * The ctype macros don't always handle 8-bit characters correctly.
  119  * Compensate for this here.
  120  */
  121 #ifdef isascii
  122 #  undef HAVE_ISASCII       /* just in case */
  123 #  define HAVE_ISASCII 1
  124 #else
  125 #endif
  126 #if STDC_HEADERS || !HAVE_ISASCII
  127 #  define is_ascii(c) 1
  128 #else
  129 #  define is_ascii(c) isascii(c)
  130 #endif
  131 
  132 #define is_space(c) (is_ascii(c) && isspace(c))
  133 #define is_alpha(c) (is_ascii(c) && isalpha(c))
  134 #define is_alnum(c) (is_ascii(c) && isalnum(c))
  135 
  136 /* Scanning macros */
  137 #define isidchar(ch) (is_alnum(ch) || (ch) == '_')
  138 #define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_')
  139 
  140 /* Forward references */
  141 char *skipspace();
  142 void writeblanks();
  143 int test1();
  144 int convert1();
  145 
  146 /* The main program */
  147 int
  148 main(argc, argv)
  149     int argc;
  150     char *argv[];
  151 {   FILE *in, *out;
  152 #define bufsize 5000            /* arbitrary size */
  153     char *buf;
  154     char *line;
  155     /*
  156      * In previous versions, ansi2knr recognized a --varargs switch.
  157      * If this switch was supplied, ansi2knr would attempt to convert
  158      * a ... argument to va_alist and va_dcl; if this switch was not
  159      * supplied, ansi2knr would simply drop any such arguments.
  160      * Now, ansi2knr always does this conversion, and we only
  161      * check for this switch for backward compatibility.
  162      */
  163     int convert_varargs = 1;
  164 
  165     if ( argc > 1 && argv[1][0] == '-' )
  166       { if ( !strcmp(argv[1], "--varargs") )
  167           { convert_varargs = 1;
  168             argc--;
  169             argv++;
  170           }
  171         else
  172           { fprintf(stderr, "Unrecognized switch: %s\n", argv[1]);
  173             exit(1);
  174           }
  175       }
  176     switch ( argc )
  177        {
  178     default:
  179         printf("Usage: ansi2knr input_file [output_file]\n");
  180         exit(0);
  181     case 2:
  182         out = stdout;
  183         break;
  184     case 3:
  185         out = fopen(argv[2], "w");
  186         if ( out == NULL )
  187            {    fprintf(stderr, "Cannot open output file %s\n", argv[2]);
  188             exit(1);
  189            }
  190        }
  191     in = fopen(argv[1], "r");
  192     if ( in == NULL )
  193        {    fprintf(stderr, "Cannot open input file %s\n", argv[1]);
  194         exit(1);
  195        }
  196     fprintf(out, "#line 1 \"%s\"\n", argv[1]);
  197     buf = malloc(bufsize);
  198     line = buf;
  199     while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
  200        {    switch ( test1(buf) )
  201            {
  202         case 2:         /* a function header */
  203             convert1(buf, out, 1, convert_varargs);
  204             break;
  205         case 1:         /* a function */
  206             convert1(buf, out, 0, convert_varargs);
  207             break;
  208         case -1:        /* maybe the start of a function */
  209             line = buf + strlen(buf);
  210             if ( line != buf + (bufsize - 1) ) /* overflow check */
  211                 continue;
  212             /* falls through */
  213         default:        /* not a function */
  214             fputs(buf, out);
  215             break;
  216            }
  217         line = buf;
  218        }
  219     if ( line != buf ) fputs(buf, out);
  220     free(buf);
  221     fclose(out);
  222     fclose(in);
  223     return 0;
  224 }
  225 
  226 /* Skip over space and comments, in either direction. */
  227 char *
  228 skipspace(p, dir)
  229     register char *p;
  230     register int dir;           /* 1 for forward, -1 for backward */
  231 {   for ( ; ; )
  232        {    while ( is_space(*p) ) p += dir;
  233         if ( !(*p == '/' && p[dir] == '*') ) break;
  234         p += dir;  p += dir;
  235         while ( !(*p == '*' && p[dir] == '/') )
  236            {    if ( *p == 0 ) return p;    /* multi-line comment?? */
  237             p += dir;
  238            }
  239         p += dir;  p += dir;
  240        }
  241     return p;
  242 }
  243 
  244 /*
  245  * Write blanks over part of a string.
  246  * Don't overwrite end-of-line characters.
  247  */
  248 void
  249 writeblanks(start, end)
  250     char *start;
  251     char *end;
  252 {   char *p;
  253     for ( p = start; p < end; p++ )
  254       if ( *p != '\r' && *p != '\n' ) *p = ' ';
  255 }
  256 
  257 /*
  258  * Test whether the string in buf is a function definition.
  259  * The string may contain and/or end with a newline.
  260  * Return as follows:
  261  *  0 - definitely not a function definition;
  262  *  1 - definitely a function definition;
  263  *  2 - definitely a function prototype (NOT USED);
  264  *  -1 - may be the beginning of a function definition,
  265  *      append another line and look again.
  266  * The reason we don't attempt to convert function prototypes is that
  267  * Ghostscript's declaration-generating macros look too much like
  268  * prototypes, and confuse the algorithms.
  269  */
  270 int
  271 test1(buf)
  272     char *buf;
  273 {   register char *p = buf;
  274     char *bend;
  275     char *endfn;
  276     int contin;
  277     if ( !isidfirstchar(*p) )
  278         return 0;       /* no name at left margin */
  279     bend = skipspace(buf + strlen(buf) - 1, -1);
  280     switch ( *bend )
  281        {
  282     case ';': contin = 0 /*2*/; break;
  283     case ')': contin = 1; break;
  284     case '{': return 0;     /* not a function */
  285     case '}': return 0;     /* not a function */
  286     default: contin = -1;
  287        }
  288     while ( isidchar(*p) ) p++;
  289     endfn = p;
  290     p = skipspace(p, 1);
  291     if ( *p++ != '(' )
  292         return 0;       /* not a function */
  293     p = skipspace(p, 1);
  294     if ( *p == ')' )
  295         return 0;       /* no parameters */
  296     /* Check that the apparent function name isn't a keyword. */
  297     /* We only need to check for keywords that could be followed */
  298     /* by a left parenthesis (which, unfortunately, is most of them). */
  299        {    static char *words[] =
  300            {    "asm", "auto", "case", "char", "const", "double",
  301             "extern", "float", "for", "if", "int", "long",
  302             "register", "return", "short", "signed", "sizeof",
  303             "static", "switch", "typedef", "unsigned",
  304             "void", "volatile", "while", 0
  305            };
  306         char **key = words;
  307         char *kp;
  308         int len = endfn - buf;
  309         while ( (kp = *key) != 0 )
  310            {    if ( strlen(kp) == len && !strncmp(kp, buf, len) )
  311                 return 0;   /* name is a keyword */
  312             key++;
  313            }
  314        }
  315     return contin;
  316 }
  317 
  318 /* Convert a recognized function definition or header to K&R syntax. */
  319 int
  320 convert1(buf, out, header, convert_varargs)
  321     char *buf;
  322     FILE *out;
  323     int header;         /* Boolean */
  324     int convert_varargs;    /* Boolean */
  325 {   char *endfn;
  326     register char *p;
  327     char **breaks;
  328     unsigned num_breaks = 2;    /* for testing */
  329     char **btop;
  330     char **bp;
  331     char **ap;
  332     char *vararg = 0;
  333     /* Pre-ANSI implementations don't agree on whether strchr */
  334     /* is called strchr or index, so we open-code it here. */
  335     for ( endfn = buf; *(endfn++) != '('; ) ;
  336 top:    p = endfn;
  337     breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
  338     if ( breaks == 0 )
  339        {    /* Couldn't allocate break table, give up */
  340         fprintf(stderr, "Unable to allocate break table!\n");
  341         fputs(buf, out);
  342         return -1;
  343        }
  344     btop = breaks + num_breaks * 2 - 2;
  345     bp = breaks;
  346     /* Parse the argument list */
  347     do
  348        {    int level = 0;
  349         char *lp = NULL;
  350         char *rp;
  351         char *end = NULL;
  352         if ( bp >= btop )
  353            {    /* Filled up break table. */
  354             /* Allocate a bigger one and start over. */
  355             free((char *)breaks);
  356             num_breaks <<= 1;
  357             goto top;
  358            }
  359         *bp++ = p;
  360         /* Find the end of the argument */
  361         for ( ; end == NULL; p++ )
  362            {    switch(*p)
  363                {
  364             case ',':
  365                 if ( !level ) end = p;
  366                 break;
  367             case '(':
  368                 if ( !level ) lp = p;
  369                 level++;
  370                 break;
  371             case ')':
  372                 if ( --level < 0 ) end = p;
  373                 else rp = p;
  374                 break;
  375             case '/':
  376                 p = skipspace(p, 1) - 1;
  377                 break;
  378             default:
  379                 ;
  380                }
  381            }
  382         /* Erase any embedded prototype parameters. */
  383         if ( lp )
  384           writeblanks(lp + 1, rp);
  385         p--;            /* back up over terminator */
  386         /* Find the name being declared. */
  387         /* This is complicated because of procedure and */
  388         /* array modifiers. */
  389         for ( ; ; )
  390            {    p = skipspace(p - 1, -1);
  391             switch ( *p )
  392                {
  393             case ']':   /* skip array dimension(s) */
  394             case ')':   /* skip procedure args OR name */
  395                {    int level = 1;
  396                 while ( level )
  397                  switch ( *--p )
  398                    {
  399                 case ']': case ')': level++; break;
  400                 case '[': case '(': level--; break;
  401                 case '/': p = skipspace(p, -1) + 1; break;
  402                 default: ;
  403                    }
  404                }
  405                 if ( *p == '(' && *skipspace(p + 1, 1) == '*' )
  406                    {    /* We found the name being declared */
  407                     while ( !isidfirstchar(*p) )
  408                         p = skipspace(p, 1) + 1;
  409                     goto found;
  410                    }
  411                 break;
  412             default: goto found;
  413                }
  414            }
  415 found:      if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
  416           { if ( convert_varargs )
  417               { *bp++ = "va_alist";
  418                 vararg = p-2;
  419               }
  420             else
  421               { p++;
  422                 if ( bp == breaks + 1 ) /* sole argument */
  423                   writeblanks(breaks[0], p);
  424                 else
  425                   writeblanks(bp[-1] - 1, p);
  426                 bp--;
  427               }
  428            }
  429         else
  430            {    while ( isidchar(*p) ) p--;
  431             *bp++ = p+1;
  432            }
  433         p = end;
  434        }
  435     while ( *p++ == ',' );
  436     *bp = p;
  437     /* Make a special check for 'void' arglist */
  438     if ( bp == breaks+2 )
  439        {    p = skipspace(breaks[0], 1);
  440         if ( !strncmp(p, "void", 4) )
  441            {    p = skipspace(p+4, 1);
  442             if ( p == breaks[2] - 1 )
  443                {    bp = breaks;    /* yup, pretend arglist is empty */
  444                 writeblanks(breaks[0], p + 1);
  445                }
  446            }
  447        }
  448     /* Put out the function name and left parenthesis. */
  449     p = buf;
  450     while ( p != endfn ) putc(*p, out), p++;
  451     /* Put out the declaration. */
  452     if ( header )
  453       { fputs(");", out);
  454         for ( p = breaks[0]; *p; p++ )
  455           if ( *p == '\r' || *p == '\n' )
  456             putc(*p, out);
  457       }
  458     else
  459       { for ( ap = breaks+1; ap < bp; ap += 2 )
  460           { p = *ap;
  461             while ( isidchar(*p) )
  462               putc(*p, out), p++;
  463             if ( ap < bp - 1 )
  464               fputs(", ", out);
  465           }
  466         fputs(")  ", out);
  467         /* Put out the argument declarations */
  468         for ( ap = breaks+2; ap <= bp; ap += 2 )
  469           (*ap)[-1] = ';';
  470         if ( vararg != 0 )
  471           { *vararg = 0;
  472             fputs(breaks[0], out);      /* any prior args */
  473             fputs("va_dcl", out);       /* the final arg */
  474             fputs(bp[0], out);
  475           }
  476         else
  477           fputs(breaks[0], out);
  478       }
  479     free((char *)breaks);
  480     return 0;
  481 }