source: trunk/essentials/sys-devel/automake-1.4/ansi2knr.c@ 3125

Last change on this file since 3125 was 3124, checked in by bird, 19 years ago

automake 1.4-p6

File size: 16.4 KB
Line 
1/* Copyright (C) 1989, 1997, 1998 Aladdin Enterprises. All rights reserved. */
2
3/*$Id: ansi2knr.c $*/
4/* Convert ANSI C function definitions to K&R ("traditional C") syntax */
5
6/*
7ansi2knr is distributed in the hope that it will be useful, but WITHOUT ANY
8WARRANTY. No author or distributor accepts responsibility to anyone for the
9consequences of using it or for whether it serves any particular purpose or
10works at all, unless he says so in writing. Refer to the GNU General Public
11License (the "GPL") for full details.
12
13Everyone is granted permission to copy, modify and redistribute ansi2knr,
14but only under the conditions described in the GPL. A copy of this license
15is supposed to have been given to you along with ansi2knr so you can know
16your rights and responsibilities. It should be in a file named COPYLEFT,
17or, if there is no file named COPYLEFT, a file named COPYING. Among other
18things, the copyright notice and this notice must be preserved on all
19copies.
20
21We explicitly state here what we believe is already implied by the GPL: if
22the ansi2knr program is distributed as a separate set of sources and a
23separate executable file which are aggregated on a storage medium together
24with another program, this in itself does not bring the other program under
25the GPL, nor does the mere fact that such a program or the procedures for
26constructing it invoke the ansi2knr executable bring any other part of the
27program 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 a non-keyword
40 * identifier at the left margin, followed by a left parenthesis,
41 * with a right parenthesis as the last character on the line,
42 * and with a left brace as the first token on the following line
43 * (ignoring possible intervening comments), except that a line
44 * consisting of only
45 * identifier1(identifier2)
46 * will not be considered a function definition unless identifier2 is
47 * the word "void". ansi2knr will recognize a multi-line header provided
48 * that no intervening line ends with a left or right brace or a semicolon.
49 * These algorithms ignore whitespace and comments, except that
50 * the function name must be the first thing on the line.
51 * The following constructs will confuse it:
52 * - Any other construct that starts at the left margin and
53 * follows the above syntax (such as a macro or function call).
54 * - Some macros that tinker with the syntax of the function header.
55 */
56
57/*
58 * The original and principal author of ansi2knr is L. Peter Deutsch
59 * <[email protected]>. Other authors are noted in the change history
60 * that follows (in reverse chronological order):
61 lpd 1998-11-09 added further hack to recognize identifier(void)
62 as being a procedure
63 lpd 1998-10-23 added hack to recognize lines consisting of
64 identifier1(identifier2) as *not* being procedures
65 lpd 1997-12-08 made input_file optional; only closes input and/or
66 output file if not stdin or stdout respectively; prints
67 usage message on stderr rather than stdout; adds
68 --filename switch (changes suggested by
69 <[email protected]>)
70 lpd 1996-01-21 added code to cope with not HAVE_CONFIG_H and with
71 compilers that don't understand void, as suggested by
72 Tom Lane
73 lpd 1996-01-15 changed to require that the first non-comment token
74 on the line following a function header be a left brace,
75 to reduce sensitivity to macros, as suggested by Tom Lane
76 <[email protected]>
77 lpd 1995-06-22 removed #ifndefs whose sole purpose was to define
78 undefined preprocessor symbols as 0; changed all #ifdefs
79 for configuration symbols to #ifs
80 lpd 1995-04-05 changed copyright notice to make it clear that
81 including ansi2knr in a program does not bring the entire
82 program under the GPL
83 lpd 1994-12-18 added conditionals for systems where ctype macros
84 don't handle 8-bit characters properly, suggested by
85 Francois Pinard <[email protected]>;
86 removed --varargs switch (this is now the default)
87 lpd 1994-10-10 removed CONFIG_BROKETS conditional
88 lpd 1994-07-16 added some conditionals to help GNU `configure',
89 suggested by Francois Pinard <[email protected]>;
90 properly erase prototype args in function parameters,
91 contributed by Jim Avera <[email protected]>;
92 correct error in writeblanks (it shouldn't erase EOLs)
93 lpd 1989-xx-xx original version
94 */
95
96/* Most of the conditionals here are to make ansi2knr work with */
97/* or without the GNU configure machinery. */
98
99#if HAVE_CONFIG_H
100# include <config.h>
101#endif
102
103#include <stdio.h>
104#include <ctype.h>
105
106#if HAVE_CONFIG_H
107
108/*
109 For properly autoconfiguring ansi2knr, use AC_CONFIG_HEADER(config.h).
110 This will define HAVE_CONFIG_H and so, activate the following lines.
111 */
112
113# if STDC_HEADERS || HAVE_STRING_H
114# include <string.h>
115# else
116# include <strings.h>
117# endif
118
119#else /* not HAVE_CONFIG_H */
120
121/* Otherwise do it the hard way */
122
123# ifdef BSD
124# include <strings.h>
125# else
126# ifdef VMS
127 extern int strlen(), strncmp();
128# else
129# include <string.h>
130# endif
131# endif
132
133#endif /* not HAVE_CONFIG_H */
134
135#if STDC_HEADERS
136# include <stdlib.h>
137#else
138/*
139 malloc and free should be declared in stdlib.h,
140 but if you've got a K&R compiler, they probably aren't.
141 */
142# ifdef MSDOS
143# include <malloc.h>
144# else
145# ifdef VMS
146 extern char *malloc();
147 extern void free();
148# else
149 extern char *malloc();
150 extern int free();
151# endif
152# endif
153
154#endif
155
156/*
157 * The ctype macros don't always handle 8-bit characters correctly.
158 * Compensate for this here.
159 */
160#ifdef isascii
161# undef HAVE_ISASCII /* just in case */
162# define HAVE_ISASCII 1
163#else
164#endif
165#if STDC_HEADERS || !HAVE_ISASCII
166# define is_ascii(c) 1
167#else
168# define is_ascii(c) isascii(c)
169#endif
170
171#define is_space(c) (is_ascii(c) && isspace(c))
172#define is_alpha(c) (is_ascii(c) && isalpha(c))
173#define is_alnum(c) (is_ascii(c) && isalnum(c))
174
175/* Scanning macros */
176#define isidchar(ch) (is_alnum(ch) || (ch) == '_')
177#define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_')
178
179/* Forward references */
180char *skipspace();
181int writeblanks();
182int test1();
183int convert1();
184
185/* The main program */
186int
187main(argc, argv)
188 int argc;
189 char *argv[];
190{ FILE *in = stdin;
191 FILE *out = stdout;
192 char *filename = 0;
193#define bufsize 5000 /* arbitrary size */
194 char *buf;
195 char *line;
196 char *more;
197 char *usage =
198 "Usage: ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]\n";
199 /*
200 * In previous versions, ansi2knr recognized a --varargs switch.
201 * If this switch was supplied, ansi2knr would attempt to convert
202 * a ... argument to va_alist and va_dcl; if this switch was not
203 * supplied, ansi2knr would simply drop any such arguments.
204 * Now, ansi2knr always does this conversion, and we only
205 * check for this switch for backward compatibility.
206 */
207 int convert_varargs = 1;
208
209 while ( argc > 1 && argv[1][0] == '-' ) {
210 if ( !strcmp(argv[1], "--varargs") ) {
211 convert_varargs = 1;
212 argc--;
213 argv++;
214 continue;
215 }
216 if ( !strcmp(argv[1], "--filename") && argc > 2 ) {
217 filename = argv[2];
218 argc -= 2;
219 argv += 2;
220 continue;
221 }
222 fprintf(stderr, "Unrecognized switch: %s\n", argv[1]);
223 fprintf(stderr, usage);
224 exit(1);
225 }
226 switch ( argc )
227 {
228 default:
229 fprintf(stderr, usage);
230 exit(0);
231 case 3:
232 out = fopen(argv[2], "w");
233 if ( out == NULL ) {
234 fprintf(stderr, "Cannot open output file %s\n", argv[2]);
235 exit(1);
236 }
237 /* falls through */
238 case 2:
239 in = fopen(argv[1], "r");
240 if ( in == NULL ) {
241 fprintf(stderr, "Cannot open input file %s\n", argv[1]);
242 exit(1);
243 }
244 if ( filename == 0 )
245 filename = argv[1];
246 /* falls through */
247 case 1:
248 break;
249 }
250 if ( filename )
251 fprintf(out, "#line 1 \"%s\"\n", filename);
252 buf = malloc(bufsize);
253 line = buf;
254 while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
255 {
256test: line += strlen(line);
257 switch ( test1(buf) )
258 {
259 case 2: /* a function header */
260 convert1(buf, out, 1, convert_varargs);
261 break;
262 case 1: /* a function */
263 /* Check for a { at the start of the next line. */
264 more = ++line;
265f: if ( line >= buf + (bufsize - 1) ) /* overflow check */
266 goto wl;
267 if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL )
268 goto wl;
269 switch ( *skipspace(more, 1) )
270 {
271 case '{':
272 /* Definitely a function header. */
273 convert1(buf, out, 0, convert_varargs);
274 fputs(more, out);
275 break;
276 case 0:
277 /* The next line was blank or a comment: */
278 /* keep scanning for a non-comment. */
279 line += strlen(line);
280 goto f;
281 default:
282 /* buf isn't a function header, but */
283 /* more might be. */
284 fputs(buf, out);
285 strcpy(buf, more);
286 line = buf;
287 goto test;
288 }
289 break;
290 case -1: /* maybe the start of a function */
291 if ( line != buf + (bufsize - 1) ) /* overflow check */
292 continue;
293 /* falls through */