/[LeafOK_CVS]/pvpgn-1.7.4/src/autoconf/ansi2knr.c
ViewVC logotype

Annotation of /pvpgn-1.7.4/src/autoconf/ansi2knr.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations)
Tue Jun 6 03:41:37 2006 UTC (19 years, 9 months ago) by sysadm
CVS Tags: pvpgn_1-7-4-0_MIL
Branch point for: GNU, MAIN
Content type: text/x-csrc
Initial revision

1 sysadm 1.1 /* Copyright (C) 1989, 1997, 1998 Aladdin Enterprises. All rights reserved. */
2    
3     /*$Id: ansi2knr.c,v 1.1.1.1 2002/12/27 08:45:08 dizzy Exp $*/
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     or, if there is no file named COPYLEFT, a file named COPYING. Among other
18     things, the copyright notice and this notice must be preserved on all
19     copies.
20    
21     We explicitly state here what we believe is already implied by the GPL: if
22     the ansi2knr program is distributed as a separate set of sources and a
23     separate executable file which are aggregated on a storage medium together
24     with another program, this in itself does not bring the other program under
25     the GPL, nor does the mere fact that such a program or the procedures for
26     constructing it invoke the ansi2knr executable bring any other part of the
27     program under the GPL.
28     */
29    
30     /*
31     * Usage:
32     ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]
33     * --filename provides the file name for the #line directive in the output,
34     * overriding input_file (if present).
35     * If no input_file is supplied, input is read from stdin.
36     * If no output_file is supplied, output goes to stdout.
37     * There are no error messages.
38     *
39     * ansi2knr recognizes function definitions by seeing one or more
40     * identifiers at the left margin, possibly including function pointer
41     * types, eventually followed by a left parenthesis with a right
42     * parenthesis after that and with a left brace as the first token on
43     * the next line. ansi2knr will recognize a multi-line header provided
44     * that no intervening line ends with a left or right brace or a
45     * semicolon. These algorithms ignore whitespace and comments.
46     * The following constructs will confuse it:
47     * - Any other construct that starts at the left margin and
48     * follows the above syntax (such as a macro or function call).
49     * - Some macros that tinker with the syntax of the function header.
50     */
51    
52     /*
53     * The original and principal author of ansi2knr is L. Peter Deutsch
54     * <ghost@aladdin.com>. Other authors are noted in the change history
55     * that follows (in reverse chronological order):
56     rac 2000-08-02 modified to not force the return values to be
57     on the preceding line, to transform prototypes, to
58     remove the "void" single parameter restriction, and to
59     handle function pointers with ANSI style parameters.
60     lpd 1998-11-09 added further hack to recognize identifier(void)
61     as being a procedure
62     lpd 1998-10-23 added hack to recognize lines consisting of
63     identifier1(identifier2) as *not* being procedures
64     lpd 1997-12-08 made input_file optional; only closes input and/or
65     output file if not stdin or stdout respectively; prints
66     usage message on stderr rather than stdout; adds
67     --filename switch (changes suggested by
68     <ceder@lysator.liu.se>)
69     lpd 1996-01-21 added code to cope with not HAVE_CONFIG_H and with
70     compilers that don't understand void, as suggested by
71     Tom Lane
72     lpd 1996-01-15 changed to require that the first non-comment token
73     on the line following a function header be a left brace,
74     to reduce sensitivity to macros, as suggested by Tom Lane
75     <tgl@sss.pgh.pa.us>
76     lpd 1995-06-22 removed #ifndefs whose sole purpose was to define
77     undefined preprocessor symbols as 0; changed all #ifdefs
78     for configuration symbols to #ifs
79     lpd 1995-04-05 changed copyright notice to make it clear that
80     including ansi2knr in a program does not bring the entire
81     program under the GPL
82     lpd 1994-12-18 added conditionals for systems where ctype macros
83     don't handle 8-bit characters properly, suggested by
84     Francois Pinard <pinard@iro.umontreal.ca>;
85     removed --varargs switch (this is now the default)
86     lpd 1994-10-10 removed CONFIG_BROKETS conditional
87     lpd 1994-07-16 added some conditionals to help GNU `configure',
88     suggested by Francois Pinard <pinard@iro.umontreal.ca>;
89     properly erase prototype args in function parameters,
90     contributed by Jim Avera <jima@netcom.com>;
91     correct error in writeblanks (it shouldn't erase EOLs)
92     lpd 1989-xx-xx original version
93     */
94    
95     /* Most of the conditionals here are to make ansi2knr work with */
96     /* or without the GNU configure machinery. */
97    
98     #if HAVE_CONFIG_H
99     # include <config.h>
100     #endif
101    
102     #include <stdio.h>
103     #include <ctype.h>
104    
105     #if HAVE_CONFIG_H
106    
107     /*
108     For properly autoconfiguring ansi2knr, use AC_CONFIG_HEADER(config.h).
109     This will define HAVE_CONFIG_H and so, activate the following lines.
110     */
111    
112     # if STDC_HEADERS || HAVE_STRING_H
113     # include <string.h>
114     # else
115     # include <strings.h>
116     # endif
117    
118     #else /* not HAVE_CONFIG_H */
119    
120     /* Otherwise do it the hard way */
121    
122     # ifdef BSD
123     # include <strings.h>
124     # else
125     # ifdef VMS
126     extern int strlen(), strncmp();
127     # else
128     # include <string.h>
129     # endif
130     # endif
131    
132     #endif /* not HAVE_CONFIG_H */
133    
134     #if STDC_HEADERS
135     # include <stdlib.h>
136     #else
137     /*
138     malloc and free should be declared in stdlib.h,
139     but if you've got a K&R compiler, they probably aren't.
140     */
141     # ifdef MSDOS
142     # include <malloc.h>
143     # else
144     # ifdef VMS
145     extern char *malloc();
146     extern void free();
147     # else
148     extern char *malloc();
149     extern int free();
150     # endif
151     # endif
152    
153     #endif
154    
155     /*
156     * The ctype macros don't always handle 8-bit characters correctly.
157     * Compensate for this here.
158     */
159     #ifdef isascii
160     # undef HAVE_ISASCII /* just in case */
161     # define HAVE_ISASCII 1
162     #else
163     #endif
164     #if STDC_HEADERS || !HAVE_ISASCII
165     # define is_ascii(c) 1
166     #else
167     # define is_ascii(c) isascii(c)
168     #endif
169    
170     #define is_space(c) (is_ascii(c) && isspace(c))
171     #define is_alpha(c) (is_ascii(c) && isalpha(c))
172     #define is_alnum(c) (is_ascii(c) && isalnum(c))
173    
174     /* Scanning macros */
175     #define isidchar(ch) (is_alnum(ch) || (ch) == '_')
176     #define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_')
177    
178     /* Forward references */
179     static char *skipspace();
180     static int writeblanks();
181     static int test1();
182     static int convert1();
183    
184     static char *startfn;
185     static char *endfn;
186    
187     /* The main program */
188     int
189     main(argc, argv)
190     int argc;
191     char *argv[];
192     { FILE *in = stdin;
193     FILE *out = stdout;
194     char *filename = 0;
195     #define bufsize 5000 /* arbitrary size */
196     char *buf;
197     char *line;
198     char *more;
199     char *usage =
200     "Usage: ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]\n";
201     /*
202     * In previous versions, ansi2knr recognized a --varargs switch.
203     * If this switch was supplied, ansi2knr would attempt to convert
204     * a ... argument to va_alist and va_dcl; if this switch was not
205     * supplied, ansi2knr would simply drop any such arguments.
206     * Now, ansi2knr always does this conversion, and we only
207     * check for this switch for backward compatibility.
208     */
209     int convert_varargs = 1;
210    
211     while ( argc > 1 && argv[1][0] == '-' ) {
212     if ( !strcmp(argv[1], "--varargs") ) {
213     convert_varargs = 1;
214     argc--;
215     argv++;
216     continue;
217     }
218     if ( !strcmp(argv[1], "--filename") && argc > 2 ) {
219     filename = argv[2];
220     argc -= 2;
221     argv += 2;
222     continue;
223     }
224     fprintf(stderr, "Unrecognized switch: %s\n", argv[1]);
225     fprintf(stderr, usage);
226     exit(1);
227     }
228     switch ( argc )
229     {
230     default:
231     fprintf(stderr, usage);
232     exit(0);
233     case 3:
234     out = fopen(argv[2], "w");
235     if ( out == NULL ) {
236     fprintf(stderr, "Cannot open output file %s\n", argv[2]);
237     exit(1);
238     }
239     /* falls through */
240     case 2:
241     in = fopen(argv[1], "r");
242     if ( in == NULL ) {
243     fprintf(stderr, "Cannot open input file %s\n", argv[1]);
244     exit(1);
245     }
246     if ( filename == 0 )
247     filename = argv[1];
248     /* falls through */
249     case 1:
250     break;
251     }
252     if ( filename )
253     fprintf(out, "#line 1 \"%s\"\n", filename);
254     buf = malloc(bufsize);
255     line = buf;
256     while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
257     {
258     test: line += strlen(line);
259     switch ( test1(buf) )
260     {
261     case 3: /* a function pointer */
262     case 2: /* a function prototype */
263     convert1(buf, out, 1, convert_varargs);
264     break;
265     case 1: /* a function */
266     /* Check for a { at the start of the next line. */
267     more = ++line;
268     f: if ( line >= buf + (bufsize - 1) ) /* overflow check */
269     goto wl;
270     if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL )
271     goto wl;
272     switch ( *skipspace(more, 1) )
273     {
274     case '{':
275     /* Definitely a function */
276     convert1(buf, out, 0, convert_varargs);
277     fputs(more, out);
278     break;
279     case 0:
280     /* The next line was blank or a comment: */
281     /* keep scanning for a non-comment. */
282     line += strlen(line);
283     goto f;
284     default:
285     /* buf isn't a function header, but */
286     /* more might be. */
287     fputs(buf, out);
288     strcpy(buf, more);
289     line = buf;
290     goto test;
291     }
292     break;
293     case -1: /* maybe the start of a function */
294     if ( line != buf + (bufsize - 1) ) /* overflow check */
295     continue;
296     /* falls through */
297     default: /* not a function */
298     wl: fputs(buf, out);
299     break;
300     }
301     line = buf;
302     }
303     if ( line != buf )
304     fputs(buf, out);
305     free(buf);
306     if ( out != stdout )
307     fclose(out);
308     if ( in != stdin )
309     fclose(in);
310     return 0;
311     }
312    
313    
314     /* Skip over space and comments, in either direction. */
315     static char *
316     skipspace(p, dir)
317     char *p;
318     int dir; /* 1 for forward, -1 for backward */
319     { if (*p=='\0') return p;
320     for ( ; ; )
321     { while ( is_space(*p) )
322     p += dir;
323     if ( !(*p == '/' && p[dir] == '*') )
324     break;
325     p += dir; p += dir;
326     while ( !(*p == '*' && p[dir] == '/') )
327     { if ( *p == 0 )
328     return p; /* multi-line comment?? */
329     p += dir;
330     }
331     p += dir; p += dir;
332     }
333     return p;
334     }
335    
336     /*
337     * Write blanks over part of a string.
338     * Don't overwrite end-of-line characters.
339     */
340     static int
341     writeblanks(start, end)
342     char *start;
343     char *end;
344     { char *p;
345     for ( p = start; p < end; p++ )
346     if ( *p != '\r' && *p != '\n' )
347     *p = ' ';
348     return 0;
349     }
350    
351     /*
352     * Test whether the string in buf is a function definition.
353     * The string may contain and/or end with a newline.
354     * Return as follows:
355     * 0 - definitely not a function definition;
356     * 1 - definitely a function definition;
357     * 2 - definitely a function prototype;
358     * 3 - definitely a function pointer;
359     * -1 - may be the beginning of a function definition,
360     * append another line and look again.
361     */
362     static int
363     test1(buf)
364     char *buf;
365     { char *p;
366     char *bend;
367     int contin;
368    
369     if ( !isalpha(*buf) )
370     return 0; /* no name at left margin */
371     bend = skipspace(buf + strlen(buf) - 1, -1);
372     switch ( *bend )
373     {
374     case ';': contin = 2; break;
375     case ')': contin = 1; break;
376     case '{':
377     case '}':
378     return 0; /* not a function */
379     default: contin = -1;
380     }
381    
382     /* find start and end of function name */
383     startfn=buf;
384     while (*startfn!='\0' && *startfn!='(')
385     {
386     startfn++;
387     startfn = skipspace(startfn, 1);
388     }
389     if (*startfn=='\0')
390     return 0; /* not a function */
391     startfn--;
392     p = startfn;
393     startfn = skipspace(startfn,-1);
394     endfn = startfn+1;
395     while (isidchar(*startfn)) startfn--;
396     startfn++;
397     if (startfn>=endfn)
398     return 0;
399    
400     p = skipspace(endfn, 1);
401     #if 0
402     /* v v */
403     /* typedef __ssize_t __io_read_ */
404     fprintf(stderr,"found %s\n",buf);
405     fprintf(stderr,"func=");
406     { int i; for (i=0; i<endfn-startfn; i++) fprintf(stderr,"%c",startfn[i]); }
407     fprintf(stderr,"\n");
408     fprintf(stderr,"p=%s\n",p);
409     #endif
410     p++; /* skip ( */
411     p = skipspace(p, 1);
412     if (*p=='*') /* maybe a function pointer */
413     {
414     startfn = p;
415     while (*p!='\0' && *p!=')')
416     p++;
417     if (*p=='\0')
418     return -1; /* wraps to the next line */
419     endfn = p-1;
420     if (contin!=-1) contin = 3;
421     }
422     else
423     if (!isidfirstchar(*p))
424     return 0; /* ok... no parameters anyway */
425    
426     /* Check that the apparent function name isn't a keyword. */
427     /* We only need to check for keywords that could be followed */
428     /* by a left parenthesis (which, unfortunately, is most of them). */
429     if (contin != 3)
430     { static char *words[] =
431     { "asm", "auto", "case", "char", "const", "double",
432     "extern", "float", "for", "if", "int", "long",
433     "register", "return", "short", "signed", "sizeof",
434     "static", "switch", "typedef", "unsigned",
435     "void", "volatile", "while", 0
436     };
437     char **key = words;
438     char *kp;
439     int len = endfn - startfn;
440    
441     while ( (kp = *key) != 0 )
442     { if ( strlen(kp) == len && !strncmp(kp, startfn, len) )
443     {
444     fprintf(stderr,"it was a keyword\n");
445     return 0; /* name is a keyword */
446     }
447     key++;
448     }
449     }
450     /*
451     * If the last significant character was a ), we need to count
452     * parentheses, because it might be part of a formal parameter
453     * that is a procedure.
454     */
455     if (contin > 0) {
456     int level = 0;
457    
458     for (p = endfn; *p; p = skipspace(p + 1, 1))
459     level += (*p == '(' ? 1 : *p == ')' ? -1 : 0);
460     if (level > 0)
461     contin = -1;
462     }
463     return contin;
464     }
465    
466     /* Convert a recognized function definition or header to K&R syntax. */
467     static int
468     convert1(buf, out, header, convert_varargs)
469     char *buf;
470     FILE *out;
471     int header; /* Boolean */
472     int convert_varargs; /* Boolean */
473     {
474     char *p;
475     /*
476     * The breaks table contains pointers to the beginning and end
477     * of each argument.
478     */
479     char **breaks;
480     unsigned num_breaks = 2; /* for testing */
481     char **btop;
482     char **bp;
483     char **ap;
484     char *vararg = 0;
485    
486     for (p=buf; p<startfn; p++)
487     fprintf(out,"%c",*p);
488    
489     while (*(endfn++) != '(');
490    
491     top: p = endfn;
492     breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
493     if ( breaks == 0 )
494     { /* Couldn't allocate break table, give up */
495     fprintf(stderr, "Unable to allocate break table!\n");
496     fputs(startfn, out);
497     return -1;
498     }
499     btop = breaks + num_breaks * 2 - 2;
500     bp = breaks;
501     /* Parse the argument list */
502     do
503     { int level = 0;
504     char *lp = NULL;
505     char *rp;
506     char *end = NULL;
507    
508     if ( bp >= btop )
509     { /* Filled up break table. */
510     /* Allocate a bigger one and start over. */
511     free((char *)breaks);
512     num_breaks <<= 1;
513     goto top;
514     }
515     *bp++ = p;
516     /* Find the end of the argument */
517     for ( ; end == NULL; p++ )
518     { switch(*p)
519     {
520     case ',':
521     if ( !level ) end = p;
522     break;
523     case '(':
524     if ( !level ) lp = p;
525     level++;
526     break;
527     case ')':
528     if ( --level < 0 ) end = p;
529     else rp = p;
530     break;
531     case '/':
532     p = skipspace(p, 1) - 1;
533     break;
534     default:
535     ;
536     }
537     }
538     /* Erase any embedded function pointer parameters. */
539     if ( lp )
540     writeblanks(lp + 1, rp);
541     p--; /* back up over terminator */
542     /* Find the name being declared. */
543     /* This is complicated because of procedure and */
544     /* array modifiers. */
545     for ( ; ; )
546     { p = skipspace(p - 1, -1);
547     switch ( *p )
548     {
549     case ']': /* skip array dimension(s) */
550     case ')': /* skip procedure args OR name */
551     { int level = 1;
552     while ( level )
553     switch ( *--p )
554     {
555     case ']': case ')': level++; break;
556     case '[': case '(': level--; break;
557     case '/': p = skipspace(p, -1) + 1; break;
558     default: ;
559     }
560     }
561     if ( *p == '(' && *skipspace(p + 1, 1) == '*' )
562     { /* We found the name of the function pointer */
563     while ( !isidfirstchar(*p) )
564     p = skipspace(p, 1) + 1;
565     goto found;
566     }
567     break;
568     default:
569     goto found;
570     }
571     }
572     found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
573     { if ( convert_varargs )
574     { *bp++ = "va_alist";
575     vararg = p-2;
576     }
577     else
578     { p++;
579     if ( bp == breaks + 1 ) /* sole argument */
580     writeblanks(breaks[0], p);
581     else
582     writeblanks(bp[-1] - 1, p);
583     bp--;
584     }
585     }
586     else
587     { while ( isidchar(*p) ) p--;
588     *bp++ = p+1;
589     }
590     p = end;
591     }
592     while ( *p++ == ',' );
593     *bp = p;
594     /* Make a special check for 'void' arglist */
595     if ( bp == breaks+2 )
596     { p = skipspace(breaks[0], 1);
597     if ( !strncmp(p, "void", 4) )
598     { p = skipspace(p+4, 1);
599     if ( p == breaks[2] - 1 )
600     { bp = breaks; /* yup, pretend arglist is empty */
601     writeblanks(breaks[0], p + 1);
602     }
603     }
604     }
605     /* Put out the function name and left parenthesis. */
606     for (p=startfn; p != endfn; p++) putc(*p, out);
607     /* Put out the declaration. */
608     if ( header )
609     { fputs(");", out);
610     for ( p = breaks[0]; *p; p++ )
611     if ( *p == '\r' || *p == '\n' )
612     putc(*p, out);
613     }
614     else
615     { for ( ap = breaks+1; ap < bp; ap += 2 )
616     { p = *ap;
617     while ( isidchar(*p) )
618     putc(*p, out), p++;
619     if ( ap < bp - 1 )
620     fputs(", ", out);
621     }
622     fputs(") ", out);
623     /* Put out the argument declarations */
624     for ( ap = breaks+2; ap <= bp; ap += 2 )
625     (*ap)[-1] = ';';
626     if ( vararg != 0 )
627     { *vararg = 0;
628     fputs(breaks[0], out); /* any prior args */
629     fputs("va_dcl", out); /* the final arg */
630     fputs(bp[0], out);
631     }
632     else
633     fputs(breaks[0], out);
634     }
635     free((char *)breaks);
636     return 0;
637     }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1