OSDN Git Service

(read_scan_file): Remove decl of unused variable RPTR.
[pf3gnuchains/gcc-fork.git] / gcc / fix-header.c
1 /* fix-header.c - Make C header file suitable for C++.
2    Copyright (C) 1993, 1994 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 2, or (at your option) any
7 later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, 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),
22    if they seem to be needed.  These prevent C++ compilers from name
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:
62         fix-header FOO.H INFILE.H OUTFILE.H REQUIRED_FUNCS <SCAN-FILE
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>
76 #include <sys/types.h>
77 #include <sys/stat.h>
78 #ifndef O_RDONLY
79 #define O_RDONLY 0
80 #endif
81 #include "hconfig.h"
82 #include "obstack.h"
83 #include "scan.h"
84
85 extern sstring buf;
86
87 int verbose = 0;
88 int partial_count = 0;
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.  */
94 int missing_extern_C_count = 0;
95 #endif
96 int missing_errno = 0;
97
98 #include "xsys-protos.h"
99
100 char *inf_buffer;
101 char *inf_limit;
102 char *inf_ptr;
103
104 /* Certain standard files get extra treatment */
105
106 enum special_file
107 {
108   no_special,
109   errno_special,
110   sys_stat_special
111 };
112
113 enum 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. */
117 int seen_S_IFBLK = 0, seen_S_ISBLK  = 0;
118 int seen_S_IFCHR = 0, seen_S_ISCHR  = 0;
119 int seen_S_IFDIR = 0, seen_S_ISDIR  = 0;
120 int seen_S_IFIFO = 0, seen_S_ISFIFO = 0;
121 int seen_S_IFLNK = 0, seen_S_ISLNK  = 0;
122 int seen_S_IFREG = 0, seen_S_ISREG  = 0;
123 \f
124 /* Wrapper around free, to avoid prototype clashes. */
125
126 void
127 xfree (ptr)
128      char *ptr;
129 {
130   free (ptr);
131 }
132
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
137 void
138 fancy_abort ()
139 {
140   abort ();
141 }
142 \f
143 #define obstack_chunk_alloc xmalloc
144 #define obstack_chunk_free xfree
145 struct obstack scan_file_obstack;
146
147 /* NOTE:  If you edit this, also edit gen-protos.c !! */
148 struct fn_decl *
149 lookup_std_proto (name)
150      char *name;
151 {
152   int i = hash (name) % HASH_SIZE;
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)
164         abort ();
165     }
166 }
167
168 char *inc_filename;
169 int inc_filename_length;
170 char *progname = "fix-header";
171 FILE *outf;
172 sstring line;
173
174 int lbrac_line, rbrac_line;
175
176 char **required_functions;
177 int required_unseen_count;
178
179 int 
180 write_lbrac ()
181 {
182   
183 #if 0
184   if (missing_extern_C_count + required_unseen_count > 0)
185     fprintf (outf, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
186 #endif
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
199 struct 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
208 struct partial_proto *partial_proto_list = NULL;
209
210 struct 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
215 void
216 recognized_macro (fname)
217      char *fname;
218 {
219   /* The original include file defines fname as a macro. */
220   struct fn_decl *fn = lookup_std_proto (fname);
221
222   /* Since fname is a macro, don't require a prototype for it. */
223   if (fn && REQUIRED (fn))
224     {
225       CLEAR_REQUIRED (fn);
226       required_unseen_count--;
227     }
228
229   switch (special_file_handling)
230     {
231     case errno_special:
232       if (strcmp (fname, "errno") == 0) missing_errno = 0;
233       break;
234     case sys_stat_special:
235       if (fname[0] == 'S' && fname[1] == '_')
236         {
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++;
249         }
250     }
251 }
252
253 void
254 recognized_extern (name, type)
255      char *name;
256      char *type;
257 {
258   switch (special_file_handling)
259     {
260     case errno_special:
261       if (strcmp (name, "errno") == 0) missing_errno = 0;
262       break;
263     }
264 }
265
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. */
273
274 void
275 recognized_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;
286 #if 0
287   if (kind == 'f')
288     missing_extern_C_count++;
289 #endif
290
291   fn = lookup_std_proto (fname);
292
293   /* Remove the function from the list of required function. */
294   if (fn && REQUIRED (fn))
295     {
296       CLEAR_REQUIRED (fn);
297       required_unseen_count--;
298     }
299
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;
316   if (fn->params[0] == '\0' || strcmp (fn->params, "void") == 0)
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*)
323     obstack_alloc (&scan_file_obstack, sizeof (struct partial_proto));
324   partial->fname = obstack_alloc (&scan_file_obstack, strlen (fname) + 1);
325   strcpy (partial->fname, fname);
326   partial->rtype = obstack_alloc (&scan_file_obstack, strlen (rtype) + 1);
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 }
339
340 void
341 read_scan_file (scan_file)
342      FILE *scan_file;
343 {
344   obstack_init (&scan_file_obstack); 
345
346   scan_decls (scan_file);
347
348   if (required_unseen_count + partial_count + missing_errno
349 #if 0
350       + missing_extern_C_count
351 #endif      
352       == 0)
353     {
354       if (verbose)
355         fprintf (stderr, "%s: OK, nothing needs to be done.\n", inc_filename);
356       exit (0);
357     }
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);
368 #if 0
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);
373 #endif
374     }
375 }
376
377 write_rbrac ()
378 {
379   struct fn_decl *fn;
380   char **rptr;
381
382   if (required_unseen_count)
383     fprintf (outf, "#ifdef __cplusplus\n");
384
385   /* Now we print out prototypes for those functions that we haven't seen. */
386   for (rptr = required_functions; *rptr; rptr++)
387     {
388       int macro_protect = 0;
389
390       fn = lookup_std_proto (*rptr);
391       if (fn == NULL || !REQUIRED (fn))
392         continue;
393
394       /* In the case of memmove, protect in case the application
395          defines it as a macro before including the header.  */
396       if (!strcmp (fn->fname, "memmove")
397           || !strcmp (fn->fname, "vprintf")
398           || !strcmp (fn->fname, "vfprintf")
399           || !strcmp (fn->fname, "vsprintf")
400           || !strcmp (fn->fname, "rewinddir"))
401         macro_protect = 1;
402
403       if (macro_protect)
404         fprintf (outf, "#ifndef %s\n", fn->fname);
405       fprintf (outf, "extern %s %s (%s);\n",
406                fn->rtype, fn->fname, fn->params);
407       if (macro_protect)
408         fprintf (outf, "#endif\n");
409     }
410   if (required_unseen_count)
411     fprintf (outf,
412              "#endif /* defined(__cplusplus) */\n");
413
414   switch (special_file_handling)
415     {
416     case errno_special:
417       if (missing_errno)
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
443 #if 0
444   if (missing_extern_C_count + required_unseen_count > 0)
445     fprintf (outf, "#ifdef __cplusplus\n}\n#endif\n");
446 #endif
447 }
448
449 char *
450 strdup (str)
451      char *str;
452 {
453   char *copy = (char *) xmalloc (strlen (str) + 1);
454   strcpy (copy, str);
455   return copy;
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
465 #define INF_GET() (inf_ptr < inf_limit ? *(unsigned char*)inf_ptr++ : EOF)
466 #define INF_UNGET(c) ((c)!=EOF && inf_ptr--)
467
468 int
469 inf_skip_spaces (c)
470      int c;
471 {
472   for (;;)
473     {
474       if (c == ' ' || c == '\t')
475         c = INF_GET ();
476       else if (c == '/')
477         {
478           c = INF_GET ();
479           if (c != '*')
480             {
481               INF_UNGET (c);
482               return '/';
483             }
484           c = INF_GET ();
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                 }
495               else if ((c = INF_GET ()) == '/')
496                 return INF_GET ();
497             }
498         }
499       else
500         break;
501     }
502   return c;
503 }
504
505 /* Read into STR from inf_buffer upto DELIM. */
506
507 int
508 inf_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;
518       SSTRING_PUT (str, ch);
519     }
520   MAKE_SSTRING_SPACE (str, 1);
521   *str->ptr = 0;
522   return ch;
523 }
524
525 int
526 inf_scan_ident (s, c)
527      register sstring *s;
528      int c;
529 {
530   s->ptr = s->base;
531   if (isalpha (c) || c == '_')
532     {
533       for (;;)
534         {
535           SSTRING_PUT (s, c);
536           c = INF_GET ();
537           if (c == EOF || !(isalnum (c) || c == '_'))
538             break;
539         }
540     }
541   MAKE_SSTRING_SPACE (s, 1);
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
551 int
552 check_protection (ifndef_line, endif_line)
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     {
563       c = inf_skip_spaces (' ');
564       if (c == EOF)
565         return 0;
566       if (c != '\n')
567         break;
568     }
569   if (c != '#')
570     return 0;
571   c = inf_scan_ident (&buf, inf_skip_spaces (' '));
572   if (SSTRING_LENGTH (&buf) == 0 || strcmp (buf.base, "ifndef") != 0)
573     return 0;
574
575   /* So far so good: We've seen an initial #ifndef. */
576   *ifndef_line = lineno;
577   c = inf_scan_ident (&buf, inf_skip_spaces (c));
578   if (SSTRING_LENGTH (&buf) == 0 || c == EOF)
579     return 0;
580   protect_name = strdup (buf.base);
581
582   INF_UNGET (c);
583   c = inf_read_upto (&buf, '\n');
584   if (c == EOF)
585     return 0;
586   lineno++;
587
588   for (;;)
589     {
590       c = inf_skip_spaces (' ');
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;
600       c = inf_scan_ident (&buf, inf_skip_spaces (' '));
601       if (SSTRING_LENGTH (&buf) == 0)
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;
623           c = inf_skip_spaces (c);
624           c = inf_scan_ident (&buf, c);
625           if (buf.base[0] > 0 && strcmp (buf.base, protect_name) == 0)
626             define_seen = 1;
627         }
628     skip_to_eol:
629       for (;;)
630         {
631           if (c == '\n' || c == EOF)
632             break;
633           c = INF_GET ();
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     {
646       c = inf_skip_spaces (' ');
647       if (c == EOF)
648         break;
649       if (c != '\n')
650         return 0;
651     }
652
653   return 1;
654 }
655
656 int
657 main (argc, argv)
658      int argc;
659      char **argv;
660 {
661   int inf_fd;
662   struct stat sbuf;
663   int c;
664   int i, done;
665   char *cptr, *cptr0, **pptr;
666   int ifndef_line;
667   int endif_line;
668   long to_read;
669   long int inf_size;
670
671   if (argv[0] && argv[0][0])
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     }
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)
694     special_file_handling = errno_special, missing_errno = 1;
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. */ 
700   required_functions = (char**)xmalloc ((i+1) * sizeof (char*));
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             {
710               struct fn_decl *fn = lookup_std_proto (cptr0);
711               *pptr++ = cptr0;
712               if (fn == NULL)
713                 fprintf (stderr, "Internal error:  No prototype for %s\n",
714                          cptr0);
715               else
716                 SET_REQUIRED (fn);
717             }
718           cptr0 = cptr + 1;
719         }
720     }
721   required_unseen_count = pptr - required_functions;
722   *pptr = 0;
723
724   read_scan_file (stdin);
725
726   inf_fd = open (argv[2], O_RDONLY, 0666);
727   if (inf_fd < 0)
728     {
729       fprintf (stderr, "%s: Cannot open '%s' for reading -",
730                progname, argv[2]);
731       perror (NULL);
732       exit (-1);
733     }
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);
766
767   /* If file doesn't end with '\n', add one. */
768   if (inf_limit > inf_buffer && inf_limit[-1] != '\n')
769     inf_limit++;
770
771   unlink (argv[3]);
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
781   lineno = 1;
782
783   if (check_protection (&ifndef_line, &endif_line))
784     {
785 #if 0
786       fprintf (stderr, "#ifndef %s on line %d; #endif on line %d\n",
787                protect_name, ifndef_line, endif_line);
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
798   /* Reset input file. */
799   inf_ptr = inf_buffer;
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;
811           c = INF_GET ();
812           if (c == EOF)
813             break;
814           if (isalpha (c) || c == '_')
815             {
816               c = inf_scan_ident (&buf, c);
817               INF_UNGET (c);
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                 {
825                   c = inf_skip_spaces (' ');
826                   if (c == EOF)
827                     break;
828                   if (c == '(')
829                     {
830                       c = inf_skip_spaces (' ');
831                       if (c == ')')
832                         {
833                           fprintf (outf, " _PARAMS((%s))", fn->params);
834                         }
835                       else
836                         {
837                           putc ('(', outf);
838                           INF_UNGET (c);
839                         }
840                     }
841                   else
842                     fprintf (outf, " %c", c);
843                 }
844             }
845           else
846             {
847               putc (c, outf);
848               if (c == '\n')
849                 break;
850             }
851         }
852       if (c == EOF)
853         break;
854       lineno++;
855     }
856   if (rbrac_line < 0)
857     write_rbrac ();
858
859   fclose (outf);
860
861   return 0;
862 }