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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1.1.1 - (show annotations) (vendor branch)
Tue Jun 6 03:41:37 2006 UTC (19 years, 9 months ago) by sysadm
Branch: GNU, MAIN
CVS Tags: arelease, HEAD
Changes since 1.1: +0 -0 lines
Content type: text/x-csrc
no message

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