]> git.saurik.com Git - bison.git/blob - src/files.c
f2ac8582d4c2f84ede0d965c49e8a5f91cc9c57f
[bison.git] / src / files.c
1 /* Open and close files for bison,
2 Copyright 1984, 1986, 1989, 1992, 2000 Free Software Foundation, Inc.
3
4 This file is part of Bison, the GNU Compiler Compiler.
5
6 Bison is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 Bison is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Bison; see the file COPYING. If not, write to the Free
18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
20
21
22 #include "system.h"
23 #include "getargs.h"
24 #include "files.h"
25 #include "xalloc.h"
26 #include "gram.h"
27 #include "complain.h"
28
29 FILE *finput = NULL;
30 FILE *foutput = NULL;
31 FILE *fguard = NULL;
32
33 struct obstack action_obstack;
34 struct obstack attrs_obstack;
35 struct obstack table_obstack;
36 struct obstack defines_obstack;
37
38 /* File name specified with -o for the output file, or 0 if no -o. */
39 char *spec_outfile;
40
41 char *infile;
42 char *attrsfile;
43 char *guardfile;
44
45 static char *outfile;
46 static char *defsfile;
47 static char *tabfile;
48 static char *actfile;
49 \f
50 /*-----------------------------------------------------------------.
51 | Return a newly allocated string composed of the concatenation of |
52 | the END1 first chars of STRING1, and STRING2. |
53 `-----------------------------------------------------------------*/
54
55 static char *
56 stringappend (const char *string1, int end1, const char *string2)
57 {
58 char *res;
59 char *cp;
60 const char *cp1;
61 int i;
62
63 cp1 = string2;
64 i = 0;
65 while (*cp1++)
66 i++;
67
68 res = XCALLOC (char, i + end1 + 1);
69
70 cp = res;
71 cp1 = string1;
72 for (i = 0; i < end1; i++)
73 *cp++ = *cp1++;
74
75 cp1 = string2;
76 while ((*cp++ = *cp1++))
77 ;
78
79 return res;
80 }
81
82 /*-----------------------------------------------------------------.
83 | Try to open file NAME with mode MODE, and print an error message |
84 | if fails. |
85 `-----------------------------------------------------------------*/
86
87 FILE *
88 xfopen (const char *name, const char *mode)
89 {
90 FILE *ptr;
91
92 ptr = fopen (name, mode);
93 if (!ptr)
94 error (2, errno, _("cannot open file `%s'"), name);
95
96 return ptr;
97 }
98
99 /*-------------------------------------------------------------.
100 | Try to close file PTR, and print an error message if fails. |
101 `-------------------------------------------------------------*/
102
103 int
104 xfclose (FILE *ptr)
105 {
106 int result;
107
108 if (ptr == NULL)
109 return 0;
110
111 result = fclose (ptr);
112 if (result == EOF)
113 error (2, errno, _("cannot close file"));
114
115 return result;
116 }
117
118 /*--------------------------------------------------.
119 | Save the content of the obstack OBS in FILENAME. |
120 `--------------------------------------------------*/
121
122 static void
123 obstack_save (struct obstack *obs, const char *filename)
124 {
125 FILE *out = xfopen (filename, "w");
126 size_t size = obstack_object_size (obs);
127 fwrite (obstack_finish (obs), 1, size, out);
128 xfclose (out);
129 }
130
131
132 /*------------------------------------------------------------------.
133 | Return the path to the skeleton which locaction might be given in |
134 | ENVVAR, otherwise return SKELETON. |
135 `------------------------------------------------------------------*/
136
137 const char *
138 skeleton_find (const char *envvar, const char *skeleton)
139 {
140 const char *res = getenv (envvar);
141
142 #ifdef MSDOS
143 const char *cp;
144
145 /* File doesn't exist in current directory; try in INIT directory. */
146 if (!res && (cp = getenv ("INIT")))
147 {
148 res = XMALLOC (char, strlen (cp) + strlen (skeleton) + 2);
149 sprintf (res, "%s%c%s", cp, '/', skeleton);
150 }
151 #endif /* !MSDOS */
152
153 if (!res)
154 res = skeleton;
155
156 return res;
157 }
158
159 \f
160 /*-----------------------------------------------------------------.
161 | Open the input file. Look for the skeletons. Find the names of |
162 | the output files. Prepare the obstacks. |
163 `-----------------------------------------------------------------*/
164
165 void
166 open_files (void)
167 {
168 char *name_base;
169 int base_length;
170 int short_base_length;
171
172 if (spec_outfile)
173 {
174 /* -o was specified. The precise -o name will be used for FTABLE.
175 For other output files, remove the ".c" or ".tab.c" suffix. */
176 name_base = spec_outfile;
177 #ifdef MSDOS
178 strlwr (name_base);
179 #endif /* MSDOS */
180 /* BASE_LENGTH includes ".tab" but not ".c". */
181 base_length = strlen (name_base);
182 if (!strcmp (name_base + base_length - 2, ".c"))
183 base_length -= 2;
184 /* SHORT_BASE_LENGTH includes neither ".tab" nor ".c". */
185 short_base_length = base_length;
186 if (!strncmp (name_base + short_base_length - 4, ".tab", 4))
187 short_base_length -= 4;
188 else if (!strncmp (name_base + short_base_length - 4, "_tab", 4))
189 short_base_length -= 4;
190 }
191 else if (spec_file_prefix)
192 {
193 /* -b was specified. Construct names from it. */
194 /* SHORT_BASE_LENGTH includes neither ".tab" nor ".c". */
195 short_base_length = strlen (spec_file_prefix);
196 /* Count room for `.tab'. */
197 base_length = short_base_length + 4;
198 name_base = XMALLOC (char, base_length + 1);
199 /* Append `.tab'. */
200 strcpy (name_base, spec_file_prefix);
201 strcat (name_base, EXT_TAB);
202 #ifdef MSDOS
203 strlwr (name_base);
204 #endif /* MSDOS */
205 }
206 else
207 {
208 /* -o was not specified; compute output file name from input
209 or use y.tab.c, etc., if -y was specified. */
210
211 static char FIXED_NAME_BASE[] = "y.y";
212
213 name_base = yacc_flag ? FIXED_NAME_BASE : infile;
214
215 /* BASE_LENGTH gets length of NAME_BASE, sans ".y" suffix if any. */
216
217 base_length = strlen (name_base);
218 if (!strcmp (name_base + base_length - 2, ".y"))
219 base_length -= 2;
220 short_base_length = base_length;
221
222 name_base = stringappend (name_base, short_base_length, EXT_TAB);
223 base_length = short_base_length + 4;
224 }
225
226 finput = xfopen (infile, "r");
227
228 if (verbose_flag)
229 {
230 /* We used to use just .out if spec_name_prefix (-p) was used,
231 but that conflicts with Posix. */
232 outfile = stringappend (name_base, short_base_length, EXT_OUTPUT);
233 foutput = xfopen (outfile, "w");
234 }
235
236 if (no_parser_flag)
237 {
238 /* use permanent name for actions file */
239 actfile = stringappend (name_base, short_base_length, ".act");
240 }
241
242 if (defines_flag)
243 {
244 defsfile = stringappend (name_base, base_length, ".h");
245 }
246
247 /* These are opened by `done' or `open_extra_files', if at all */
248 if (spec_outfile)
249 tabfile = spec_outfile;
250 else
251 tabfile = stringappend (name_base, base_length, ".c");
252
253 attrsfile = stringappend (name_base, short_base_length, EXT_STYPE_H);
254 guardfile = stringappend (name_base, short_base_length, EXT_GUARD_C);
255
256 /* Initialize the obstacks. */
257 obstack_init (&action_obstack);
258 obstack_init (&attrs_obstack);
259 obstack_init (&table_obstack);
260 obstack_init (&defines_obstack);
261 }
262
263
264
265 /*-----------------------------------------------------.
266 | Close the open files, produce all the output files. |
267 `-----------------------------------------------------*/
268
269 void
270 output_files (void)
271 {
272 xfclose (fguard);
273 xfclose (finput);
274 xfclose (foutput);
275
276 /* Output the main file. */
277 obstack_save (&table_obstack, tabfile);
278
279 /* Output the header file if wanted. */
280 if (defines_flag)
281 obstack_save (&defines_obstack, defsfile);
282
283 /* If we output only the table, dump the actions in ACTFILE.
284 */
285 if (no_parser_flag)
286 obstack_save (&action_obstack, actfile);
287
288 /* If we produced a semantic parser ATTRS_OBSTACK must be dumped
289 into its own file, ATTTRSFILE. */
290 if (semantic_parser)
291 obstack_save (&attrs_obstack, attrsfile);
292 }