]> git.saurik.com Git - bison.git/blob - src/files.c
37a9bb27e66aa3365e56c676d9b40a059c3fb73f
[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
24 #if defined (VMS) & !defined (__VMS_POSIX)
25 # include <ssdef.h>
26 # define unlink delete
27 # ifndef XPFILE
28 # define XPFILE "GNU_BISON:[000000]BISON.SIMPLE"
29 # endif
30 # ifndef XPFILE1
31 # define XPFILE1 "GNU_BISON:[000000]BISON.HAIRY"
32 # endif
33 #endif
34
35 #if defined (_MSC_VER)
36 # ifndef XPFILE
37 # define XPFILE "c:/usr/local/lib/bison.simple"
38 # endif
39 # ifndef XPFILE1
40 # define XPFILE1 "c:/usr/local/lib/bison.hairy"
41 # endif
42 #endif
43
44 #include "getargs.h"
45 #include "files.h"
46 #include "xalloc.h"
47 #include "gram.h"
48 #include "complain.h"
49
50 FILE *finput = NULL;
51 FILE *foutput = NULL;
52 FILE *fguard = NULL;
53 FILE *fparser = NULL;
54
55 struct obstack action_obstack;
56 struct obstack attrs_obstack;
57 struct obstack table_obstack;
58 struct obstack defines_obstack;
59
60 /* File name specified with -o for the output file, or 0 if no -o. */
61 char *spec_outfile;
62
63 char *infile;
64 char *attrsfile;
65
66 static char *outfile;
67 static char *defsfile;
68 static char *tabfile;
69 static char *guardfile;
70 static char *actfile;
71
72 extern char *getenv ();
73
74 extern char *program_name;
75 \f
76
77 static char *
78 stringappend (const char *string1, int end1, const char *string2)
79 {
80 register char *ostring;
81 register char *cp;
82 register const char *cp1;
83 register int i;
84
85 cp1 = string2;
86 i = 0;
87 while (*cp1++)
88 i++;
89
90 ostring = XCALLOC (char, i + end1 + 1);
91
92 cp = ostring;
93 cp1 = string1;
94 for (i = 0; i < end1; i++)
95 *cp++ = *cp1++;
96
97 cp1 = string2;
98 while ((*cp++ = *cp1++))
99 ;
100
101 return ostring;
102 }
103
104 /*-----------------------------------------------------------------.
105 | Try to open file NAME with mode MODE, and print an error message |
106 | if fails. |
107 `-----------------------------------------------------------------*/
108
109 static FILE *
110 xfopen (const char *name, const char *mode)
111 {
112 FILE *ptr;
113
114 ptr = fopen (name, mode);
115 if (!ptr)
116 error (2, errno, _("cannot open file `%s'"), name);
117
118 return ptr;
119 }
120
121 /*-------------------------------------------------------------.
122 | Try to close file PTR, and print an error message if fails. |
123 `-------------------------------------------------------------*/
124
125 static int
126 xfclose (FILE *ptr)
127 {
128 int result;
129
130 if (ptr == NULL)
131 return 0;
132
133 result = fclose (ptr);
134 if (result == EOF)
135 error (2, errno, _("cannot close file"));
136
137 return result;
138 }
139
140 /*--------------------------------------------------.
141 | Save the content of the obstack OBS in FILENAME. |
142 `--------------------------------------------------*/
143
144 static void
145 obstack_save (struct obstack *obs, const char *filename)
146 {
147 FILE *out = xfopen (filename, "w");
148 size_t size = obstack_object_size (obs);
149 fwrite (obstack_finish (obs), 1, size, out);
150 xfclose (out);
151 }
152
153
154 static const char *
155 skeleton_find (const char *envvar, const char *skeleton)
156 {
157 const char *res = getenv (envvar);
158
159 #ifdef MSDOS
160 const char *cp;
161
162 /* File doesn't exist in current directory; try in INIT directory. */
163 if (!res && (cp = getenv ("INIT")))
164 {
165 res = XMALLOC (char, strlen (cp) + strlen (skeleton) + 2);
166 sprintf (res, "%s%c%s", cp, '/', skeleton);
167 }
168 #endif /* !MSDOS */
169
170 if (!res)
171 res = skeleton;
172
173 return res;
174 }
175
176 \f
177 /*-----------------------------------------------------------------.
178 | Open the input file. Look for the skeletons. Find the names of |
179 | the output files. Prepare the obstacks. |
180 `-----------------------------------------------------------------*/
181
182 void
183 open_files (void)
184 {
185 char *name_base;
186 #ifdef MSDOS
187 register char *cp;
188 #endif
189 int base_length;
190 int short_base_length;
191
192 #if defined (VMS) & !defined (__VMS_POSIX)
193 const char *tmp_base = "sys$scratch:b_";
194 #else
195 const char *tmp_base = "/tmp/b.";
196 #endif
197 int tmp_len;
198
199 #ifdef MSDOS
200 tmp_base = getenv ("TMP");
201 if (tmp_base == 0)
202 tmp_base = "";
203 strlwr (infile);
204 #endif /* MSDOS */
205
206 #if (defined(_WIN32) && !defined(__CYGWIN32__))
207 tmp_base = getenv ("TEMP"); /* Windows95 defines this ... */
208 if (tmp_base == 0)
209 tmp_base = getenv ("Temp"); /* ... while NT prefers this */
210 if (tmp_base == 0)
211 tmp_base = "";
212 strlwr (infile);
213 #endif /* _WIN32 && !__CYGWIN32__ */
214
215 #if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__EMX__))
216 {
217 char *tmp_ptr = getenv ("TMPDIR");
218
219 if (tmp_ptr != 0)
220 tmp_base = stringappend (tmp_ptr, strlen (tmp_ptr), "/b.");
221 }
222 #endif /* unix || __unix || __unix__ */
223
224 tmp_len = strlen (tmp_base);
225
226 if (spec_outfile)
227 {
228 /* -o was specified. The precise -o name will be used for FTABLE.
229 For other output files, remove the ".c" or ".tab.c" suffix. */
230 name_base = spec_outfile;
231 #ifdef MSDOS
232 strlwr (name_base);
233 #endif /* MSDOS */
234 /* BASE_LENGTH includes ".tab" but not ".c". */
235 base_length = strlen (name_base);
236 if (!strcmp (name_base + base_length - 2, ".c"))
237 base_length -= 2;
238 /* SHORT_BASE_LENGTH includes neither ".tab" nor ".c". */
239 short_base_length = base_length;
240 if (!strncmp (name_base + short_base_length - 4, ".tab", 4))
241 short_base_length -= 4;
242 else if (!strncmp (name_base + short_base_length - 4, "_tab", 4))
243 short_base_length -= 4;
244 }
245 else if (spec_file_prefix)
246 {
247 /* -b was specified. Construct names from it. */
248 /* SHORT_BASE_LENGTH includes neither ".tab" nor ".c". */
249 short_base_length = strlen (spec_file_prefix);
250 /* Count room for `.tab'. */
251 base_length = short_base_length + 4;
252 name_base = XMALLOC (char, base_length + 1);
253 /* Append `.tab'. */
254 strcpy (name_base, spec_file_prefix);
255 #ifdef VMS
256 strcat (name_base, "_tab");
257 #else
258 strcat (name_base, ".tab");
259 #endif
260 #ifdef MSDOS
261 strlwr (name_base);
262 #endif /* MSDOS */
263 }
264 else
265 {
266 /* -o was not specified; compute output file name from input
267 or use y.tab.c, etc., if -y was specified. */
268
269 static char FIXED_NAME_BASE[] = "y.y";
270
271 name_base = yacc_flag ? FIXED_NAME_BASE : infile;
272
273 /* BASE_LENGTH gets length of NAME_BASE, sans ".y" suffix if any. */
274
275 base_length = strlen (name_base);
276 if (!strcmp (name_base + base_length - 2, ".y"))
277 base_length -= 2;
278 short_base_length = base_length;
279
280 #ifdef VMS
281 name_base = stringappend (name_base, short_base_length, "_tab");
282 #else
283 #ifdef MSDOS
284 name_base = stringappend (name_base, short_base_length, "_tab");
285 #else
286 name_base = stringappend (name_base, short_base_length, ".tab");
287 #endif /* not MSDOS */
288 #endif
289 base_length = short_base_length + 4;
290 }
291
292 finput = xfopen (infile, "r");
293
294 if (!no_parser_flag)
295 fparser = xfopen (skeleton_find ("BISON_SIMPLE", PFILE), "r");
296
297 if (verbose_flag)
298 {
299 #ifdef MSDOS
300 outfile = stringappend (name_base, short_base_length, ".out");
301 #else
302 /* We used to use just .out if spec_name_prefix (-p) was used,
303 but that conflicts with Posix. */
304 outfile = stringappend (name_base, short_base_length, ".output");
305 #endif
306 foutput = xfopen (outfile, "w");
307 }
308
309 if (no_parser_flag)
310 {
311 /* use permanent name for actions file */
312 actfile = stringappend (name_base, short_base_length, ".act");
313 }
314
315 if (defines_flag)
316 {
317 defsfile = stringappend (name_base, base_length, ".h");
318 }
319
320 /* These are opened by `done' or `open_extra_files', if at all */
321 if (spec_outfile)
322 tabfile = spec_outfile;
323 else
324 tabfile = stringappend (name_base, base_length, ".c");
325
326 #ifdef VMS
327 attrsfile = stringappend (name_base, short_base_length, "_stype.h");
328 guardfile = stringappend (name_base, short_base_length, "_guard.c");
329 #else
330 #ifdef MSDOS
331 attrsfile = stringappend (name_base, short_base_length, ".sth");
332 guardfile = stringappend (name_base, short_base_length, ".guc");
333 #else
334 attrsfile = stringappend (name_base, short_base_length, ".stype.h");
335 guardfile = stringappend (name_base, short_base_length, ".guard.c");
336 #endif /* not MSDOS */
337 #endif /* not VMS */
338
339 /* Initialize the obstacks. */
340 obstack_init (&action_obstack);
341 obstack_init (&attrs_obstack);
342 obstack_init (&table_obstack);
343 obstack_init (&defines_obstack);
344 }
345
346
347
348 /*--------------------------------------------------------------------.
349 | Open the output files needed only for the semantic parser. This |
350 | is done when %semantic_parser is seen in the declarations section. |
351 `--------------------------------------------------------------------*/
352
353 void
354 open_extra_files (void)
355 {
356 xfclose (fparser);
357
358 if (!no_parser_flag)
359 fparser = xfopen (skeleton_find ("BISON_HAIRY", PFILE1), "r");
360 fguard = xfopen (guardfile, "w");
361 }
362
363
364 /*-----------------------------------------------------.
365 | Close the open files, produce all the output files. |
366 `-----------------------------------------------------*/
367
368 void
369 output_files (void)
370 {
371 xfclose (fguard);
372 xfclose (finput);
373 xfclose (fparser);
374 xfclose (foutput);
375
376 /* Output the main file. */
377 obstack_save (&table_obstack, tabfile);
378
379 /* Output the header file if wanted. */
380 if (defines_flag)
381 obstack_save (&defines_obstack, defsfile);
382
383 /* If we output only the table, dump the actions in ACTFILE.
384 */
385 if (no_parser_flag)
386 obstack_save (&action_obstack, actfile);
387
388 /* If we produced a semantic parser ATTRS_OBSTACK must be dumped
389 into its own file, ATTTRSFILE. */
390 if (semantic_parser)
391 obstack_save (&attrs_obstack, attrsfile);
392 }