]> gcc.gnu.org Git - gcc.git/blame - gcc/fix-header.c
Fix whitespace in pattern.
[gcc.git] / gcc / fix-header.c
CommitLineData
e7f9bcdc 1/* fix-header.c - Make C header file suitable for C++.
55575a9d 2 Copyright (C) 1993, 1994 Free Software Foundation, Inc.
7936052f
PB
3
4This program is free software; you can redistribute it and/or modify it
5under the terms of the GNU General Public License as published by the
6Free Software Foundation; either version 2, or (at your option) any
7later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18/* This program massages a system include file (such as stdio.h),
19 into a form more conformant with ANSI/POSIX, and more suitable for C++:
20
21 * extern "C" { ... } braces are added (inside #ifndef __cplusplus),
05227b51 22 if they seem to be needed. These prevent C++ compilers from name
7936052f
PB
23 mangling the functions inside the braces.
24
25 * If an old-style incomplete function declaration is seen (without
26 an argument list), and it is a "standard" function listed in
27 the file sys-protos.h (and with a non-empty argument list), then
28 the declaration is converted to a complete prototype by replacing
29 the empty parameter list with the argument lust from sys-protos.h.
30
31 * The program can be given a list of (names of) required standard
32 functions (such as fclose for stdio.h). If a reqquired function
33 is not seen in the input, then a prototype for it will be
34 written to the output.
35
36 * If all of the non-comment code of the original file is protected
37 against multiple inclusion:
38 #ifndef FOO
39 #define FOO
40 <body of include file>
41 #endif
42 then extra matter added to the include file is placed inside the <body>.
43
44 * If the input file is OK (nothing needs to be done);
45 the output file is not written (nor removed if it exists).
46
47 There are also some special actions that are done for certain
48 well-known standard include files:
49
50 * If argv[1] is "sys/stat.h", the Posix.1 macros
51 S_ISBLK, S_ISCHR, S_ISDIR, S_ISFIFO, S_ISLNK, S_ISREG are added if
52 they were missing, and the corresponding "traditional" S_IFxxx
53 macros were defined.
54
55 * If argv[1] is "errno.h", errno is declared if it was missing.
56
57 * TODO: The input file should be read complete into memory, because:
58 a) it needs to be scanned twice anyway, and
59 b) it would be nice to allow update in place.
60
61 Usage:
e7f9bcdc 62 fix-header FOO.H INFILE.H OUTFILE.H REQUIRED_FUNCS <SCAN-FILE
7936052f
PB
63 where:
64 * FOO.H is the relative file name of the include file,
65 as it would be #include'd by a C file. (E.g. stdio.h)
66 * INFILE.H is a full pathname for the input file (e.g. /usr/include/stdio.h)
67 * OUTFILE.H is the full pathname for where to write the output file,
68 if anything needs to be done. (e.g. ./include/stdio.h)
69 * SCAN-FILE is the output of the scan-decls program.
70 * REQUIRED_FUNCS is a list of required function (e.g. fclose for stdio.h).
71
72 Written by Per Bothner <bothner@cygnus.com>, July 1993. */
73
74#include <stdio.h>
75#include <ctype.h>
05227b51 76#include <sys/types.h>
49d3ca5c 77#include <sys/stat.h>
05227b51
PB
78#ifndef O_RDONLY
79#define O_RDONLY 0
80#endif
39eda06e 81#include "hconfig.h"
7936052f
PB
82#include "obstack.h"
83#include "scan.h"
84
8fb0620c
PB
85extern sstring buf;
86
7936052f
PB
87int verbose = 0;
88int partial_count = 0;
af86171d
JW
89#if 0
90/* All uses of this are ifdefed out. This is no longer needed, because
91 cccp.c implicitly forces the standard include files to be treated as C.
92 Adding an explicit extern "C" is undesireable as it breaks the SunOS 4.x
93 sun4c/romvec.h file. */
7936052f 94int missing_extern_C_count = 0;
af86171d 95#endif
b156894e 96int missing_errno = 0;
7936052f
PB
97
98#include "xsys-protos.h"
99
05227b51
PB
100char *inf_buffer;
101char *inf_limit;
102char *inf_ptr;
05227b51 103
7936052f
PB
104/* Certain standard files get extra treatment */
105
106enum special_file
107{
108 no_special,
109 errno_special,
110 sys_stat_special
111};
112
113enum special_file special_file_handling = no_special;
114
115/* The following are only used when handling sys/stat.h */
116/* They are set if the corresponding macro has been seen. */
117int seen_S_IFBLK = 0, seen_S_ISBLK = 0;
118int seen_S_IFCHR = 0, seen_S_ISCHR = 0;
119int seen_S_IFDIR = 0, seen_S_ISDIR = 0;
120int seen_S_IFIFO = 0, seen_S_ISFIFO = 0;
121int seen_S_IFLNK = 0, seen_S_ISLNK = 0;
122int seen_S_IFREG = 0, seen_S_ISREG = 0;
10b8b0ba 123\f
7936052f
PB
124/* Wrapper around free, to avoid prototype clashes. */
125
10b8b0ba
RS
126void
127xfree (ptr)
7936052f
PB
128 char *ptr;
129{
c2b6b9a1 130 free (ptr);
7936052f
PB
131}
132
10b8b0ba
RS
133/* Avoid error if config defines abort as fancy_abort.
134 It's not worth "really" implementing this because ordinary
135 compiler users never run fix-header. */
136
137void
138fancy_abort ()
139{
140 abort ();
141}
142\f
7936052f
PB
143#define obstack_chunk_alloc xmalloc
144#define obstack_chunk_free xfree
145struct obstack scan_file_obstack;
146
147/* NOTE: If you edit this, also edit gen-protos.c !! */
148struct fn_decl *
149lookup_std_proto (name)
150 char *name;
151{
c2b6b9a1 152 int i = hash (name) % HASH_SIZE;
7936052f
PB
153 int i0 = i;
154 for (;;)
155 {
156 struct fn_decl *fn;
157 if (hash_tab[i] == 0)
158 return NULL;
159 fn = &std_protos[hash_tab[i]];
160 if (strcmp (fn->fname, name) == 0)
161 return fn;
162 i = (i+1) % HASH_SIZE;
163 if (i == i0)
c2b6b9a1 164 abort ();
7936052f
PB
165 }
166}
167
168char *inc_filename;
169int inc_filename_length;
e7f9bcdc 170char *progname = "fix-header";
7936052f 171FILE *outf;
7936052f
PB
172sstring line;
173
174int lbrac_line, rbrac_line;
175
176char **required_functions;
177int required_unseen_count;
178
179int
180write_lbrac ()
181{
b156894e 182
af86171d 183#if 0
b156894e
RS
184 if (missing_extern_C_count + required_unseen_count > 0)
185 fprintf (outf, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
af86171d 186#endif
7936052f
PB
187
188 if (partial_count)
189 {
190 fprintf (outf, "#ifndef _PARAMS\n");
191 fprintf (outf, "#if defined(__STDC__) || defined(__cplusplus)\n");
192 fprintf (outf, "#define _PARAMS(ARGS) ARGS\n");
193 fprintf (outf, "#else\n");
194 fprintf (outf, "#define _PARAMS(ARGS) ()\n");
195 fprintf (outf, "#endif\n#endif /* _PARAMS */\n");
196 }
197}
198
199struct partial_proto
200{
201 struct partial_proto *next;
202 char *fname; /* name of function */
203 char *rtype; /* return type */
204 struct fn_decl *fn;
205 int line_seen;
206};
207
208struct partial_proto *partial_proto_list = NULL;
209
210struct partial_proto required_dummy_proto;
211#define REQUIRED(FN) ((FN)->partial == &required_dummy_proto)
212#define SET_REQUIRED(FN) ((FN)->partial = &required_dummy_proto)
213#define CLEAR_REQUIRED(FN) ((FN)->partial = 0)
214
215void
05227b51
PB
216recognized_macro (fname)
217 char *fname;
7936052f 218{
05227b51
PB
219 /* The original include file defines fname as a macro. */
220 struct fn_decl *fn = lookup_std_proto (fname);
7936052f 221
05227b51
PB
222 /* Since fname is a macro, don't require a prototype for it. */
223 if (fn && REQUIRED (fn))
7936052f 224 {
c2b6b9a1 225 CLEAR_REQUIRED (fn);
05227b51
PB
226 required_unseen_count--;
227 }
7936052f 228
05227b51
PB
229 switch (special_file_handling)
230 {
231 case errno_special:
b156894e 232 if (strcmp (fname, "errno") == 0) missing_errno = 0;
05227b51
PB
233 break;
234 case sys_stat_special:
235 if (fname[0] == 'S' && fname[1] == '_')
7936052f 236 {
05227b51
PB
237 if (strcmp (fname, "S_IFBLK") == 0) seen_S_IFBLK++;
238 else if (strcmp (fname, "S_ISBLK") == 0) seen_S_ISBLK++;
239 else if (strcmp (fname, "S_IFCHR") == 0) seen_S_IFCHR++;
240 else if (strcmp (fname, "S_ISCHR") == 0) seen_S_ISCHR++;
241 else if (strcmp (fname, "S_IFDIR") == 0) seen_S_IFDIR++;
242 else if (strcmp (fname, "S_ISDIR") == 0) seen_S_ISDIR++;
243 else if (strcmp (fname, "S_IFIFO") == 0) seen_S_IFIFO++;
244 else if (strcmp (fname, "S_ISFIFO") == 0) seen_S_ISFIFO++;
245 else if (strcmp (fname, "S_IFLNK") == 0) seen_S_IFLNK++;
246 else if (strcmp (fname, "S_ISLNK") == 0) seen_S_ISLNK++;
247 else if (strcmp (fname, "S_IFREG") == 0) seen_S_IFREG++;
248 else if (strcmp (fname, "S_ISREG") == 0) seen_S_ISREG++;
7936052f 249 }
05227b51
PB
250 }
251}
7936052f 252
05227b51
PB
253void
254recognized_extern (name, type)
255 char *name;
256 char *type;
257{
258 switch (special_file_handling)
259 {
260 case errno_special:
b156894e 261 if (strcmp (name, "errno") == 0) missing_errno = 0;
05227b51
PB
262 break;
263 }
264}
7936052f 265
05227b51
PB
266/* Called by scan_decls if it saw a function definition for a function
267 named FNAME, with return type RTYPE, and argument list ARGS,
268 in source file FILE_SEEN on line LINE_SEEN.
269 KIND is 'I' for an inline function;
270 'F' if a normal function declaration preceded by 'extern "C"'
271 (or nested inside 'extern "C"' braces); or
272 'f' for other function declarations. */
7936052f 273
05227b51
PB
274void
275recognized_function (fname, kind, rtype, args, file_seen, line_seen)
276 char *fname;
277 int kind; /* One of 'f' 'F' or 'I' */
278 char *rtype;
279 char *args;
280 char *file_seen;
281 int line_seen;
282{
283 struct partial_proto *partial;
284 int i;
285 struct fn_decl *fn;
af86171d 286#if 0
05227b51
PB
287 if (kind == 'f')
288 missing_extern_C_count++;
af86171d 289#endif
7936052f 290
05227b51 291 fn = lookup_std_proto (fname);
7936052f 292
05227b51
PB
293 /* Remove the function from the list of required function. */
294 if (fn && REQUIRED (fn))
295 {
c2b6b9a1 296 CLEAR_REQUIRED (fn);
05227b51
PB
297 required_unseen_count--;
298 }
e9cd0b25 299
05227b51
PB
300 /* If we have a full prototype, we're done. */
301 if (args[0] != '\0')
302 return;
303
304 if (kind == 'I') /* don't edit inline function */
305 return;
306
307 /* If the partial prototype was included from some other file,
308 we don't need to patch it up (in this run). */
309 i = strlen (file_seen);
310 if (i < inc_filename_length
311 || strcmp (inc_filename, file_seen + (i - inc_filename_length)) != 0)
312 return;
313
314 if (fn == NULL)
315 return;
c2b6b9a1 316 if (fn->params[0] == '\0' || strcmp (fn->params, "void") == 0)
05227b51
PB
317 return;
318
319 /* We only have a partial function declaration,
320 so remember that we have to add a complete prototype. */
321 partial_count++;
322 partial = (struct partial_proto*)
c2b6b9a1
RS
323 obstack_alloc (&scan_file_obstack, sizeof (struct partial_proto));
324 partial->fname = obstack_alloc (&scan_file_obstack, strlen (fname) + 1);
05227b51 325 strcpy (partial->fname, fname);
c2b6b9a1 326 partial->rtype = obstack_alloc (&scan_file_obstack, strlen (rtype) + 1);
05227b51
PB
327 strcpy (partial->rtype, rtype);
328 partial->line_seen = line_seen;
329 partial->fn = fn;
330 fn->partial = partial;
331 partial->next = partial_proto_list;
332 partial_proto_list = partial;
333 if (verbose)
334 {
335 fprintf (stderr, "(%s: %s non-prototype function declaration.)\n",
336 inc_filename, fname);
337 }
338}
7936052f 339
05227b51
PB
340void
341read_scan_file (scan_file)
342 FILE *scan_file;
343{
c2b6b9a1 344 obstack_init (&scan_file_obstack);
7936052f 345
05227b51 346 scan_decls (scan_file);
7936052f 347
af86171d
JW
348 if (required_unseen_count + partial_count + missing_errno
349#if 0
350 + missing_extern_C_count
351#endif
352 == 0)
7936052f
PB
353 {
354 if (verbose)
355 fprintf (stderr, "%s: OK, nothing needs to be done.\n", inc_filename);
356 exit (0);
357 }
e9cd0b25
PB
358 if (!verbose)
359 fprintf (stderr, "%s: fixing %s\n", progname, inc_filename);
360 else
361 {
362 if (required_unseen_count)
363 fprintf (stderr, "%s: %d missing function declarations.\n",
364 inc_filename, required_unseen_count);
365 if (partial_count)
366 fprintf (stderr, "%s: %d non-prototype function declarations.\n",
367 inc_filename, partial_count);
af86171d 368#if 0
e9cd0b25
PB
369 if (missing_extern_C_count)
370 fprintf (stderr,
371 "%s: %d declarations not protected by extern \"C\".\n",
372 inc_filename, missing_extern_C_count);
af86171d 373#endif
e9cd0b25 374 }
7936052f
PB
375}
376
377write_rbrac ()
378{
379 struct fn_decl *fn;
380 char **rptr;
7936052f
PB
381
382 if (required_unseen_count)
2ee370da 383 fprintf (outf, "#ifdef __cplusplus\n");
7936052f
PB
384
385 /* Now we print out prototypes for those functions that we haven't seen. */
386 for (rptr = required_functions; *rptr; rptr++)
387 {
10b8b0ba
RS
388 int macro_protect = 0;
389
7936052f
PB
390 fn = lookup_std_proto (*rptr);
391 if (fn == NULL || !REQUIRED (fn))
392 continue;
10b8b0ba
RS
393
394 /* In the case of memmove, protect in case the application
395 defines it as a macro before including the header. */
5881bacc
RS
396 if (!strcmp (fn->fname, "memmove")
397 || !strcmp (fn->fname, "vprintf")
398 || !strcmp (fn->fname, "vfprintf")
4bc38260
RS
399 || !strcmp (fn->fname, "vsprintf")
400 || !strcmp (fn->fname, "rewinddir"))
10b8b0ba
RS
401 macro_protect = 1;
402
403 if (macro_protect)
404 fprintf (outf, "#ifndef %s\n", fn->fname);
7936052f
PB
405 fprintf (outf, "extern %s %s (%s);\n",
406 fn->rtype, fn->fname, fn->params);
10b8b0ba
RS
407 if (macro_protect)
408 fprintf (outf, "#endif\n");
7936052f
PB
409 }
410 if (required_unseen_count)
411 fprintf (outf,
2ee370da 412 "#endif /* defined(__cplusplus) */\n");
7936052f
PB
413
414 switch (special_file_handling)
415 {
416 case errno_special:
b156894e 417 if (missing_errno)
7936052f
PB
418 fprintf (outf, "extern int errno;\n");
419 break;
420 case sys_stat_special:
421 if (!seen_S_ISBLK && seen_S_IFBLK)
422 fprintf (outf,
423 "#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)\n");
424 if (!seen_S_ISCHR && seen_S_IFCHR)
425 fprintf (outf,
426 "#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)\n");
427 if (!seen_S_ISDIR && seen_S_IFDIR)
428 fprintf (outf,
429 "#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)\n");
430 if (!seen_S_ISFIFO && seen_S_IFIFO)
431 fprintf (outf,
432 "#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)\n");
433 if (!seen_S_ISLNK && seen_S_IFLNK)
434 fprintf (outf,
435 "#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)\n");
436 if (!seen_S_ISREG && seen_S_IFREG)
437 fprintf (outf,
438 "#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)\n");
439 break;
440 }
441
442
af86171d 443#if 0
b156894e
RS
444 if (missing_extern_C_count + required_unseen_count > 0)
445 fprintf (outf, "#ifdef __cplusplus\n}\n#endif\n");
af86171d 446#endif
7936052f
PB
447}
448
449char *
450strdup (str)
451 char *str;
452{
c2b6b9a1
RS
453 char *copy = (char *) xmalloc (strlen (str) + 1);
454 strcpy (copy, str);
455 return copy;
7936052f
PB
456}
457
458/* Returns 1 iff the file is properly protected from multiple inclusion:
459 #ifndef PROTECT_NAME
460 #define PROTECT_NAME
461 #endif
462
463 */
464
05227b51 465#define INF_GET() (inf_ptr < inf_limit ? *(unsigned char*)inf_ptr++ : EOF)
c2b6b9a1 466#define INF_UNGET(c) ((c)!=EOF && inf_ptr--)
05227b51
PB
467
468int
469inf_skip_spaces (c)
470 int c;
471{
472 for (;;)
473 {
474 if (c == ' ' || c == '\t')
c2b6b9a1 475 c = INF_GET ();
05227b51
PB
476 else if (c == '/')
477 {
c2b6b9a1 478 c = INF_GET ();
05227b51
PB
479 if (c != '*')
480 {
c2b6b9a1 481 INF_UNGET (c);
05227b51
PB
482 return '/';
483 }
c2b6b9a1 484 c = INF_GET ();
05227b51
PB
485 for (;;)
486 {
487 if (c == EOF)
488 return EOF;
489 else if (c != '*')
490 {
491 if (c == '\n')
492 source_lineno++, lineno++;
493 c = INF_GET ();
494 }
c2b6b9a1
RS
495 else if ((c = INF_GET ()) == '/')
496 return INF_GET ();
05227b51
PB
497 }
498 }
499 else
500 break;
501 }
502 return c;
503}
504
505/* Read into STR from inf_buffer upto DELIM. */
506
507int
508inf_read_upto (str, delim)
509 sstring *str;
510 int delim;
511{
512 int ch;
513 for (;;)
514 {
515 ch = INF_GET ();
516 if (ch == EOF || ch == delim)
517 break;
c2b6b9a1 518 SSTRING_PUT (str, ch);
05227b51 519 }
c2b6b9a1 520 MAKE_SSTRING_SPACE (str, 1);
05227b51
PB
521 *str->ptr = 0;
522 return ch;
523}
524
7936052f 525int
05227b51
PB
526inf_scan_ident (s, c)
527 register sstring *s;
528 int c;
529{
530 s->ptr = s->base;
c2b6b9a1 531 if (isalpha (c) || c == '_')
05227b51
PB
532 {
533 for (;;)
534 {
c2b6b9a1 535 SSTRING_PUT (s, c);
05227b51 536 c = INF_GET ();
c2b6b9a1 537 if (c == EOF || !(isalnum (c) || c == '_'))
05227b51
PB
538 break;
539 }
540 }
c2b6b9a1 541 MAKE_SSTRING_SPACE (s, 1);
05227b51
PB
542 *s->ptr = 0;
543 return c;
544}
545
546/* Returns 1 if the file is correctly protected against multiple
547 inclusion, setting *ifndef_line to the line number of the initial #ifndef
548 and setting *endif_line to the final #endif.
549 Otherwise return 0. */
550
551int
552check_protection (ifndef_line, endif_line)
7936052f
PB
553 int *ifndef_line, *endif_line;
554{
555 int c;
556 int if_nesting = 1; /* Level of nesting of #if's */
557 char *protect_name = NULL; /* Identifier following initial #ifndef */
558 int define_seen = 0;
559
560 /* Skip initial white space (including comments). */
561 for (;; lineno++)
562 {
05227b51 563 c = inf_skip_spaces (' ');
7936052f
PB
564 if (c == EOF)
565 return 0;
566 if (c != '\n')
567 break;
568 }
569 if (c != '#')
570 return 0;
05227b51 571 c = inf_scan_ident (&buf, inf_skip_spaces (' '));
c2b6b9a1 572 if (SSTRING_LENGTH (&buf) == 0 || strcmp (buf.base, "ifndef") != 0)
7936052f
PB
573 return 0;
574
575 /* So far so good: We've seen an initial #ifndef. */
576 *ifndef_line = lineno;
05227b51 577 c = inf_scan_ident (&buf, inf_skip_spaces (c));
c2b6b9a1 578 if (SSTRING_LENGTH (&buf) == 0 || c == EOF)
7936052f
PB
579 return 0;
580 protect_name = strdup (buf.base);
581
c2b6b9a1 582 INF_UNGET (c);
05227b51 583 c = inf_read_upto (&buf, '\n');
7936052f
PB
584 if (c == EOF)
585 return 0;
586 lineno++;
587
588 for (;;)
589 {
c2b6b9a1 590 c = inf_skip_spaces (' ');
7936052f
PB
591 if (c == EOF)
592 return 0;
593 if (c == '\n')
594 {
595 lineno++;
596 continue;
597 }
598 if (c != '#')
599 goto skip_to_eol;
05227b51 600 c = inf_scan_ident (&buf, inf_skip_spaces (' '));
c2b6b9a1 601 if (SSTRING_LENGTH (&buf) == 0)
7936052f
PB
602 ;
603 else if (!strcmp (buf.base, "ifndef")
604 || !strcmp (buf.base, "ifdef") || !strcmp (buf.base, "if"))
605 {
606 if_nesting++;
607 }
608 else if (!strcmp (buf.base, "endif"))
609 {
610 if_nesting--;
611 if (if_nesting == 0)
612 break;
613 }
614 else if (!strcmp (buf.base, "else"))
615 {
616 if (if_nesting == 1)
617 return 0;
618 }
619 else if (!strcmp (buf.base, "define"))
620 {
621 if (if_nesting != 1)
622 goto skip_to_eol;
05227b51
PB
623 c = inf_skip_spaces (c);
624 c = inf_scan_ident (&buf, c);
c2b6b9a1 625 if (buf.base[0] > 0 && strcmp (buf.base, protect_name) == 0)
7936052f
PB
626 define_seen = 1;
627 }
628 skip_to_eol:
629 for (;;)
630 {
631 if (c == '\n' || c == EOF)
632 break;
c2b6b9a1 633 c = INF_GET ();
7936052f
PB
634 }
635 if (c == EOF)
636 return 0;
637 lineno++;
638 }
639
640 if (!define_seen)
641 return 0;
642 *endif_line = lineno;
643 /* Skip final white space (including comments). */
644 for (;;)
645 {
05227b51 646 c = inf_skip_spaces (' ');
7936052f
PB
647 if (c == EOF)
648 break;
649 if (c != '\n')
650 return 0;
651 }
652
653 return 1;
654}
655
656int
c2b6b9a1 657main (argc, argv)
7936052f
PB
658 int argc;
659 char **argv;
660{
05227b51
PB
661 int inf_fd;
662 struct stat sbuf;
7936052f
PB
663 int c;
664 int i, done;
665 char *cptr, *cptr0, **pptr;
666 int ifndef_line;
05227b51
PB
667 int endif_line;
668 long to_read;
c2b6b9a1 669 long int inf_size;
7936052f
PB
670
671 if (argv[0] && argv[0][0])
9bbd1091
RS
672 {
673 register char *p;
674
675 progname = 0;
676 for (p = argv[0]; *p; p++)
677 if (*p == '/')
678 progname = p;
679 progname = progname ? progname+1 : argv[0];
680 }
7936052f
PB
681
682 if (argc < 4)
683 {
684 fprintf (stderr, "%s: Usage: foo.h infile.h outfile.h req_funcs <scan-file-name\n",
685 progname);
686 exit (-1);
687 }
688
689 inc_filename = argv[1];
690 inc_filename_length = strlen (inc_filename);
691 if (strcmp (inc_filename, "sys/stat.h") == 0)
692 special_file_handling = sys_stat_special;
693 else if (strcmp (inc_filename, "errno.h") == 0)
b156894e 694 special_file_handling = errno_special, missing_errno = 1;
7936052f
PB
695
696 /* Calculate an upper bound of the number of function names in argv[4] */
697 for (i = 1, cptr = argv[4]; *cptr; cptr++)
698 if (*cptr == ' ') i++;
699 /* Find the list of prototypes required for this include file. */
c2b6b9a1 700 required_functions = (char**)xmalloc ((i+1) * sizeof (char*));
7936052f
PB
701 for (cptr = argv[4], cptr0 = cptr, pptr = required_functions, done = 0;
702 !done; cptr++)
703 {
704 done = *cptr == '\0';
705 if (*cptr == ' ' || done)
706 {
707 *cptr = '\0';
708 if (cptr > cptr0)
709 {
c2b6b9a1 710 struct fn_decl *fn = lookup_std_proto (cptr0);
7936052f
PB
711 *pptr++ = cptr0;
712 if (fn == NULL)
713 fprintf (stderr, "Internal error: No prototype for %s\n",
714 cptr0);
715 else
c2b6b9a1 716 SET_REQUIRED (fn);
7936052f
PB
717 }
718 cptr0 = cptr + 1;
719 }
720 }
721 required_unseen_count = pptr - required_functions;
722 *pptr = 0;
723
724 read_scan_file (stdin);
725
05227b51
PB
726 inf_fd = open (argv[2], O_RDONLY, 0666);
727 if (inf_fd < 0)
7936052f
PB
728 {
729 fprintf (stderr, "%s: Cannot open '%s' for reading -",
730 progname, argv[2]);
731 perror (NULL);
732 exit (-1);
733 }
05227b51
PB
734 if (fstat (inf_fd, &sbuf) < 0)
735 {
736 fprintf (stderr, "%s: Cannot get size of '%s' -", progname, argv[2]);
737 perror (NULL);
738 exit (-1);
739 }
740 inf_size = sbuf.st_size;
741 inf_buffer = (char*) xmalloc (inf_size + 2);
742 inf_buffer[inf_size] = '\n';
743 inf_buffer[inf_size + 1] = '\0';
744 inf_limit = inf_buffer + inf_size;
745 inf_ptr = inf_buffer;
746
747 to_read = inf_size;
748 while (to_read > 0)
749 {
750 long i = read (inf_fd, inf_buffer + inf_size - to_read, to_read);
751 if (i < 0)
752 {
753 fprintf (stderr, "%s: Failed to read '%s' -", progname, argv[2]);
754 perror (NULL);
755 exit (-1);
756 }
757 if (i == 0)
758 {
759 inf_size -= to_read;
760 break;
761 }
762 to_read -= i;
763 }
764
765 close (inf_fd);
7936052f 766
c2b6b9a1
RS
767 /* If file doesn't end with '\n', add one. */
768 if (inf_limit > inf_buffer && inf_limit[-1] != '\n')
769 inf_limit++;
770
9bbd1091 771 unlink (argv[3]);
7936052f
PB
772 outf = fopen (argv[3], "w");
773 if (outf == NULL)
774 {
775 fprintf (stderr, "%s: Cannot open '%s' for writing -",
776 progname, argv[3]);
777 perror (NULL);
778 exit (-1);
779 }
780
05227b51
PB
781 lineno = 1;
782
783 if (check_protection (&ifndef_line, &endif_line))
7936052f
PB
784 {
785#if 0
c2b6b9a1
RS
786 fprintf (stderr, "#ifndef %s on line %d; #endif on line %d\n",
787 protect_name, ifndef_line, endif_line);
7936052f
PB
788#endif
789 lbrac_line = ifndef_line+1;
790 rbrac_line = endif_line;
791 }
792 else
793 {
794 lbrac_line = 1;
795 rbrac_line = -1;
796 }
797
05227b51
PB
798 /* Reset input file. */
799 inf_ptr = inf_buffer;
7936052f
PB
800 lineno = 1;
801
802 for (;;)
803 {
804 if (lineno == lbrac_line)
805 write_lbrac ();
806 if (lineno == rbrac_line)
807 write_rbrac ();
808 for (;;)
809 {
810 struct fn_decl *fn;
c2b6b9a1 811 c = INF_GET ();
7936052f
PB
812 if (c == EOF)
813 break;
814 if (isalpha (c) || c == '_')
815 {
05227b51 816 c = inf_scan_ident (&buf, c);
c2b6b9a1 817 INF_UNGET (c);
7936052f
PB
818 fputs (buf.base, outf);
819 fn = lookup_std_proto (buf.base);
820 /* We only want to edit the declaration matching the one
821 seen by scan-decls, as there can be multiple
822 declarations, selected by #ifdef __STDC__ or whatever. */
823 if (fn && fn->partial && fn->partial->line_seen == lineno)
824 {
05227b51 825 c = inf_skip_spaces (' ');
7936052f
PB
826 if (c == EOF)
827 break;
828 if (c == '(')
829 {
05227b51 830 c = inf_skip_spaces (' ');
7936052f
PB
831 if (c == ')')
832 {
833 fprintf (outf, " _PARAMS((%s))", fn->params);
834 }
835 else
836 {
837 putc ('(', outf);
c2b6b9a1 838 INF_UNGET (c);
7936052f
PB
839 }
840 }
841 else
e9cd0b25 842 fprintf (outf, " %c", c);
7936052f
PB
843 }
844 }
845 else
05227b51
PB
846 {
847 putc (c, outf);
848 if (c == '\n')
849 break;
850 }
7936052f
PB
851 }
852 if (c == EOF)
853 break;
854 lineno++;
855 }
856 if (rbrac_line < 0)
857 write_rbrac ();
858
7936052f
PB
859 fclose (outf);
860
861 return 0;
862}
This page took 0.185346 seconds and 5 git commands to generate.