1 |
38 |
julius |
/* fix-header.c - Make C header file suitable for C++.
|
2 |
|
|
Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
3 |
|
|
2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
|
4 |
|
|
|
5 |
|
|
This program is free software; you can redistribute it and/or modify it
|
6 |
|
|
under the terms of the GNU General Public License as published by the
|
7 |
|
|
Free Software Foundation; either version 3, or (at your option) any
|
8 |
|
|
later version.
|
9 |
|
|
|
10 |
|
|
This program is distributed in the hope that it will be useful,
|
11 |
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
|
|
GNU General Public License for more details.
|
14 |
|
|
|
15 |
|
|
You should have received a copy of the GNU General Public License
|
16 |
|
|
along with this program; see the file COPYING3. If not see
|
17 |
|
|
<http://www.gnu.org/licenses/>. */
|
18 |
|
|
|
19 |
|
|
/* This program massages a system include file (such as stdio.h),
|
20 |
|
|
into a form that is compatible with GNU C and GNU C++.
|
21 |
|
|
|
22 |
|
|
* extern "C" { ... } braces are added (inside #ifndef __cplusplus),
|
23 |
|
|
if they seem to be needed. These prevent C++ compilers from name
|
24 |
|
|
mangling the functions inside the braces.
|
25 |
|
|
|
26 |
|
|
* If an old-style incomplete function declaration is seen (without
|
27 |
|
|
an argument list), and it is a "standard" function listed in
|
28 |
|
|
the file sys-protos.h (and with a non-empty argument list), then
|
29 |
|
|
the declaration is converted to a complete prototype by replacing
|
30 |
|
|
the empty parameter list with the argument list from sys-protos.h.
|
31 |
|
|
|
32 |
|
|
* The program can be given a list of (names of) required standard
|
33 |
|
|
functions (such as fclose for stdio.h). If a required function
|
34 |
|
|
is not seen in the input, then a prototype for it will be
|
35 |
|
|
written to the output.
|
36 |
|
|
|
37 |
|
|
* If all of the non-comment code of the original file is protected
|
38 |
|
|
against multiple inclusion:
|
39 |
|
|
#ifndef FOO
|
40 |
|
|
#define FOO
|
41 |
|
|
<body of include file>
|
42 |
|
|
#endif
|
43 |
|
|
then extra matter added to the include file is placed inside the <body>.
|
44 |
|
|
|
45 |
|
|
* If the input file is OK (nothing needs to be done);
|
46 |
|
|
the output file is not written (nor removed if it exists).
|
47 |
|
|
|
48 |
|
|
There are also some special actions that are done for certain
|
49 |
|
|
well-known standard include files:
|
50 |
|
|
|
51 |
|
|
* If argv[1] is "sys/stat.h", the Posix.1 macros
|
52 |
|
|
S_ISBLK, S_ISCHR, S_ISDIR, S_ISFIFO, S_ISLNK, S_ISREG are added if
|
53 |
|
|
they were missing, and the corresponding "traditional" S_IFxxx
|
54 |
|
|
macros were defined.
|
55 |
|
|
|
56 |
|
|
* If argv[1] is "errno.h", errno is declared if it was missing.
|
57 |
|
|
|
58 |
|
|
* TODO: The input file should be read complete into memory, because:
|
59 |
|
|
a) it needs to be scanned twice anyway, and
|
60 |
|
|
b) it would be nice to allow update in place.
|
61 |
|
|
|
62 |
|
|
Usage:
|
63 |
|
|
fix-header FOO.H INFILE.H OUTFILE.H [OPTIONS]
|
64 |
|
|
where:
|
65 |
|
|
* FOO.H is the relative file name of the include file,
|
66 |
|
|
as it would be #include'd by a C file. (E.g. stdio.h)
|
67 |
|
|
* INFILE.H is a full pathname for the input file (e.g. /usr/include/stdio.h)
|
68 |
|
|
* OUTFILE.H is the full pathname for where to write the output file,
|
69 |
|
|
if anything needs to be done. (e.g. ./include/stdio.h)
|
70 |
|
|
* OPTIONS can be -D or -I switches as you would pass to cpp.
|
71 |
|
|
|
72 |
|
|
Written by Per Bothner <bothner@cygnus.com>, July 1993. */
|
73 |
|
|
|
74 |
|
|
#include "bconfig.h"
|
75 |
|
|
#include "system.h"
|
76 |
|
|
#include "coretypes.h"
|
77 |
|
|
#include "tm.h"
|
78 |
|
|
#include "obstack.h"
|
79 |
|
|
#include "scan.h"
|
80 |
|
|
#include "cpplib.h"
|
81 |
|
|
#include "c-incpath.h"
|
82 |
|
|
#include "errors.h"
|
83 |
|
|
|
84 |
|
|
#ifdef TARGET_EXTRA_INCLUDES
|
85 |
|
|
void
|
86 |
|
|
TARGET_EXTRA_INCLUDES (const char *sysroot ATTRIBUTE_UNUSED,
|
87 |
|
|
const char *iprefix ATTRIBUTE_UNUSED,
|
88 |
|
|
int stdinc ATTRIBUTE_UNUSED)
|
89 |
|
|
{
|
90 |
|
|
}
|
91 |
|
|
#endif
|
92 |
|
|
|
93 |
|
|
#ifdef TARGET_EXTRA_PRE_INCLUDES
|
94 |
|
|
void
|
95 |
|
|
TARGET_EXTRA_PRE_INCLUDES (const char *sysroot ATTRIBUTE_UNUSED,
|
96 |
|
|
const char *iprefix ATTRIBUTE_UNUSED,
|
97 |
|
|
int stdinc ATTRIBUTE_UNUSED)
|
98 |
|
|
{
|
99 |
|
|
}
|
100 |
|
|
#endif
|
101 |
|
|
|
102 |
|
|
struct line_maps line_table;
|
103 |
|
|
|
104 |
|
|
sstring buf;
|
105 |
|
|
|
106 |
|
|
int verbose = 0;
|
107 |
|
|
int partial_count = 0;
|
108 |
|
|
int warnings = 0;
|
109 |
|
|
|
110 |
|
|
#if ADD_MISSING_EXTERN_C
|
111 |
|
|
int missing_extern_C_count = 0;
|
112 |
|
|
#endif
|
113 |
|
|
|
114 |
|
|
#include "xsys-protos.h"
|
115 |
|
|
|
116 |
|
|
#ifdef FIXPROTO_IGNORE_LIST
|
117 |
|
|
/* This is a currently unused feature. */
|
118 |
|
|
|
119 |
|
|
/* List of files and directories to ignore.
|
120 |
|
|
A directory name (ending in '/') means ignore anything in that
|
121 |
|
|
directory. (It might be more efficient to do directory pruning
|
122 |
|
|
earlier in fixproto, but this is simpler and easier to customize.) */
|
123 |
|
|
|
124 |
|
|
static const char *const files_to_ignore[] = {
|
125 |
|
|
"X11/",
|
126 |
|
|
FIXPROTO_IGNORE_LIST
|
127 |
|
|
|
128 |
|
|
};
|
129 |
|
|
#endif
|
130 |
|
|
|
131 |
|
|
char *inf_buffer;
|
132 |
|
|
char *inf_limit;
|
133 |
|
|
char *inf_ptr;
|
134 |
|
|
static const char *cur_file;
|
135 |
|
|
|
136 |
|
|
/* Certain standard files get extra treatment */
|
137 |
|
|
|
138 |
|
|
enum special_file
|
139 |
|
|
{
|
140 |
|
|
no_special,
|
141 |
|
|
#ifdef errno_h
|
142 |
|
|
#undef errno_h
|
143 |
|
|
#endif
|
144 |
|
|
errno_h,
|
145 |
|
|
#ifdef stdio_h
|
146 |
|
|
#undef stdio_h
|
147 |
|
|
#endif
|
148 |
|
|
stdio_h,
|
149 |
|
|
#ifdef stdlib_h
|
150 |
|
|
#undef stdlib_h
|
151 |
|
|
#endif
|
152 |
|
|
stdlib_h,
|
153 |
|
|
#ifdef sys_stat_h
|
154 |
|
|
#undef sys_stat_h
|
155 |
|
|
#endif
|
156 |
|
|
sys_stat_h
|
157 |
|
|
};
|
158 |
|
|
|
159 |
|
|
/* A NAMELIST is a sequence of names, separated by '\0', and terminated
|
160 |
|
|
by an empty name (i.e. by "\0\0"). */
|
161 |
|
|
|
162 |
|
|
typedef const char *namelist;
|
163 |
|
|
|
164 |
|
|
/* The following macros provide the bits for symbol_flags. */
|
165 |
|
|
typedef int symbol_flags;
|
166 |
|
|
|
167 |
|
|
/* Used to mark names defined in the ANSI/ISO C standard. */
|
168 |
|
|
#define ANSI_SYMBOL 1
|
169 |
|
|
|
170 |
|
|
/* We no longer massage include files for POSIX or XOPEN symbols,
|
171 |
|
|
as there are now several versions of the POSIX and XOPEN standards,
|
172 |
|
|
and it would be a maintenance nightmare for us to track them all.
|
173 |
|
|
Better to be compatible with the system include files. */
|
174 |
|
|
/*#define ADD_MISSING_POSIX 1 */
|
175 |
|
|
/*#define ADD_MISSING_XOPEN 1 */
|
176 |
|
|
|
177 |
|
|
#if ADD_MISSING_POSIX
|
178 |
|
|
/* Used to mark names defined in the Posix.1 or Posix.2 standard. */
|
179 |
|
|
#define POSIX1_SYMBOL 2
|
180 |
|
|
#define POSIX2_SYMBOL 4
|
181 |
|
|
#else
|
182 |
|
|
#define POSIX1_SYMBOL 0
|
183 |
|
|
#define POSIX2_SYMBOL 0
|
184 |
|
|
#endif
|
185 |
|
|
|
186 |
|
|
#if ADD_MISSING_XOPEN
|
187 |
|
|
/* Used to mark names defined in X/Open Portability Guide. */
|
188 |
|
|
#define XOPEN_SYMBOL 8
|
189 |
|
|
/* Used to mark names defined in X/Open UNIX Extensions. */
|
190 |
|
|
#define XOPEN_EXTENDED_SYMBOL 16
|
191 |
|
|
#else
|
192 |
|
|
#define XOPEN_SYMBOL 0
|
193 |
|
|
#define XOPEN_EXTENDED_SYMBOL 0
|
194 |
|
|
#endif
|
195 |
|
|
|
196 |
|
|
/* Used to indicate names that are not functions */
|
197 |
|
|
#define MACRO_SYMBOL 512
|
198 |
|
|
|
199 |
|
|
struct symbol_list {
|
200 |
|
|
symbol_flags flags;
|
201 |
|
|
namelist names;
|
202 |
|
|
};
|
203 |
|
|
|
204 |
|
|
#define SYMBOL_TABLE_SIZE 10
|
205 |
|
|
struct symbol_list symbol_table[SYMBOL_TABLE_SIZE];
|
206 |
|
|
int cur_symbol_table_size;
|
207 |
|
|
|
208 |
|
|
static void add_symbols (symbol_flags, namelist);
|
209 |
|
|
static struct fn_decl *lookup_std_proto (const char *, int);
|
210 |
|
|
static void write_lbrac (void);
|
211 |
|
|
static void recognized_macro (const char *);
|
212 |
|
|
static void check_macro_names (cpp_reader *, namelist);
|
213 |
|
|
static void read_scan_file (char *, int, char **);
|
214 |
|
|
static void write_rbrac (void);
|
215 |
|
|
static int inf_skip_spaces (int);
|
216 |
|
|
static int inf_read_upto (sstring *, int);
|
217 |
|
|
static int inf_scan_ident (sstring *, int);
|
218 |
|
|
static int check_protection (int *, int *);
|
219 |
|
|
static void cb_file_change (cpp_reader *, const struct line_map *);
|
220 |
|
|
|
221 |
|
|
static void
|
222 |
|
|
add_symbols (symbol_flags flags, namelist names)
|
223 |
|
|
{
|
224 |
|
|
symbol_table[cur_symbol_table_size].flags = flags;
|
225 |
|
|
symbol_table[cur_symbol_table_size].names = names;
|
226 |
|
|
cur_symbol_table_size++;
|
227 |
|
|
if (cur_symbol_table_size >= SYMBOL_TABLE_SIZE)
|
228 |
|
|
fatal ("too many calls to add_symbols");
|
229 |
|
|
symbol_table[cur_symbol_table_size].names = NULL; /* Termination. */
|
230 |
|
|
}
|
231 |
|
|
|
232 |
|
|
struct std_include_entry {
|
233 |
|
|
const char *const name;
|
234 |
|
|
const symbol_flags flags;
|
235 |
|
|
const namelist names;
|
236 |
|
|
};
|
237 |
|
|
|
238 |
|
|
const char NONE[] = ""; /* The empty namelist. */
|
239 |
|
|
|
240 |
|
|
/* Special name to indicate a continuation line in std_include_table. */
|
241 |
|
|
const char CONTINUED[] = "";
|
242 |
|
|
|
243 |
|
|
const struct std_include_entry *include_entry;
|
244 |
|
|
|
245 |
|
|
const struct std_include_entry std_include_table [] = {
|
246 |
|
|
{ "ctype.h", ANSI_SYMBOL,
|
247 |
|
|
"isalnum\0isalpha\0iscntrl\0isdigit\0isgraph\0islower\0\
|
248 |
|
|
isprint\0ispunct\0isspace\0isupper\0isxdigit\0tolower\0toupper\0" },
|
249 |
|
|
|
250 |
|
|
{ "dirent.h", POSIX1_SYMBOL, "closedir\0opendir\0readdir\0rewinddir\0"},
|
251 |
|
|
|
252 |
|
|
{ "errno.h", ANSI_SYMBOL|MACRO_SYMBOL, "errno\0" },
|
253 |
|
|
|
254 |
|
|
/* ANSI_SYMBOL is wrong, but ... */
|
255 |
|
|
{ "curses.h", ANSI_SYMBOL, "box\0delwin\0endwin\0getcurx\0getcury\0initscr\0\
|
256 |
|
|
mvcur\0mvwprintw\0mvwscanw\0newwin\0overlay\0overwrite\0\
|
257 |
|
|
scroll\0subwin\0touchwin\0waddstr\0wclear\0wclrtobot\0wclrtoeol\0\
|
258 |
|
|
waddch\0wdelch\0wdeleteln\0werase\0wgetch\0wgetstr\0winsch\0winsertln\0\
|
259 |
|
|
wmove\0wprintw\0wrefresh\0wscanw\0wstandend\0wstandout\0" },
|
260 |
|
|
|
261 |
|
|
{ "fcntl.h", POSIX1_SYMBOL, "creat\0fcntl\0open\0" },
|
262 |
|
|
|
263 |
|
|
/* Maybe also "getgrent fgetgrent setgrent endgrent" */
|
264 |
|
|
{ "grp.h", POSIX1_SYMBOL, "getgrgid\0getgrnam\0" },
|
265 |
|
|
|
266 |
|
|
/*{ "limit.h", ... provided by gcc }, */
|
267 |
|
|
|
268 |
|
|
{ "locale.h", ANSI_SYMBOL, "localeconv\0setlocale\0" },
|
269 |
|
|
|
270 |
|
|
{ "math.h", ANSI_SYMBOL,
|
271 |
|
|
"acos\0asin\0atan\0atan2\0ceil\0cos\0cosh\0exp\0\
|
272 |
|
|
fabs\0floor\0fmod\0frexp\0ldexp\0log10\0log\0modf\0pow\0sin\0sinh\0sqrt\0\
|
273 |
|
|
tan\0tanh\0" },
|
274 |
|
|
|
275 |
|
|
{ CONTINUED, ANSI_SYMBOL|MACRO_SYMBOL, "HUGE_VAL\0" },
|
276 |
|
|
|
277 |
|
|
{ "pwd.h", POSIX1_SYMBOL, "getpwnam\0getpwuid\0" },
|
278 |
|
|
|
279 |
|
|
/* Left out siglongjmp sigsetjmp - these depend on sigjmp_buf. */
|
280 |
|
|
{ "setjmp.h", ANSI_SYMBOL, "longjmp\0setjmp\0" },
|
281 |
|
|
|
282 |
|
|
/* Left out signal() - its prototype is too complex for us!
|
283 |
|
|
Also left out "sigaction sigaddset sigdelset sigemptyset
|
284 |
|
|
sigfillset sigismember sigpending sigprocmask sigsuspend"
|
285 |
|
|
because these need sigset_t or struct sigaction.
|
286 |
|
|
Most systems that provide them will also declare them. */
|
287 |
|
|
{ "signal.h", ANSI_SYMBOL, "raise\0" },
|
288 |
|
|
{ CONTINUED, POSIX1_SYMBOL, "kill\0" },
|
289 |
|
|
|
290 |
|
|
{ "stdio.h", ANSI_SYMBOL,
|
291 |
|
|
"clearerr\0fclose\0feof\0ferror\0fflush\0fgetc\0fgetpos\0\
|
292 |
|
|
fgets\0fopen\0fprintf\0fputc\0fputs\0fread\0freopen\0fscanf\0fseek\0\
|
293 |
|
|
fsetpos\0ftell\0fwrite\0getc\0getchar\0gets\0perror\0\
|
294 |
|
|
printf\0putc\0putchar\0puts\0remove\0rename\0rewind\0scanf\0setbuf\0\
|
295 |
|
|
setvbuf\0sprintf\0sscanf\0vprintf\0vsprintf\0vfprintf\0tmpfile\0\
|
296 |
|
|
tmpnam\0ungetc\0" },
|
297 |
|
|
{ CONTINUED, POSIX1_SYMBOL, "fdopen\0fileno\0" },
|
298 |
|
|
{ CONTINUED, POSIX2_SYMBOL, "pclose\0popen\0" }, /* I think ... */
|
299 |
|
|
/* Should perhaps also handle NULL, EOF, ... ? */
|
300 |
|
|
|
301 |
|
|
/* "div ldiv", - ignored because these depend on div_t, ldiv_t
|
302 |
|
|
ignore these: "mblen mbstowcs mbstowc wcstombs wctomb"
|
303 |
|
|
Left out getgroups, because SunOS4 has incompatible BSD and SVR4 versions.
|
304 |
|
|
Should perhaps also add NULL */
|
305 |
|
|
{ "stdlib.h", ANSI_SYMBOL,
|
306 |
|
|
"abort\0abs\0atexit\0atof\0atoi\0atol\0bsearch\0calloc\0\
|
307 |
|
|
exit\0free\0getenv\0labs\0malloc\0qsort\0rand\0realloc\0\
|
308 |
|
|
srand\0strtod\0strtol\0strtoul\0system\0" },
|
309 |
|
|
{ CONTINUED, ANSI_SYMBOL|MACRO_SYMBOL, "EXIT_FAILURE\0EXIT_SUCCESS\0" },
|
310 |
|
|
{ CONTINUED, POSIX1_SYMBOL, "putenv\0" },
|
311 |
|
|
|
312 |
|
|
{ "string.h", ANSI_SYMBOL, "memchr\0memcmp\0memcpy\0memmove\0memset\0\
|
313 |
|
|
strcat\0strchr\0strcmp\0strcoll\0strcpy\0strcspn\0strerror\0\
|
314 |
|
|
strlen\0strncat\0strncmp\0strncpy\0strpbrk\0strrchr\0strspn\0strstr\0\
|
315 |
|
|
strtok\0strxfrm\0" },
|
316 |
|
|
/* Should perhaps also add NULL and size_t */
|
317 |
|
|
|
318 |
|
|
{ "strings.h", XOPEN_EXTENDED_SYMBOL,
|
319 |
|
|
"bcmp\0bcopy\0bzero\0ffs\0index\0rindex\0strcasecmp\0strncasecmp\0" },
|
320 |
|
|
|
321 |
|
|
{ "strops.h", XOPEN_EXTENDED_SYMBOL, "ioctl\0" },
|
322 |
|
|
|
323 |
|
|
/* Actually, XPG4 does not seem to have <sys/ioctl.h>, but defines
|
324 |
|
|
ioctl in <strops.h>. However, many systems have it is sys/ioctl.h,
|
325 |
|
|
and many systems do have <sys/ioctl.h> but not <strops.h>. */
|
326 |
|
|
{ "sys/ioctl.h", XOPEN_EXTENDED_SYMBOL, "ioctl\0" },
|
327 |
|
|
|
328 |
|
|
{ "sys/socket.h", XOPEN_EXTENDED_SYMBOL, "socket\0" },
|
329 |
|
|
|
330 |
|
|
{ "sys/stat.h", POSIX1_SYMBOL,
|
331 |
|
|
"chmod\0fstat\0mkdir\0mkfifo\0stat\0lstat\0umask\0" },
|
332 |
|
|
{ CONTINUED, POSIX1_SYMBOL|MACRO_SYMBOL,
|
333 |
|
|
"S_ISDIR\0S_ISBLK\0S_ISCHR\0S_ISFIFO\0S_ISREG\0S_ISLNK\0S_IFDIR\0\
|
334 |
|
|
S_IFBLK\0S_IFCHR\0S_IFIFO\0S_IFREG\0S_IFLNK\0" },
|
335 |
|
|
{ CONTINUED, XOPEN_EXTENDED_SYMBOL, "fchmod\0" },
|
336 |
|
|
|
337 |
|
|
#if 0
|
338 |
|
|
/* How do we handle fd_set? */
|
339 |
|
|
{ "sys/time.h", XOPEN_EXTENDED_SYMBOL, "select\0" },
|
340 |
|
|
{ "sys/select.h", XOPEN_EXTENDED_SYMBOL /* fake */, "select\0" },
|
341 |
|
|
#endif
|
342 |
|
|
|
343 |
|
|
{ "sys/times.h", POSIX1_SYMBOL, "times\0" },
|
344 |
|
|
/* "sys/types.h" add types (not in old g++-include) */
|
345 |
|
|
|
346 |
|
|
{ "sys/utsname.h", POSIX1_SYMBOL, "uname\0" },
|
347 |
|
|
|
348 |
|
|
{ "sys/wait.h", POSIX1_SYMBOL, "wait\0waitpid\0" },
|
349 |
|
|
{ CONTINUED, POSIX1_SYMBOL|MACRO_SYMBOL,
|
350 |
|
|
"WEXITSTATUS\0WIFEXITED\0WIFSIGNALED\0WIFSTOPPED\0WSTOPSIG\0\
|
351 |
|
|
WTERMSIG\0WNOHANG\0WNOTRACED\0" },
|
352 |
|
|
|
353 |
|
|
{ "tar.h", POSIX1_SYMBOL, NONE },
|
354 |
|
|
|
355 |
|
|
{ "termios.h", POSIX1_SYMBOL,
|
356 |
|
|
"cfgetispeed\0cfgetospeed\0cfsetispeed\0cfsetospeed\0tcdrain\0tcflow\0tcflush\0tcgetattr\0tcsendbreak\0tcsetattr\0" },
|
357 |
|
|
|
358 |
|
|
{ "time.h", ANSI_SYMBOL,
|
359 |
|
|
"asctime\0clock\0ctime\0difftime\0gmtime\0localtime\0mktime\0strftime\0time\0" },
|
360 |
|
|
{ CONTINUED, POSIX1_SYMBOL, "tzset\0" },
|
361 |
|
|
|
362 |
|
|
{ "unistd.h", POSIX1_SYMBOL,
|
363 |
|
|
"_exit\0access\0alarm\0chdir\0chown\0close\0ctermid\0cuserid\0\
|
364 |
|
|
dup\0dup2\0execl\0execle\0execlp\0execv\0execve\0execvp\0fork\0fpathconf\0\
|
365 |
|
|
getcwd\0getegid\0geteuid\0getgid\0getlogin\0getpgrp\0getpid\0\
|
366 |
|
|
getppid\0getuid\0isatty\0link\0lseek\0pathconf\0pause\0pipe\0read\0rmdir\0\
|
367 |
|
|
setgid\0setpgid\0setsid\0setuid\0sleep\0sysconf\0tcgetpgrp\0tcsetpgrp\0\
|
368 |
|
|
ttyname\0unlink\0write\0" },
|
369 |
|
|
{ CONTINUED, POSIX2_SYMBOL, "getopt\0" },
|
370 |
|
|
{ CONTINUED, XOPEN_EXTENDED_SYMBOL,
|
371 |
|
|
"lockf\0gethostid\0gethostname\0readlink\0symlink\0" },
|
372 |
|
|
|
373 |
|
|
{ "utime.h", POSIX1_SYMBOL, "utime\0" },
|
374 |
|
|
|
375 |
|
|
{ NULL, 0, NONE }
|
376 |
|
|
};
|
377 |
|
|
|
378 |
|
|
enum special_file special_file_handling = no_special;
|
379 |
|
|
|
380 |
|
|
/* They are set if the corresponding macro has been seen. */
|
381 |
|
|
/* The following are only used when handling sys/stat.h */
|
382 |
|
|
int seen_S_IFBLK = 0, seen_S_ISBLK = 0;
|
383 |
|
|
int seen_S_IFCHR = 0, seen_S_ISCHR = 0;
|
384 |
|
|
int seen_S_IFDIR = 0, seen_S_ISDIR = 0;
|
385 |
|
|
int seen_S_IFIFO = 0, seen_S_ISFIFO = 0;
|
386 |
|
|
int seen_S_IFLNK = 0, seen_S_ISLNK = 0;
|
387 |
|
|
int seen_S_IFREG = 0, seen_S_ISREG = 0;
|
388 |
|
|
/* The following are only used when handling errno.h */
|
389 |
|
|
int seen_errno = 0;
|
390 |
|
|
/* The following are only used when handling stdlib.h */
|
391 |
|
|
int seen_EXIT_FAILURE = 0, seen_EXIT_SUCCESS = 0;
|
392 |
|
|
|
393 |
|
|
struct obstack scan_file_obstack;
|
394 |
|
|
|
395 |
|
|
/* NOTE: If you edit this, also edit gen-protos.c !! */
|
396 |
|
|
|
397 |
|
|
static struct fn_decl *
|
398 |
|
|
lookup_std_proto (const char *name, int name_length)
|
399 |
|
|
{
|
400 |
|
|
int i = hashstr (name, name_length) % HASH_SIZE;
|
401 |
|
|
int i0 = i;
|
402 |
|
|
for (;;)
|
403 |
|
|
{
|
404 |
|
|
struct fn_decl *fn;
|
405 |
|
|
if (hash_tab[i] == 0)
|
406 |
|
|
return NULL;
|
407 |
|
|
fn = &std_protos[hash_tab[i]];
|
408 |
|
|
if ((int) strlen (fn->fname) == name_length
|
409 |
|
|
&& strncmp (fn->fname, name, name_length) == 0)
|
410 |
|
|
return fn;
|
411 |
|
|
i = (i+1) % HASH_SIZE;
|
412 |
|
|
gcc_assert (i != i0);
|
413 |
|
|
}
|
414 |
|
|
}
|
415 |
|
|
|
416 |
|
|
char *inc_filename;
|
417 |
|
|
int inc_filename_length;
|
418 |
|
|
FILE *outf;
|
419 |
|
|
sstring line;
|
420 |
|
|
|
421 |
|
|
int lbrac_line, rbrac_line;
|
422 |
|
|
|
423 |
|
|
int required_unseen_count = 0;
|
424 |
|
|
int required_other = 0;
|
425 |
|
|
|
426 |
|
|
static void
|
427 |
|
|
write_lbrac (void)
|
428 |
|
|
{
|
429 |
|
|
if (partial_count)
|
430 |
|
|
{
|
431 |
|
|
fprintf (outf, "#ifndef _PARAMS\n");
|
432 |
|
|
fprintf (outf, "#if defined(__STDC__) || defined(__cplusplus)\n");
|
433 |
|
|
fprintf (outf, "#define _PARAMS(ARGS) ARGS\n");
|
434 |
|
|
fprintf (outf, "#else\n");
|
435 |
|
|
fprintf (outf, "#define _PARAMS(ARGS) ()\n");
|
436 |
|
|
fprintf (outf, "#endif\n#endif /* _PARAMS */\n");
|
437 |
|
|
}
|
438 |
|
|
}
|
439 |
|
|
|
440 |
|
|
struct partial_proto
|
441 |
|
|
{
|
442 |
|
|
struct partial_proto *next;
|
443 |
|
|
struct fn_decl *fn;
|
444 |
|
|
int line_seen;
|
445 |
|
|
};
|
446 |
|
|
|
447 |
|
|
struct partial_proto *partial_proto_list = NULL;
|
448 |
|
|
|
449 |
|
|
struct partial_proto required_dummy_proto, seen_dummy_proto;
|
450 |
|
|
#define REQUIRED(FN) ((FN)->partial == &required_dummy_proto)
|
451 |
|
|
#define SET_REQUIRED(FN) ((FN)->partial = &required_dummy_proto)
|
452 |
|
|
#define SET_SEEN(FN) ((FN)->partial = &seen_dummy_proto)
|
453 |
|
|
#define SEEN(FN) ((FN)->partial == &seen_dummy_proto)
|
454 |
|
|
|
455 |
|
|
static void
|
456 |
|
|
recognized_macro (const char *fname)
|
457 |
|
|
{
|
458 |
|
|
/* The original include file defines fname as a macro. */
|
459 |
|
|
struct fn_decl *fn = lookup_std_proto (fname, strlen (fname));
|
460 |
|
|
|
461 |
|
|
/* Since fname is a macro, don't require a prototype for it. */
|
462 |
|
|
if (fn)
|
463 |
|
|
{
|
464 |
|
|
if (REQUIRED (fn))
|
465 |
|
|
required_unseen_count--;
|
466 |
|
|
SET_SEEN (fn);
|
467 |
|
|
}
|
468 |
|
|
|
469 |
|
|
switch (special_file_handling)
|
470 |
|
|
{
|
471 |
|
|
case errno_h:
|
472 |
|
|
if (strcmp (fname, "errno") == 0 && !seen_errno)
|
473 |
|
|
seen_errno = 1, required_other--;
|
474 |
|
|
break;
|
475 |
|
|
case stdlib_h:
|
476 |
|
|
if (strcmp (fname, "EXIT_FAILURE") == 0 && !seen_EXIT_FAILURE)
|
477 |
|
|
seen_EXIT_FAILURE = 1, required_other--;
|
478 |
|
|
if (strcmp (fname, "EXIT_SUCCESS") == 0 && !seen_EXIT_SUCCESS)
|
479 |
|
|
seen_EXIT_SUCCESS = 1, required_other--;
|
480 |
|
|
break;
|
481 |
|
|
case sys_stat_h:
|
482 |
|
|
if (fname[0] == 'S' && fname[1] == '_')
|
483 |
|
|
{
|
484 |
|
|
if (strcmp (fname, "S_IFBLK") == 0) seen_S_IFBLK++;
|
485 |
|
|
else if (strcmp (fname, "S_ISBLK") == 0) seen_S_ISBLK++;
|
486 |
|
|
else if (strcmp (fname, "S_IFCHR") == 0) seen_S_IFCHR++;
|
487 |
|
|
else if (strcmp (fname, "S_ISCHR") == 0) seen_S_ISCHR++;
|
488 |
|
|
else if (strcmp (fname, "S_IFDIR") == 0) seen_S_IFDIR++;
|
489 |
|
|
else if (strcmp (fname, "S_ISDIR") == 0) seen_S_ISDIR++;
|
490 |
|
|
else if (strcmp (fname, "S_IFIFO") == 0) seen_S_IFIFO++;
|
491 |
|
|
else if (strcmp (fname, "S_ISFIFO") == 0) seen_S_ISFIFO++;
|
492 |
|
|
else if (strcmp (fname, "S_IFLNK") == 0) seen_S_IFLNK++;
|
493 |
|
|
else if (strcmp (fname, "S_ISLNK") == 0) seen_S_ISLNK++;
|
494 |
|
|
else if (strcmp (fname, "S_IFREG") == 0) seen_S_IFREG++;
|
495 |
|
|
else if (strcmp (fname, "S_ISREG") == 0) seen_S_ISREG++;
|
496 |
|
|
}
|
497 |
|
|
break;
|
498 |
|
|
|
499 |
|
|
default:
|
500 |
|
|
break;
|
501 |
|
|
}
|
502 |
|
|
}
|
503 |
|
|
|
504 |
|
|
void
|
505 |
|
|
recognized_extern (const cpp_token *name)
|
506 |
|
|
{
|
507 |
|
|
switch (special_file_handling)
|
508 |
|
|
{
|
509 |
|
|
case errno_h:
|
510 |
|
|
if (cpp_ideq (name, "errno"))
|
511 |
|
|
seen_errno = 1, required_other--;
|
512 |
|
|
break;
|
513 |
|
|
|
514 |
|
|
default:
|
515 |
|
|
break;
|
516 |
|
|
}
|
517 |
|
|
}
|
518 |
|
|
|
519 |
|
|
/* Called by scan_decls if it saw a function definition for a function
|
520 |
|
|
named FNAME. KIND is 'I' for an inline function; 'F' if a normal
|
521 |
|
|
function declaration preceded by 'extern "C"' (or nested inside
|
522 |
|
|
'extern "C"' braces); or 'f' for other function declarations. */
|
523 |
|
|
|
524 |
|
|
void
|
525 |
|
|
recognized_function (const cpp_token *fname, unsigned int line, int kind,
|
526 |
|
|
int have_arg_list)
|
527 |
|
|
{
|
528 |
|
|
struct partial_proto *partial;
|
529 |
|
|
int i;
|
530 |
|
|
struct fn_decl *fn;
|
531 |
|
|
|
532 |
|
|
fn = lookup_std_proto ((const char *) NODE_NAME (fname->val.node),
|
533 |
|
|
NODE_LEN (fname->val.node));
|
534 |
|
|
|
535 |
|
|
/* Remove the function from the list of required function. */
|
536 |
|
|
if (fn)
|
537 |
|
|
{
|
538 |
|
|
if (REQUIRED (fn))
|
539 |
|
|
required_unseen_count--;
|
540 |
|
|
SET_SEEN (fn);
|
541 |
|
|
}
|
542 |
|
|
|
543 |
|
|
/* If we have a full prototype, we're done. */
|
544 |
|
|
if (have_arg_list)
|
545 |
|
|
return;
|
546 |
|
|
|
547 |
|
|
if (kind == 'I') /* don't edit inline function */
|
548 |
|
|
return;
|
549 |
|
|
|
550 |
|
|
/* If the partial prototype was included from some other file,
|
551 |
|
|
we don't need to patch it up (in this run). */
|
552 |
|
|
i = strlen (cur_file);
|
553 |
|
|
if (i < inc_filename_length
|
554 |
|
|
|| strcmp (inc_filename, cur_file + (i - inc_filename_length)) != 0)
|
555 |
|
|
return;
|
556 |
|
|
|
557 |
|
|
if (fn == NULL)
|
558 |
|
|
return;
|
559 |
|
|
if (fn->params[0] == '\0')
|
560 |
|
|
return;
|
561 |
|
|
|
562 |
|
|
/* We only have a partial function declaration,
|
563 |
|
|
so remember that we have to add a complete prototype. */
|
564 |
|
|
partial_count++;
|
565 |
|
|
partial = obstack_alloc (&scan_file_obstack, sizeof (struct partial_proto));
|
566 |
|
|
partial->line_seen = line;
|
567 |
|
|
partial->fn = fn;
|
568 |
|
|
fn->partial = partial;
|
569 |
|
|
partial->next = partial_proto_list;
|
570 |
|
|
partial_proto_list = partial;
|
571 |
|
|
if (verbose)
|
572 |
|
|
{
|
573 |
|
|
fprintf (stderr, "(%s: %s non-prototype function declaration.)\n",
|
574 |
|
|
inc_filename, fn->fname);
|
575 |
|
|
}
|
576 |
|
|
}
|
577 |
|
|
|
578 |
|
|
/* For any name in NAMES that is defined as a macro,
|
579 |
|
|
call recognized_macro on it. */
|
580 |
|
|
|
581 |
|
|
static void
|
582 |
|
|
check_macro_names (cpp_reader *pfile, namelist names)
|
583 |
|
|
{
|
584 |
|
|
size_t len;
|
585 |
|
|
while (*names)
|
586 |
|
|
{
|
587 |
|
|
len = strlen (names);
|
588 |
|
|
if (cpp_defined (pfile, (const unsigned char *)names, len))
|
589 |
|
|
recognized_macro (names);
|
590 |
|
|
names += len + 1;
|
591 |
|
|
}
|
592 |
|
|
}
|
593 |
|
|
|
594 |
|
|
static void
|
595 |
|
|
cb_file_change (cpp_reader *pfile ATTRIBUTE_UNUSED,
|
596 |
|
|
const struct line_map *map)
|
597 |
|
|
{
|
598 |
|
|
/* Just keep track of current file name. */
|
599 |
|
|
cur_file = map == NULL ? NULL : map->to_file;
|
600 |
|
|
}
|
601 |
|
|
|
602 |
|
|
static void
|
603 |
|
|
read_scan_file (char *in_fname, int argc, char **argv)
|
604 |
|
|
{
|
605 |
|
|
cpp_reader *scan_in;
|
606 |
|
|
cpp_callbacks *cb;
|
607 |
|
|
cpp_options *options;
|
608 |
|
|
struct fn_decl *fn;
|
609 |
|
|
int i, strings_processed;
|
610 |
|
|
struct symbol_list *cur_symbols;
|
611 |
|
|
|
612 |
|
|
obstack_init (&scan_file_obstack);
|
613 |
|
|
|
614 |
|
|
linemap_init (&line_table);
|
615 |
|
|
scan_in = cpp_create_reader (CLK_GNUC89, NULL, &line_table);
|
616 |
|
|
cb = cpp_get_callbacks (scan_in);
|
617 |
|
|
cb->file_change = cb_file_change;
|
618 |
|
|
|
619 |
|
|
/* We are going to be scanning a header file out of its proper context,
|
620 |
|
|
so ignore warnings and errors. */
|
621 |
|
|
options = cpp_get_options (scan_in);
|
622 |
|
|
options->inhibit_warnings = 1;
|
623 |
|
|
options->inhibit_errors = 1;
|
624 |
|
|
cpp_post_options (scan_in);
|
625 |
|
|
|
626 |
|
|
if (!cpp_read_main_file (scan_in, in_fname))
|
627 |
|
|
exit (FATAL_EXIT_CODE);
|
628 |
|
|
|
629 |
|
|
cpp_change_file (scan_in, LC_RENAME, "<built-in>");
|
630 |
|
|
cpp_init_builtins (scan_in, true);
|
631 |
|
|
cpp_change_file (scan_in, LC_RENAME, in_fname);
|
632 |
|
|
|
633 |
|
|
/* Process switches after builtins so -D can override them. */
|
634 |
|
|
for (i = 0; i < argc; i += strings_processed)
|
635 |
|
|
{
|
636 |
|
|
strings_processed = 0;
|
637 |
|
|
if (argv[i][0] == '-')
|
638 |
|
|
{
|
639 |
|
|
if (argv[i][1] == 'I')
|
640 |
|
|
{
|
641 |
|
|
if (argv[i][2] != '\0')
|
642 |
|
|
{
|
643 |
|
|
strings_processed = 1;
|
644 |
|
|
add_path (xstrdup (argv[i] + 2), BRACKET, false, false);
|
645 |
|
|
}
|
646 |
|
|
else if (i + 1 != argc)
|
647 |
|
|
{
|
648 |
|
|
strings_processed = 2;
|
649 |
|
|
add_path (xstrdup (argv[i + 1]), BRACKET, false, false);
|
650 |
|
|
}
|
651 |
|
|
}
|
652 |
|
|
else if (argv[i][1] == 'D')
|
653 |
|
|
{
|
654 |
|
|
if (argv[i][2] != '\0')
|
655 |
|
|
strings_processed = 1, cpp_define (scan_in, argv[i] + 2);
|
656 |
|
|
else if (i + 1 != argc)
|
657 |
|
|
strings_processed = 2, cpp_define (scan_in, argv[i + 1]);
|
658 |
|
|
}
|
659 |
|
|
}
|
660 |
|
|
|
661 |
|
|
if (strings_processed == 0)
|
662 |
|
|
break;
|
663 |
|
|
}
|
664 |
|
|
|
665 |
|
|
if (i < argc)
|
666 |
|
|
cpp_error (scan_in, CPP_DL_ERROR, "invalid option `%s'", argv[i]);
|
667 |
|
|
if (cpp_errors (scan_in))
|
668 |
|
|
exit (FATAL_EXIT_CODE);
|
669 |
|
|
|
670 |
|
|
register_include_chains (scan_in, NULL /* sysroot */, NULL /* iprefix */,
|
671 |
|
|
NULL /* imultilib */, true /* stdinc */,
|
672 |
|
|
false /* cxx_stdinc */, false /* verbose */);
|
673 |
|
|
|
674 |
|
|
/* We are scanning a system header, so mark it as such. */
|
675 |
|
|
cpp_make_system_header (scan_in, 1, 0);
|
676 |
|
|
|
677 |
|
|
scan_decls (scan_in, argc, argv);
|
678 |
|
|
for (cur_symbols = &symbol_table[0]; cur_symbols->names; cur_symbols++)
|
679 |
|
|
check_macro_names (scan_in, cur_symbols->names);
|
680 |
|
|
|
681 |
|
|
/* Traditionally, getc and putc are defined in terms of _filbuf and _flsbuf.
|
682 |
|
|
If so, those functions are also required. */
|
683 |
|
|
if (special_file_handling == stdio_h
|
684 |
|
|
&& (fn = lookup_std_proto ("_filbuf", 7)) != NULL)
|
685 |
|
|
{
|
686 |
|
|
unsigned char getchar_call[] = "getchar();\n";
|
687 |
|
|
int seen_filbuf = 0;
|
688 |
|
|
|
689 |
|
|
/* Scan the macro expansion of "getchar();". */
|
690 |
|
|
cpp_push_buffer (scan_in, getchar_call, sizeof(getchar_call) - 1,
|
691 |
|
|
/* from_stage3 */ true);
|
692 |
|
|
for (;;)
|
693 |
|
|
{
|
694 |
|
|
const cpp_token *t = cpp_get_token (scan_in);
|
695 |
|
|
|
696 |
|
|
if (t->type == CPP_EOF)
|
697 |
|
|
break;
|
698 |
|
|
else if (cpp_ideq (t, "_filbuf"))
|
699 |
|
|
seen_filbuf++;
|
700 |
|
|
}
|
701 |
|
|
|
702 |
|
|
if (seen_filbuf)
|
703 |
|
|
{
|
704 |
|
|
int need_filbuf = !SEEN (fn) && !REQUIRED (fn);
|
705 |
|
|
struct fn_decl *flsbuf_fn = lookup_std_proto ("_flsbuf", 7);
|
706 |
|
|
int need_flsbuf
|
707 |
|
|
= flsbuf_fn && !SEEN (flsbuf_fn) && !REQUIRED (flsbuf_fn);
|
708 |
|
|
|
709 |
|
|
/* Append "_filbuf" and/or "_flsbuf" to the required functions. */
|
710 |
|
|
if (need_filbuf + need_flsbuf)
|
711 |
|
|
{
|
712 |
|
|
const char *new_list;
|
713 |
|
|
if (need_filbuf)
|
714 |
|
|
SET_REQUIRED (fn);
|
715 |
|
|
if (need_flsbuf)
|
716 |
|
|
SET_REQUIRED (flsbuf_fn);
|
717 |
|
|
if (need_flsbuf && need_filbuf)
|
718 |
|
|
new_list = "_filbuf\0_flsbuf\0";
|
719 |
|
|
else if (need_flsbuf)
|
720 |
|
|
new_list = "_flsbuf\0";
|
721 |
|
|
else /* if (need_flsbuf) */
|
722 |
|
|
new_list = "_filbuf\0";
|
723 |
|
|
add_symbols (ANSI_SYMBOL, new_list);
|
724 |
|
|
required_unseen_count += need_filbuf + need_flsbuf;
|
725 |
|
|
}
|
726 |
|
|
}
|
727 |
|
|
}
|
728 |
|
|
|
729 |
|
|
if (required_unseen_count + partial_count + required_other == 0)
|
730 |
|
|
{
|
731 |
|
|
if (verbose)
|
732 |
|
|
fprintf (stderr, "%s: OK, nothing needs to be done.\n", inc_filename);
|
733 |
|
|
exit (SUCCESS_EXIT_CODE);
|
734 |
|
|
}
|
735 |
|
|
if (!verbose)
|
736 |
|
|
fprintf (stderr, "%s: fixing %s\n", progname, inc_filename);
|
737 |
|
|
else
|
738 |
|
|
{
|
739 |
|
|
if (required_unseen_count)
|
740 |
|
|
fprintf (stderr, "%s: %d missing function declarations.\n",
|
741 |
|
|
inc_filename, required_unseen_count);
|
742 |
|
|
if (partial_count)
|
743 |
|
|
fprintf (stderr, "%s: %d non-prototype function declarations.\n",
|
744 |
|
|
inc_filename, partial_count);
|
745 |
|
|
}
|
746 |
|
|
}
|
747 |
|
|
|
748 |
|
|
static void
|
749 |
|
|
write_rbrac (void)
|
750 |
|
|
{
|
751 |
|
|
struct fn_decl *fn;
|
752 |
|
|
const char *cptr;
|
753 |
|
|
struct symbol_list *cur_symbols;
|
754 |
|
|
|
755 |
|
|
if (required_unseen_count)
|
756 |
|
|
{
|
757 |
|
|
#ifdef NO_IMPLICIT_EXTERN_C
|
758 |
|
|
fprintf (outf, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
|
759 |
|
|
#endif
|
760 |
|
|
}
|
761 |
|
|
|
762 |
|
|
/* Now we print out prototypes for those functions that we haven't seen. */
|
763 |
|
|
for (cur_symbols = &symbol_table[0]; cur_symbols->names; cur_symbols++)
|
764 |
|
|
{
|
765 |
|
|
int if_was_emitted = 0;
|
766 |
|
|
int name_len;
|
767 |
|
|
cptr = cur_symbols->names;
|
768 |
|
|
for ( ; (name_len = strlen (cptr)) != 0; cptr+= name_len + 1)
|
769 |
|
|
{
|
770 |
|
|
int macro_protect = 0;
|
771 |
|
|
|
772 |
|
|
if (cur_symbols->flags & MACRO_SYMBOL)
|
773 |
|
|
continue;
|
774 |
|
|
|
775 |
|
|
fn = lookup_std_proto (cptr, name_len);
|
776 |
|
|
if (fn == NULL || !REQUIRED (fn))
|
777 |
|
|
continue;
|
778 |
|
|
|
779 |
|
|
if (!if_was_emitted)
|
780 |
|
|
{
|
781 |
|
|
/* what about curses. ??? or _flsbuf/_filbuf ??? */
|
782 |
|
|
if (cur_symbols->flags & ANSI_SYMBOL)
|
783 |
|
|
fprintf (outf,
|
784 |
|
|
"#if defined(__USE_FIXED_PROTOTYPES__) || defined(__cplusplus) || defined (__STRICT_ANSI__)\n");
|
785 |
|
|
else if (cur_symbols->flags & (POSIX1_SYMBOL|POSIX2_SYMBOL))
|
786 |
|
|
fprintf (outf,
|
787 |
|
|
"#if defined(__USE_FIXED_PROTOTYPES__) || (defined(__cplusplus) \\\n\
|
788 |
|
|
? (!defined(__STRICT_ANSI__) || defined(_POSIX_SOURCE)) \\\n\
|
789 |
|
|
: (defined(__STRICT_ANSI__) && defined(_POSIX_SOURCE)))\n");
|
790 |
|
|
else if (cur_symbols->flags & XOPEN_SYMBOL)
|
791 |
|
|
{
|
792 |
|
|
fprintf (outf,
|
793 |
|
|
"#if defined(__USE_FIXED_PROTOTYPES__) \\\n\
|
794 |
|
|
|| (defined(__STRICT_ANSI__) && defined(_XOPEN_SOURCE))\n");
|
795 |
|
|
}
|
796 |
|
|
else if (cur_symbols->flags & XOPEN_EXTENDED_SYMBOL)
|
797 |
|
|
{
|
798 |
|
|
fprintf (outf,
|
799 |
|
|
"#if defined(__USE_FIXED_PROTOTYPES__) \\\n\
|
800 |
|
|
|| (defined(__STRICT_ANSI__) && defined(_XOPEN_EXTENDED_SOURCE))\n");
|
801 |
|
|
}
|
802 |
|
|
else
|
803 |
|
|
{
|
804 |
|
|
fatal ("internal error for function %s", fn->fname);
|
805 |
|
|
}
|
806 |
|
|
if_was_emitted = 1;
|
807 |
|
|
}
|
808 |
|
|
|
809 |
|
|
/* In the case of memmove, protect in case the application
|
810 |
|
|
defines it as a macro before including the header. */
|
811 |
|
|
if (!strcmp (fn->fname, "memmove")
|
812 |
|
|
|| !strcmp (fn->fname, "putc")
|
813 |
|
|
|| !strcmp (fn->fname, "getc")
|
814 |
|
|
|| !strcmp (fn->fname, "vprintf")
|
815 |
|
|
|| !strcmp (fn->fname, "vfprintf")
|
816 |
|
|
|| !strcmp (fn->fname, "vsprintf")
|
817 |
|
|
|| !strcmp (fn->fname, "rewinddir")
|
818 |
|
|
|| !strcmp (fn->fname, "abort"))
|
819 |
|
|
macro_protect = 1;
|
820 |
|
|
|
821 |
|
|
if (macro_protect)
|
822 |
|
|
fprintf (outf, "#ifndef %s\n", fn->fname);
|
823 |
|
|
fprintf (outf, "extern %s %s (%s);\n",
|
824 |
|
|
fn->rtype, fn->fname, fn->params);
|
825 |
|
|
if (macro_protect)
|
826 |
|
|
fprintf (outf, "#endif\n");
|
827 |
|
|
}
|
828 |
|
|
if (if_was_emitted)
|
829 |
|
|
fprintf (outf,
|
830 |
|
|
"#endif /* defined(__USE_FIXED_PROTOTYPES__) || ... */\n");
|
831 |
|
|
}
|
832 |
|
|
if (required_unseen_count)
|
833 |
|
|
{
|
834 |
|
|
#ifdef NO_IMPLICIT_EXTERN_C
|
835 |
|
|
fprintf (outf, "#ifdef __cplusplus\n}\n#endif\n");
|
836 |
|
|
#endif
|
837 |
|
|
}
|
838 |
|
|
|
839 |
|
|
switch (special_file_handling)
|
840 |
|
|
{
|
841 |
|
|
case errno_h:
|
842 |
|
|
if (!seen_errno)
|
843 |
|
|
fprintf (outf, "extern int errno;\n");
|
844 |
|
|
break;
|
845 |
|
|
case stdlib_h:
|
846 |
|
|
if (!seen_EXIT_FAILURE)
|
847 |
|
|
fprintf (outf, "#define EXIT_FAILURE 1\n");
|
848 |
|
|
if (!seen_EXIT_SUCCESS)
|
849 |
|
|
fprintf (outf, "#define EXIT_SUCCESS 0\n");
|
850 |
|
|
break;
|
851 |
|
|
case sys_stat_h:
|
852 |
|
|
if (!seen_S_ISBLK && seen_S_IFBLK)
|
853 |
|
|
fprintf (outf,
|
854 |
|
|
"#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)\n");
|
855 |
|
|
if (!seen_S_ISCHR && seen_S_IFCHR)
|
856 |
|
|
fprintf (outf,
|
857 |
|
|
"#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)\n");
|
858 |
|
|
if (!seen_S_ISDIR && seen_S_IFDIR)
|
859 |
|
|
fprintf (outf,
|
860 |
|
|
"#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)\n");
|
861 |
|
|
if (!seen_S_ISFIFO && seen_S_IFIFO)
|
862 |
|
|
fprintf (outf,
|
863 |
|
|
"#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)\n");
|
864 |
|
|
if (!seen_S_ISLNK && seen_S_IFLNK)
|
865 |
|
|
fprintf (outf,
|
866 |
|
|
"#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)\n");
|
867 |
|
|
if (!seen_S_ISREG && seen_S_IFREG)
|
868 |
|
|
fprintf (outf,
|
869 |
|
|
"#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)\n");
|
870 |
|
|
break;
|
871 |
|
|
|
872 |
|
|
default:
|
873 |
|
|
break;
|
874 |
|
|
}
|
875 |
|
|
|
876 |
|
|
}
|
877 |
|
|
|
878 |
|
|
/* Returns 1 iff the file is properly protected from multiple inclusion:
|
879 |
|
|
#ifndef PROTECT_NAME
|
880 |
|
|
#define PROTECT_NAME
|
881 |
|
|
#endif
|
882 |
|
|
|
883 |
|
|
*/
|
884 |
|
|
|
885 |
|
|
#define INF_GET() (inf_ptr < inf_limit ? *(unsigned char *) inf_ptr++ : EOF)
|
886 |
|
|
#define INF_UNGET(c) ((c)!=EOF && inf_ptr--)
|
887 |
|
|
|
888 |
|
|
static int
|
889 |
|
|
inf_skip_spaces (int c)
|
890 |
|
|
{
|
891 |
|
|
for (;;)
|
892 |
|
|
{
|
893 |
|
|
if (c == ' ' || c == '\t')
|
894 |
|
|
c = INF_GET ();
|
895 |
|
|
else if (c == '/')
|
896 |
|
|
{
|
897 |
|
|
c = INF_GET ();
|
898 |
|
|
if (c != '*')
|
899 |
|
|
{
|
900 |
|
|
(void) INF_UNGET (c);
|
901 |
|
|
return '/';
|
902 |
|
|
}
|
903 |
|
|
c = INF_GET ();
|
904 |
|
|
for (;;)
|
905 |
|
|
{
|
906 |
|
|
if (c == EOF)
|
907 |
|
|
return EOF;
|
908 |
|
|
else if (c != '*')
|
909 |
|
|
{
|
910 |
|
|
if (c == '\n')
|
911 |
|
|
source_lineno++, lineno++;
|
912 |
|
|
c = INF_GET ();
|
913 |
|
|
}
|
914 |
|
|
else if ((c = INF_GET ()) == '/')
|
915 |
|
|
return INF_GET ();
|
916 |
|
|
}
|
917 |
|
|
}
|
918 |
|
|
else
|
919 |
|
|
break;
|
920 |
|
|
}
|
921 |
|
|
return c;
|
922 |
|
|
}
|
923 |
|
|
|
924 |
|
|
/* Read into STR from inf_buffer upto DELIM. */
|
925 |
|
|
|
926 |
|
|
static int
|
927 |
|
|
inf_read_upto (sstring *str, int delim)
|
928 |
|
|
{
|
929 |
|
|
int ch;
|
930 |
|
|
for (;;)
|
931 |
|
|
{
|
932 |
|
|
ch = INF_GET ();
|
933 |
|
|
if (ch == EOF || ch == delim)
|
934 |
|
|
break;
|
935 |
|
|
SSTRING_PUT (str, ch);
|
936 |
|
|
}
|
937 |
|
|
MAKE_SSTRING_SPACE (str, 1);
|
938 |
|
|
*str->ptr = 0;
|
939 |
|
|
return ch;
|
940 |
|
|
}
|
941 |
|
|
|
942 |
|
|
static int
|
943 |
|
|
inf_scan_ident (sstring *s, int c)
|
944 |
|
|
{
|
945 |
|
|
s->ptr = s->base;
|
946 |
|
|
if (ISIDST (c))
|
947 |
|
|
{
|
948 |
|
|
for (;;)
|
949 |
|
|
{
|
950 |
|
|
SSTRING_PUT (s, c);
|
951 |
|
|
c = INF_GET ();
|
952 |
|
|
if (c == EOF || !(ISIDNUM (c)))
|
953 |
|
|
break;
|
954 |
|
|
}
|
955 |
|
|
}
|
956 |
|
|
MAKE_SSTRING_SPACE (s, 1);
|
957 |
|
|
*s->ptr = 0;
|
958 |
|
|
return c;
|
959 |
|
|
}
|
960 |
|
|
|
961 |
|
|
/* Returns 1 if the file is correctly protected against multiple
|
962 |
|
|
inclusion, setting *ifndef_line to the line number of the initial #ifndef
|
963 |
|
|
and setting *endif_line to the final #endif.
|
964 |
|
|
Otherwise return 0. */
|
965 |
|
|
|
966 |
|
|
static int
|
967 |
|
|
check_protection (int *ifndef_line, int *endif_line)
|
968 |
|
|
{
|
969 |
|
|
int c;
|
970 |
|
|
int if_nesting = 1; /* Level of nesting of #if's */
|
971 |
|
|
char *protect_name = NULL; /* Identifier following initial #ifndef */
|
972 |
|
|
int define_seen = 0;
|
973 |
|
|
|
974 |
|
|
/* Skip initial white space (including comments). */
|
975 |
|
|
for (;; lineno++)
|
976 |
|
|
{
|
977 |
|
|
c = inf_skip_spaces (' ');
|
978 |
|
|
if (c == EOF)
|
979 |
|
|
return 0;
|
980 |
|
|
if (c != '\n')
|
981 |
|
|
break;
|
982 |
|
|
}
|
983 |
|
|
if (c != '#')
|
984 |
|
|
return 0;
|
985 |
|
|
c = inf_scan_ident (&buf, inf_skip_spaces (' '));
|
986 |
|
|
if (SSTRING_LENGTH (&buf) == 0 || strcmp (buf.base, "ifndef") != 0)
|
987 |
|
|
return 0;
|
988 |
|
|
|
989 |
|
|
/* So far so good: We've seen an initial #ifndef. */
|
990 |
|
|
*ifndef_line = lineno;
|
991 |
|
|
c = inf_scan_ident (&buf, inf_skip_spaces (c));
|
992 |
|
|
if (SSTRING_LENGTH (&buf) == 0 || c == EOF)
|
993 |
|
|
return 0;
|
994 |
|
|
protect_name = xstrdup (buf.base);
|
995 |
|
|
|
996 |
|
|
(void) INF_UNGET (c);
|
997 |
|
|
c = inf_read_upto (&buf, '\n');
|
998 |
|
|
if (c == EOF)
|
999 |
|
|
return 0;
|
1000 |
|
|
lineno++;
|
1001 |
|
|
|
1002 |
|
|
for (;;)
|
1003 |
|
|
{
|
1004 |
|
|
c = inf_skip_spaces (' ');
|
1005 |
|
|
if (c == EOF)
|
1006 |
|
|
return 0;
|
1007 |
|
|
if (c == '\n')
|
1008 |
|
|
{
|
1009 |
|
|
lineno++;
|
1010 |
|
|
continue;
|
1011 |
|
|
}
|
1012 |
|
|
if (c != '#')
|
1013 |
|
|
goto skip_to_eol;
|
1014 |
|
|
c = inf_scan_ident (&buf, inf_skip_spaces (' '));
|
1015 |
|
|
if (SSTRING_LENGTH (&buf) == 0)
|
1016 |
|
|
;
|
1017 |
|
|
else if (!strcmp (buf.base, "ifndef")
|
1018 |
|
|
|| !strcmp (buf.base, "ifdef") || !strcmp (buf.base, "if"))
|
1019 |
|
|
{
|
1020 |
|
|
if_nesting++;
|
1021 |
|
|
}
|
1022 |
|
|
else if (!strcmp (buf.base, "endif"))
|
1023 |
|
|
{
|
1024 |
|
|
if_nesting--;
|
1025 |
|
|
if (if_nesting == 0)
|
1026 |
|
|
break;
|
1027 |
|
|
}
|
1028 |
|
|
else if (!strcmp (buf.base, "else"))
|
1029 |
|
|
{
|
1030 |
|
|
if (if_nesting == 1)
|
1031 |
|
|
return 0;
|
1032 |
|
|
}
|
1033 |
|
|
else if (!strcmp (buf.base, "define"))
|
1034 |
|
|
{
|
1035 |
|
|
c = inf_skip_spaces (c);
|
1036 |
|
|
c = inf_scan_ident (&buf, c);
|
1037 |
|
|
if (buf.base[0] > 0 && strcmp (buf.base, protect_name) == 0)
|
1038 |
|
|
define_seen = 1;
|
1039 |
|
|
}
|
1040 |
|
|
skip_to_eol:
|
1041 |
|
|
for (;;)
|
1042 |
|
|
{
|
1043 |
|
|
if (c == '\n' || c == EOF)
|
1044 |
|
|
break;
|
1045 |
|
|
c = INF_GET ();
|
1046 |
|
|
}
|
1047 |
|
|
if (c == EOF)
|
1048 |
|
|
return 0;
|
1049 |
|
|
lineno++;
|
1050 |
|
|
}
|
1051 |
|
|
|
1052 |
|
|
if (!define_seen)
|
1053 |
|
|
return 0;
|
1054 |
|
|
*endif_line = lineno;
|
1055 |
|
|
/* Skip final white space (including comments). */
|
1056 |
|
|
for (;;)
|
1057 |
|
|
{
|
1058 |
|
|
c = inf_skip_spaces (' ');
|
1059 |
|
|
if (c == EOF)
|
1060 |
|
|
break;
|
1061 |
|
|
if (c != '\n')
|
1062 |
|
|
return 0;
|
1063 |
|
|
}
|
1064 |
|
|
|
1065 |
|
|
return 1;
|
1066 |
|
|
}
|
1067 |
|
|
|
1068 |
|
|
extern int main (int, char **);
|
1069 |
|
|
|
1070 |
|
|
int
|
1071 |
|
|
main (int argc, char **argv)
|
1072 |
|
|
{
|
1073 |
|
|
int inf_fd;
|
1074 |
|
|
struct stat sbuf;
|
1075 |
|
|
int c;
|
1076 |
|
|
#ifdef FIXPROTO_IGNORE_LIST
|
1077 |
|
|
int i;
|
1078 |
|
|
#endif
|
1079 |
|
|
const char *cptr;
|
1080 |
|
|
int ifndef_line;
|
1081 |
|
|
int endif_line;
|
1082 |
|
|
long to_read;
|
1083 |
|
|
long int inf_size;
|
1084 |
|
|
struct symbol_list *cur_symbols;
|
1085 |
|
|
|
1086 |
|
|
progname = "fix-header";
|
1087 |
|
|
if (argv[0] && argv[0][0])
|
1088 |
|
|
{
|
1089 |
|
|
char *p;
|
1090 |
|
|
|
1091 |
|
|
progname = 0;
|
1092 |
|
|
for (p = argv[0]; *p; p++)
|
1093 |
|
|
if (*p == '/')
|
1094 |
|
|
progname = p;
|
1095 |
|
|
progname = progname ? progname+1 : argv[0];
|
1096 |
|
|
}
|
1097 |
|
|
|
1098 |
|
|
if (argc < 4)
|
1099 |
|
|
{
|
1100 |
|
|
fprintf (stderr, "%s: Usage: foo.h infile.h outfile.h options\n",
|
1101 |
|
|
progname);
|
1102 |
|
|
exit (FATAL_EXIT_CODE);
|
1103 |
|
|
}
|
1104 |
|
|
|
1105 |
|
|
inc_filename = argv[1];
|
1106 |
|
|
inc_filename_length = strlen (inc_filename);
|
1107 |
|
|
|
1108 |
|
|
#ifdef FIXPROTO_IGNORE_LIST
|
1109 |
|
|
for (i = 0; files_to_ignore[i] != NULL; i++)
|
1110 |
|
|
{
|
1111 |
|
|
const char *const ignore_name = files_to_ignore[i];
|
1112 |
|
|
int ignore_len = strlen (ignore_name);
|
1113 |
|
|
if (strncmp (inc_filename, ignore_name, ignore_len) == 0)
|
1114 |
|
|
{
|
1115 |
|
|
if (ignore_name[ignore_len-1] == '/'
|
1116 |
|
|
|| inc_filename[ignore_len] == '\0')
|
1117 |
|
|
{
|
1118 |
|
|
if (verbose)
|
1119 |
|
|
fprintf (stderr, "%s: ignoring %s\n", progname, inc_filename);
|
1120 |
|
|
exit (SUCCESS_EXIT_CODE);
|
1121 |
|
|
}
|
1122 |
|
|
}
|
1123 |
|
|
|
1124 |
|
|
}
|
1125 |
|
|
#endif
|
1126 |
|
|
|
1127 |
|
|
if (strcmp (inc_filename, "sys/stat.h") == 0)
|
1128 |
|
|
special_file_handling = sys_stat_h;
|
1129 |
|
|
else if (strcmp (inc_filename, "errno.h") == 0)
|
1130 |
|
|
special_file_handling = errno_h, required_other++;
|
1131 |
|
|
else if (strcmp (inc_filename, "stdlib.h") == 0)
|
1132 |
|
|
special_file_handling = stdlib_h, required_other+=2;
|
1133 |
|
|
else if (strcmp (inc_filename, "stdio.h") == 0)
|
1134 |
|
|
special_file_handling = stdio_h;
|
1135 |
|
|
include_entry = std_include_table;
|
1136 |
|
|
while (include_entry->name != NULL
|
1137 |
|
|
&& ((strcmp (include_entry->name, CONTINUED) == 0)
|
1138 |
|
|
|| strcmp (inc_filename, include_entry->name) != 0))
|
1139 |
|
|
include_entry++;
|
1140 |
|
|
|
1141 |
|
|
if (include_entry->name != NULL)
|
1142 |
|
|
{
|
1143 |
|
|
const struct std_include_entry *entry;
|
1144 |
|
|
cur_symbol_table_size = 0;
|
1145 |
|
|
for (entry = include_entry; ;)
|
1146 |
|
|
{
|
1147 |
|
|
if (entry->flags)
|
1148 |
|
|
add_symbols (entry->flags, entry->names);
|
1149 |
|
|
entry++;
|
1150 |
|
|
if (!entry->name || strcmp (entry->name, CONTINUED) != 0)
|
1151 |
|
|
break;
|
1152 |
|
|
}
|
1153 |
|
|
}
|
1154 |
|
|
else
|
1155 |
|
|
symbol_table[0].names = NULL;
|
1156 |
|
|
|
1157 |
|
|
/* Count and mark the prototypes required for this include file. */
|
1158 |
|
|
for (cur_symbols = &symbol_table[0]; cur_symbols->names; cur_symbols++)
|
1159 |
|
|
{
|
1160 |
|
|
int name_len;
|
1161 |
|
|
if (cur_symbols->flags & MACRO_SYMBOL)
|
1162 |
|
|
continue;
|
1163 |
|
|
cptr = cur_symbols->names;
|
1164 |
|
|
for ( ; (name_len = strlen (cptr)) != 0; cptr+= name_len + 1)
|
1165 |
|
|
{
|
1166 |
|
|
struct fn_decl *fn = lookup_std_proto (cptr, name_len);
|
1167 |
|
|
required_unseen_count++;
|
1168 |
|
|
if (fn == NULL)
|
1169 |
|
|
fprintf (stderr, "Internal error: No prototype for %s\n", cptr);
|
1170 |
|
|
else
|
1171 |
|
|
SET_REQUIRED (fn);
|
1172 |
|
|
}
|
1173 |
|
|
}
|
1174 |
|
|
|
1175 |
|
|
read_scan_file (argv[2], argc - 4, argv + 4);
|
1176 |
|
|
|
1177 |
|
|
inf_fd = open (argv[2], O_RDONLY, 0666);
|
1178 |
|
|
if (inf_fd < 0)
|
1179 |
|
|
{
|
1180 |
|
|
fprintf (stderr, "%s: Cannot open '%s' for reading -",
|
1181 |
|
|
progname, argv[2]);
|
1182 |
|
|
perror (NULL);
|
1183 |
|
|
exit (FATAL_EXIT_CODE);
|
1184 |
|
|
}
|
1185 |
|
|
if (fstat (inf_fd, &sbuf) < 0)
|
1186 |
|
|
{
|
1187 |
|
|
fprintf (stderr, "%s: Cannot get size of '%s' -", progname, argv[2]);
|
1188 |
|
|
perror (NULL);
|
1189 |
|
|
exit (FATAL_EXIT_CODE);
|
1190 |
|
|
}
|
1191 |
|
|
inf_size = sbuf.st_size;
|
1192 |
|
|
inf_buffer = XNEWVEC (char, inf_size + 2);
|
1193 |
|
|
inf_ptr = inf_buffer;
|
1194 |
|
|
|
1195 |
|
|
to_read = inf_size;
|
1196 |
|
|
while (to_read > 0)
|
1197 |
|
|
{
|
1198 |
|
|
long i = read (inf_fd, inf_buffer + inf_size - to_read, to_read);
|
1199 |
|
|
if (i < 0)
|
1200 |
|
|
{
|
1201 |
|
|
fprintf (stderr, "%s: Failed to read '%s' -", progname, argv[2]);
|
1202 |
|
|
perror (NULL);
|
1203 |
|
|
exit (FATAL_EXIT_CODE);
|
1204 |
|
|
}
|
1205 |
|
|
if (i == 0)
|
1206 |
|
|
{
|
1207 |
|
|
inf_size -= to_read;
|
1208 |
|
|
break;
|
1209 |
|
|
}
|
1210 |
|
|
to_read -= i;
|
1211 |
|
|
}
|
1212 |
|
|
|
1213 |
|
|
close (inf_fd);
|
1214 |
|
|
|
1215 |
|
|
/* Inf_size may have changed if read was short (as on VMS) */
|
1216 |
|
|
inf_buffer[inf_size] = '\n';
|
1217 |
|
|
inf_buffer[inf_size + 1] = '\0';
|
1218 |
|
|
inf_limit = inf_buffer + inf_size;
|
1219 |
|
|
|
1220 |
|
|
/* If file doesn't end with '\n', add one. */
|
1221 |
|
|
if (inf_limit > inf_buffer && inf_limit[-1] != '\n')
|
1222 |
|
|
inf_limit++;
|
1223 |
|
|
|
1224 |
|
|
unlink (argv[3]);
|
1225 |
|
|
outf = fopen (argv[3], "w");
|
1226 |
|
|
if (outf == NULL)
|
1227 |
|
|
{
|
1228 |
|
|
fprintf (stderr, "%s: Cannot open '%s' for writing -",
|
1229 |
|
|
progname, argv[3]);
|
1230 |
|
|
perror (NULL);
|
1231 |
|
|
exit (FATAL_EXIT_CODE);
|
1232 |
|
|
}
|
1233 |
|
|
|
1234 |
|
|
lineno = 1;
|
1235 |
|
|
|
1236 |
|
|
if (check_protection (&ifndef_line, &endif_line))
|
1237 |
|
|
{
|
1238 |
|
|
lbrac_line = ifndef_line+1;
|
1239 |
|
|
rbrac_line = endif_line;
|
1240 |
|
|
}
|
1241 |
|
|
else
|
1242 |
|
|
{
|
1243 |
|
|
lbrac_line = 1;
|
1244 |
|
|
rbrac_line = -1;
|
1245 |
|
|
}
|
1246 |
|
|
|
1247 |
|
|
/* Reset input file. */
|
1248 |
|
|
inf_ptr = inf_buffer;
|
1249 |
|
|
lineno = 1;
|
1250 |
|
|
|
1251 |
|
|
for (;;)
|
1252 |
|
|
{
|
1253 |
|
|
if (lineno == lbrac_line)
|
1254 |
|
|
write_lbrac ();
|
1255 |
|
|
if (lineno == rbrac_line)
|
1256 |
|
|
write_rbrac ();
|
1257 |
|
|
for (;;)
|
1258 |
|
|
{
|
1259 |
|
|
struct fn_decl *fn;
|
1260 |
|
|
c = INF_GET ();
|
1261 |
|
|
if (c == EOF)
|
1262 |
|
|
break;
|
1263 |
|
|
if (ISIDST (c))
|
1264 |
|
|
{
|
1265 |
|
|
c = inf_scan_ident (&buf, c);
|
1266 |
|
|
(void) INF_UNGET (c);
|
1267 |
|
|
fputs (buf.base, outf);
|
1268 |
|
|
fn = lookup_std_proto (buf.base, strlen (buf.base));
|
1269 |
|
|
/* We only want to edit the declaration matching the one
|
1270 |
|
|
seen by scan-decls, as there can be multiple
|
1271 |
|
|
declarations, selected by #ifdef __STDC__ or whatever. */
|
1272 |
|
|
if (fn && fn->partial && fn->partial->line_seen == lineno)
|
1273 |
|
|
{
|
1274 |
|
|
c = inf_skip_spaces (' ');
|
1275 |
|
|
if (c == EOF)
|
1276 |
|
|
break;
|
1277 |
|
|
if (c == '(')
|
1278 |
|
|
{
|
1279 |
|
|
c = inf_skip_spaces (' ');
|
1280 |
|
|
if (c == ')')
|
1281 |
|
|
{
|
1282 |
|
|
fprintf (outf, " _PARAMS((%s))", fn->params);
|
1283 |
|
|
}
|
1284 |
|
|
else
|
1285 |
|
|
{
|
1286 |
|
|
putc ('(', outf);
|
1287 |
|
|
(void) INF_UNGET (c);
|
1288 |
|
|
}
|
1289 |
|
|
}
|
1290 |
|
|
else
|
1291 |
|
|
fprintf (outf, " %c", c);
|
1292 |
|
|
}
|
1293 |
|
|
}
|
1294 |
|
|
else
|
1295 |
|
|
{
|
1296 |
|
|
putc (c, outf);
|
1297 |
|
|
if (c == '\n')
|
1298 |
|
|
break;
|
1299 |
|
|
}
|
1300 |
|
|
}
|
1301 |
|
|
if (c == EOF)
|
1302 |
|
|
break;
|
1303 |
|
|
lineno++;
|
1304 |
|
|
}
|
1305 |
|
|
if (rbrac_line < 0)
|
1306 |
|
|
write_rbrac ();
|
1307 |
|
|
|
1308 |
|
|
fclose (outf);
|
1309 |
|
|
|
1310 |
|
|
return 0;
|
1311 |
|
|
}
|