Back to index

plt-scheme  4.2.1
ansi2knr.c
Go to the documentation of this file.
00001 /* ansi2knr.c */
00002 /* Convert ANSI C function definitions to K&R ("traditional C") syntax */
00003 
00004 /*
00005 ansi2knr is distributed in the hope that it will be useful, but WITHOUT ANY
00006 WARRANTY.  No author or distributor accepts responsibility to anyone for the
00007 consequences of using it or for whether it serves any particular purpose or
00008 works at all, unless he says so in writing.  Refer to the GNU General Public
00009 License (the "GPL") for full details.
00010 
00011 Everyone is granted permission to copy, modify and redistribute ansi2knr,
00012 but only under the conditions described in the GPL.  A copy of this license
00013 is supposed to have been given to you along with ansi2knr so you can know
00014 your rights and responsibilities.  It should be in a file named COPYLEFT.
00015 [In the IJG distribution, the GPL appears below, not in a separate file.]
00016 Among other things, the copyright notice and this notice must be preserved
00017 on all copies.
00018 
00019 We explicitly state here what we believe is already implied by the GPL: if
00020 the ansi2knr program is distributed as a separate set of sources and a
00021 separate executable file which are aggregated on a storage medium together
00022 with another program, this in itself does not bring the other program under
00023 the GPL, nor does the mere fact that such a program or the procedures for
00024 constructing it invoke the ansi2knr executable bring any other part of the
00025 program under the GPL.
00026 */
00027 
00028 /*
00029 ---------- Here is the GNU GPL file COPYLEFT, referred to above ----------
00030 ----- These terms do NOT apply to the JPEG software itself; see README ------
00031 
00032                   GHOSTSCRIPT GENERAL PUBLIC LICENSE
00033                   (Clarified 11 Feb 1988)
00034 
00035  Copyright (C) 1988 Richard M. Stallman
00036  Everyone is permitted to copy and distribute verbatim copies of this
00037  license, but changing it is not allowed.  You can also use this wording
00038  to make the terms for other programs.
00039 
00040   The license agreements of most software companies keep you at the
00041 mercy of those companies.  By contrast, our general public license is
00042 intended to give everyone the right to share Ghostscript.  To make sure
00043 that you get the rights we want you to have, we need to make
00044 restrictions that forbid anyone to deny you these rights or to ask you
00045 to surrender the rights.  Hence this license agreement.
00046 
00047   Specifically, we want to make sure that you have the right to give
00048 away copies of Ghostscript, that you receive source code or else can get
00049 it if you want it, that you can change Ghostscript or use pieces of it
00050 in new free programs, and that you know you can do these things.
00051 
00052   To make sure that everyone has such rights, we have to forbid you to
00053 deprive anyone else of these rights.  For example, if you distribute
00054 copies of Ghostscript, you must give the recipients all the rights that
00055 you have.  You must make sure that they, too, receive or can get the
00056 source code.  And you must tell them their rights.
00057 
00058   Also, for our own protection, we must make certain that everyone finds
00059 out that there is no warranty for Ghostscript.  If Ghostscript is
00060 modified by someone else and passed on, we want its recipients to know
00061 that what they have is not what we distributed, so that any problems
00062 introduced by others will not reflect on our reputation.
00063 
00064   Therefore we (Richard M. Stallman and the Free Software Foundation,
00065 Inc.) make the following terms which say what you must do to be allowed
00066 to distribute or change Ghostscript.
00067 
00068 
00069                      COPYING POLICIES
00070 
00071   1. You may copy and distribute verbatim copies of Ghostscript source
00072 code as you receive it, in any medium, provided that you conspicuously
00073 and appropriately publish on each copy a valid copyright and license
00074 notice "Copyright (C) 1989 Aladdin Enterprises.  All rights reserved.
00075 Distributed by Free Software Foundation, Inc." (or with whatever year is
00076 appropriate); keep intact the notices on all files that refer to this
00077 License Agreement and to the absence of any warranty; and give any other
00078 recipients of the Ghostscript program a copy of this License Agreement
00079 along with the program.  You may charge a distribution fee for the
00080 physical act of transferring a copy.
00081 
00082   2. You may modify your copy or copies of Ghostscript or any portion of
00083 it, and copy and distribute such modifications under the terms of
00084 Paragraph 1 above, provided that you also do the following:
00085 
00086     a) cause the modified files to carry prominent notices stating
00087     that you changed the files and the date of any change; and
00088 
00089     b) cause the whole of any work that you distribute or publish,
00090     that in whole or in part contains or is a derivative of Ghostscript
00091     or any part thereof, to be licensed at no charge to all third
00092     parties on terms identical to those contained in this License
00093     Agreement (except that you may choose to grant more extensive
00094     warranty protection to some or all third parties, at your option).
00095 
00096     c) You may charge a distribution fee for the physical act of
00097     transferring a copy, and you may at your option offer warranty
00098     protection in exchange for a fee.
00099 
00100 Mere aggregation of another unrelated program with this program (or its
00101 derivative) on a volume of a storage or distribution medium does not bring
00102 the other program under the scope of these terms.
00103 
00104   3. You may copy and distribute Ghostscript (or a portion or derivative
00105 of it, under Paragraph 2) in object code or executable form under the
00106 terms of Paragraphs 1 and 2 above provided that you also do one of the
00107 following:
00108 
00109     a) accompany it with the complete corresponding machine-readable
00110     source code, which must be distributed under the terms of
00111     Paragraphs 1 and 2 above; or,
00112 
00113     b) accompany it with a written offer, valid for at least three
00114     years, to give any third party free (except for a nominal
00115     shipping charge) a complete machine-readable copy of the
00116     corresponding source code, to be distributed under the terms of
00117     Paragraphs 1 and 2 above; or,
00118 
00119     c) accompany it with the information you received as to where the
00120     corresponding source code may be obtained.  (This alternative is
00121     allowed only for noncommercial distribution and only if you
00122     received the program in object code or executable form alone.)
00123 
00124 For an executable file, complete source code means all the source code for
00125 all modules it contains; but, as a special exception, it need not include
00126 source code for modules which are standard libraries that accompany the
00127 operating system on which the executable file runs.
00128 
00129   4. You may not copy, sublicense, distribute or transfer Ghostscript
00130 except as expressly provided under this License Agreement.  Any attempt
00131 otherwise to copy, sublicense, distribute or transfer Ghostscript is
00132 void and your rights to use the program under this License agreement
00133 shall be automatically terminated.  However, parties who have received
00134 computer software programs from you with this License Agreement will not
00135 have their licenses terminated so long as such parties remain in full
00136 compliance.
00137 
00138   5. If you wish to incorporate parts of Ghostscript into other free
00139 programs whose distribution conditions are different, write to the Free
00140 Software Foundation at 675 Mass Ave, Cambridge, MA 02139.  We have not
00141 yet worked out a simple rule that can be stated here, but we will often
00142 permit this.  We will be guided by the two goals of preserving the free
00143 status of all derivatives of our free software and of promoting the
00144 sharing and reuse of software.
00145 
00146 Your comments and suggestions about our licensing policies and our
00147 software are welcome!  Please contact the Free Software Foundation,
00148 Inc., 675 Mass Ave, Cambridge, MA 02139, or call (617) 876-3296.
00149 
00150                      NO WARRANTY
00151 
00152   BECAUSE GHOSTSCRIPT IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
00153 NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW.  EXCEPT
00154 WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, RICHARD
00155 M. STALLMAN, ALADDIN ENTERPRISES, L. PETER DEUTSCH, AND/OR OTHER PARTIES
00156 PROVIDE GHOSTSCRIPT "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
00157 EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00158 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE
00159 ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF GHOSTSCRIPT IS WITH
00160 YOU.  SHOULD GHOSTSCRIPT PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
00161 NECESSARY SERVICING, REPAIR OR CORRECTION.
00162 
00163   IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
00164 STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., L. PETER DEUTSCH, ALADDIN
00165 ENTERPRISES, AND/OR ANY OTHER PARTY WHO MAY MODIFY AND REDISTRIBUTE
00166 GHOSTSCRIPT AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING
00167 ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL, INCIDENTAL OR
00168 CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
00169 (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
00170 INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A FAILURE OF THE
00171 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GHOSTSCRIPT, EVEN IF YOU
00172 HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM
00173 BY ANY OTHER PARTY.
00174 
00175 -------------------- End of file COPYLEFT ------------------------------
00176 */
00177 
00178 /*
00179  * Usage:
00180        ansi2knr input_file [output_file]
00181  * If no output_file is supplied, output goes to stdout.
00182  * There are no error messages.
00183  *
00184  * ansi2knr recognizes function definitions by seeing a non-keyword
00185  * identifier at the left margin, followed by a left parenthesis,
00186  * with a right parenthesis as the last character on the line,
00187  * and with a left brace as the first token on the following line
00188  * (ignoring possible intervening comments).
00189  * It will recognize a multi-line header provided that no intervening
00190  * line ends with a left or right brace or a semicolon.
00191  * These algorithms ignore whitespace and comments, except that
00192  * the function name must be the first thing on the line.
00193  * The following constructs will confuse it:
00194  *     - Any other construct that starts at the left margin and
00195  *         follows the above syntax (such as a macro or function call).
00196  *     - Some macros that tinker with the syntax of the function header.
00197  */
00198 
00199 /*
00200  * The original and principal author of ansi2knr is L. Peter Deutsch
00201  * <ghost@aladdin.com>.  Other authors are noted in the change history
00202  * that follows (in reverse chronological order):
00203        lpd 96-01-21 added code to cope with not HAVE_CONFIG_H and with
00204               compilers that don't understand void, as suggested by
00205               Tom Lane
00206        lpd 96-01-15 changed to require that the first non-comment token
00207               on the line following a function header be a left brace,
00208               to reduce sensitivity to macros, as suggested by Tom Lane
00209               <tgl@sss.pgh.pa.us>
00210        lpd 95-06-22 removed #ifndefs whose sole purpose was to define
00211               undefined preprocessor symbols as 0; changed all #ifdefs
00212               for configuration symbols to #ifs
00213        lpd 95-04-05 changed copyright notice to make it clear that
00214               including ansi2knr in a program does not bring the entire
00215               program under the GPL
00216        lpd 94-12-18 added conditionals for systems where ctype macros
00217               don't handle 8-bit characters properly, suggested by
00218               Francois Pinard <pinard@iro.umontreal.ca>;
00219               removed --varargs switch (this is now the default)
00220        lpd 94-10-10 removed CONFIG_BROKETS conditional
00221        lpd 94-07-16 added some conditionals to help GNU `configure',
00222               suggested by Francois Pinard <pinard@iro.umontreal.ca>;
00223               properly erase prototype args in function parameters,
00224               contributed by Jim Avera <jima@netcom.com>;
00225               correct error in writeblanks (it shouldn't erase EOLs)
00226        lpd 89-xx-xx original version
00227  */
00228 
00229 /* Most of the conditionals here are to make ansi2knr work with */
00230 /* or without the GNU configure machinery. */
00231 
00232 #if HAVE_CONFIG_H
00233 # include <config.h>
00234 #endif
00235 
00236 #include <stdio.h>
00237 #include <ctype.h>
00238 
00239 #if HAVE_CONFIG_H
00240 
00241 /*
00242    For properly autoconfiguring ansi2knr, use AC_CONFIG_HEADER(config.h).
00243    This will define HAVE_CONFIG_H and so, activate the following lines.
00244  */
00245 
00246 # if STDC_HEADERS || HAVE_STRING_H
00247 #  include <string.h>
00248 # else
00249 #  include <strings.h>
00250 # endif
00251 
00252 #else /* not HAVE_CONFIG_H */
00253 
00254 /* Otherwise do it the hard way */
00255 
00256 # ifdef BSD
00257 #  include <strings.h>
00258 # else
00259 #  ifdef VMS
00260     extern int strlen(), strncmp();
00261 #  else
00262 #   include <string.h>
00263 #  endif
00264 # endif
00265 
00266 #endif /* not HAVE_CONFIG_H */
00267 
00268 #if STDC_HEADERS
00269 # include <stdlib.h>
00270 #else
00271 /*
00272    malloc and free should be declared in stdlib.h,
00273    but if you've got a K&R compiler, they probably aren't.
00274  */
00275 # ifdef MSDOS
00276 #  include <malloc.h>
00277 # else
00278 #  ifdef VMS
00279      extern char *malloc();
00280      extern void free();
00281 #  else
00282      extern char *malloc();
00283      extern int free();
00284 #  endif
00285 # endif
00286 
00287 #endif
00288 
00289 /*
00290  * The ctype macros don't always handle 8-bit characters correctly.
00291  * Compensate for this here.
00292  */
00293 #ifdef isascii
00294 #  undef HAVE_ISASCII              /* just in case */
00295 #  define HAVE_ISASCII 1
00296 #else
00297 #endif
00298 #if STDC_HEADERS || !HAVE_ISASCII
00299 #  define is_ascii(c) 1
00300 #else
00301 #  define is_ascii(c) isascii(c)
00302 #endif
00303 
00304 #define is_space(c) (is_ascii(c) && isspace(c))
00305 #define is_alpha(c) (is_ascii(c) && isalpha(c))
00306 #define is_alnum(c) (is_ascii(c) && isalnum(c))
00307 
00308 /* Scanning macros */
00309 #define isidchar(ch) (is_alnum(ch) || (ch) == '_')
00310 #define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_')
00311 
00312 /* Forward references */
00313 char *skipspace();
00314 int writeblanks();
00315 int test1();
00316 int convert1();
00317 
00318 /* The main program */
00319 int
00320 main(argc, argv)
00321     int argc;
00322     char *argv[];
00323 {      FILE *in, *out;
00324 #define bufsize 5000               /* arbitrary size */
00325        char *buf;
00326        char *line;
00327        char *more;
00328        /*
00329         * In previous versions, ansi2knr recognized a --varargs switch.
00330         * If this switch was supplied, ansi2knr would attempt to convert
00331         * a ... argument to va_alist and va_dcl; if this switch was not
00332         * supplied, ansi2knr would simply drop any such arguments.
00333         * Now, ansi2knr always does this conversion, and we only
00334         * check for this switch for backward compatibility.
00335         */
00336        int convert_varargs = 1;
00337 
00338        if ( argc > 1 && argv[1][0] == '-' )
00339          {    if ( !strcmp(argv[1], "--varargs") )
00340                 {    convert_varargs = 1;
00341                      argc--;
00342                      argv++;
00343                 }
00344               else
00345                 {    fprintf(stderr, "Unrecognized switch: %s\n", argv[1]);
00346                      exit(1);
00347                 }
00348          }
00349        switch ( argc )
00350           {
00351        default:
00352               printf("Usage: ansi2knr input_file [output_file]\n");
00353               exit(0);
00354        case 2:
00355               out = stdout;
00356               break;
00357        case 3:
00358               out = fopen(argv[2], "w");
00359               if ( out == NULL )
00360                  {   fprintf(stderr, "Cannot open output file %s\n", argv[2]);
00361                      exit(1);
00362                  }
00363           }
00364        in = fopen(argv[1], "r");
00365        if ( in == NULL )
00366           {   fprintf(stderr, "Cannot open input file %s\n", argv[1]);
00367               exit(1);
00368           }
00369        fprintf(out, "#line 1 \"%s\"\n", argv[1]);
00370        buf = malloc(bufsize);
00371        line = buf;
00372        while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
00373           {
00374 test:         line += strlen(line);
00375               switch ( test1(buf) )
00376                  {
00377               case 2:                     /* a function header */
00378                      convert1(buf, out, 1, convert_varargs);
00379                      break;
00380               case 1:                     /* a function */
00381                      /* Check for a { at the start of the next line. */
00382                      more = ++line;
00383 f:                   if ( line >= buf + (bufsize - 1) ) /* overflow check */
00384                        goto wl;
00385                      if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL )
00386                        goto wl;
00387                      switch ( *skipspace(more, 1) )
00388                        {
00389                        case '{':
00390                          /* Definitely a function header. */
00391                          convert1(buf, out, 0, convert_varargs);
00392                          fputs(more, out);
00393                          break;
00394                        case 0:
00395                          /* The next line was blank or a comment: */
00396                          /* keep scanning for a non-comment. */
00397                          line += strlen(line);
00398                          goto f;
00399                        default:
00400                          /* buf isn't a function header, but */
00401                          /* more might be. */
00402                          fputs(buf, out);
00403                          strcpy(buf, more);
00404                          line = buf;
00405                          goto test;
00406                        }
00407                      break;
00408               case -1:             /* maybe the start of a function */
00409                      if ( line != buf + (bufsize - 1) ) /* overflow check */
00410                        continue;
00411                      /* falls through */
00412               default:             /* not a function */
00413 wl:                  fputs(buf, out);
00414                      break;
00415                  }
00416               line = buf;
00417           }
00418        if ( line != buf )
00419          fputs(buf, out);
00420        free(buf);
00421        fclose(out);
00422        fclose(in);
00423        return 0;
00424 }
00425 
00426 /* Skip over space and comments, in either direction. */
00427 char *
00428 skipspace(p, dir)
00429     register char *p;
00430     register int dir;                     /* 1 for forward, -1 for backward */
00431 {      for ( ; ; )
00432           {   while ( is_space(*p) )
00433                 p += dir;
00434               if ( !(*p == '/' && p[dir] == '*') )
00435                 break;
00436               p += dir;  p += dir;
00437               while ( !(*p == '*' && p[dir] == '/') )
00438                  {   if ( *p == 0 )
00439                        return p;   /* multi-line comment?? */
00440                      p += dir;
00441                  }
00442               p += dir;  p += dir;
00443           }
00444        return p;
00445 }
00446 
00447 /*
00448  * Write blanks over part of a string.
00449  * Don't overwrite end-of-line characters.
00450  */
00451 int
00452 writeblanks(start, end)
00453     char *start;
00454     char *end;
00455 {      char *p;
00456        for ( p = start; p < end; p++ )
00457          if ( *p != '\r' && *p != '\n' )
00458            *p = ' ';
00459        return 0;
00460 }
00461 
00462 /*
00463  * Test whether the string in buf is a function definition.
00464  * The string may contain and/or end with a newline.
00465  * Return as follows:
00466  *     0 - definitely not a function definition;
00467  *     1 - definitely a function definition;
00468  *     2 - definitely a function prototype (NOT USED);
00469  *     -1 - may be the beginning of a function definition,
00470  *            append another line and look again.
00471  * The reason we don't attempt to convert function prototypes is that
00472  * Ghostscript's declaration-generating macros look too much like
00473  * prototypes, and confuse the algorithms.
00474  */
00475 int
00476 test1(buf)
00477     char *buf;
00478 {      register char *p = buf;
00479        char *bend;
00480        char *endfn;
00481        int contin;
00482 
00483        if ( !isidfirstchar(*p) )
00484          return 0;          /* no name at left margin */
00485        bend = skipspace(buf + strlen(buf) - 1, -1);
00486        switch ( *bend )
00487           {
00488           case ';': contin = 0 /*2*/; break;
00489           case ')': contin = 1; break;
00490           case '{': return 0;             /* not a function */
00491           case '}': return 0;             /* not a function */
00492           default: contin = -1;
00493           }
00494        while ( isidchar(*p) )
00495          p++;
00496        endfn = p;
00497        p = skipspace(p, 1);
00498        if ( *p++ != '(' )
00499          return 0;          /* not a function */
00500        p = skipspace(p, 1);
00501        if ( *p == ')' )
00502          return 0;          /* no parameters */
00503        /* Check that the apparent function name isn't a keyword. */
00504        /* We only need to check for keywords that could be followed */
00505        /* by a left parenthesis (which, unfortunately, is most of them). */
00506           {   static char *words[] =
00507                  {   "asm", "auto", "case", "char", "const", "double",
00508                      "extern", "float", "for", "if", "int", "long",
00509                      "register", "return", "short", "signed", "sizeof",
00510                      "static", "switch", "typedef", "unsigned",
00511                      "void", "volatile", "while", 0
00512                  };
00513               char **key = words;
00514               char *kp;
00515               int len = endfn - buf;
00516 
00517               while ( (kp = *key) != 0 )
00518                  {   if ( strlen(kp) == len && !strncmp(kp, buf, len) )
00519                        return 0;   /* name is a keyword */
00520                      key++;
00521                  }
00522           }
00523        return contin;
00524 }
00525 
00526 /* Convert a recognized function definition or header to K&R syntax. */
00527 int
00528 convert1(buf, out, header, convert_varargs)
00529     char *buf;
00530     FILE *out;
00531     int header;                    /* Boolean */
00532     int convert_varargs;    /* Boolean */
00533 {      char *endfn;
00534        register char *p;
00535        char **breaks;
00536        unsigned num_breaks = 2;    /* for testing */
00537        char **btop;
00538        char **bp;
00539        char **ap;
00540        char *vararg = 0;
00541 
00542        /* Pre-ANSI implementations don't agree on whether strchr */
00543        /* is called strchr or index, so we open-code it here. */
00544        for ( endfn = buf; *(endfn++) != '('; )
00545          ;
00546 top:   p = endfn;
00547        breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
00548        if ( breaks == 0 )
00549           {   /* Couldn't allocate break table, give up */
00550               fprintf(stderr, "Unable to allocate break table!\n");
00551               fputs(buf, out);
00552               return -1;
00553           }
00554        btop = breaks + num_breaks * 2 - 2;
00555        bp = breaks;
00556        /* Parse the argument list */
00557        do
00558           {   int level = 0;
00559               char *lp = NULL;
00560               char *rp;
00561               char *end = NULL;
00562 
00563               if ( bp >= btop )
00564                  {   /* Filled up break table. */
00565                      /* Allocate a bigger one and start over. */
00566                      free((char *)breaks);
00567                      num_breaks <<= 1;
00568                      goto top;
00569                  }
00570               *bp++ = p;
00571               /* Find the end of the argument */
00572               for ( ; end == NULL; p++ )
00573                  {   switch(*p)
00574                         {
00575                         case ',':
00576                             if ( !level ) end = p;
00577                             break;
00578                         case '(':
00579                             if ( !level ) lp = p;
00580                             level++;
00581                             break;
00582                         case ')':
00583                             if ( --level < 0 ) end = p;
00584                             else rp = p;
00585                             break;
00586                         case '/':
00587                             p = skipspace(p, 1) - 1;
00588                             break;
00589                         default:
00590                             ;
00591                         }
00592                  }
00593               /* Erase any embedded prototype parameters. */
00594               if ( lp )
00595                 writeblanks(lp + 1, rp);
00596               p--;                 /* back up over terminator */
00597               /* Find the name being declared. */
00598               /* This is complicated because of procedure and */
00599               /* array modifiers. */
00600               for ( ; ; )
00601                  {   p = skipspace(p - 1, -1);
00602                      switch ( *p )
00603                         {
00604                         case ']':  /* skip array dimension(s) */
00605                         case ')':  /* skip procedure args OR name */
00606                         {   int level = 1;
00607                             while ( level )
00608                              switch ( *--p )
00609                                {
00610                                case ']': case ')': level++; break;
00611                                case '[': case '(': level--; break;
00612                                case '/': p = skipspace(p, -1) + 1; break;
00613                                default: ;
00614                                }
00615                         }
00616                             if ( *p == '(' && *skipspace(p + 1, 1) == '*' )
00617                                {   /* We found the name being declared */
00618                                    while ( !isidfirstchar(*p) )
00619                                      p = skipspace(p, 1) + 1;
00620                                    goto found;
00621                                }
00622                             break;
00623                         default:
00624                             goto found;
00625                         }
00626                  }
00627 found:        if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
00628                 {    if ( convert_varargs )
00629                        {    *bp++ = "va_alist";
00630                             vararg = p-2;
00631                        }
00632                      else
00633                        {    p++;
00634                             if ( bp == breaks + 1 )     /* sole argument */
00635                               writeblanks(breaks[0], p);
00636                             else
00637                               writeblanks(bp[-1] - 1, p);
00638                             bp--;
00639                        }
00640                  }
00641               else
00642                  {   while ( isidchar(*p) ) p--;
00643                      *bp++ = p+1;
00644                  }
00645               p = end;
00646           }
00647        while ( *p++ == ',' );
00648        *bp = p;
00649        /* Make a special check for 'void' arglist */
00650        if ( bp == breaks+2 )
00651           {   p = skipspace(breaks[0], 1);
00652               if ( !strncmp(p, "void", 4) )
00653                  {   p = skipspace(p+4, 1);
00654                      if ( p == breaks[2] - 1 )
00655                         {   bp = breaks;  /* yup, pretend arglist is empty */
00656                             writeblanks(breaks[0], p + 1);
00657                         }
00658                  }
00659           }
00660        /* Put out the function name and left parenthesis. */
00661        p = buf;
00662        while ( p != endfn ) putc(*p, out), p++;
00663        /* Put out the declaration. */
00664        if ( header )
00665          {    fputs(");", out);
00666               for ( p = breaks[0]; *p; p++ )
00667                 if ( *p == '\r' || *p == '\n' )
00668                   putc(*p, out);
00669          }
00670        else
00671          {    for ( ap = breaks+1; ap < bp; ap += 2 )
00672                 {    p = *ap;
00673                      while ( isidchar(*p) )
00674                        putc(*p, out), p++;
00675                      if ( ap < bp - 1 )
00676                        fputs(", ", out);
00677                 }
00678               fputs(")  ", out);
00679               /* Put out the argument declarations */
00680               for ( ap = breaks+2; ap <= bp; ap += 2 )
00681                 (*ap)[-1] = ';';
00682               if ( vararg != 0 )
00683                 {    *vararg = 0;
00684                      fputs(breaks[0], out);             /* any prior args */
00685                      fputs("va_dcl", out);              /* the final arg */
00686                      fputs(bp[0], out);
00687                 }
00688               else
00689                 fputs(breaks[0], out);
00690          }
00691        free((char *)breaks);
00692        return 0;
00693 }