1cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project/* Open and close files for Bison.
2cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Copyright (C) 1984, 1986, 1989, 1992, 2000-2012 Free Software
405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Foundation, Inc.
5cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
6cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   This file is part of Bison, the GNU Compiler Compiler.
7cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
805436638acc7c010349a69c3395f1a57c642dc62Ying Wang   This program is free software: you can redistribute it and/or modify
905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   it under the terms of the GNU General Public License as published by
1005436638acc7c010349a69c3395f1a57c642dc62Ying Wang   the Free Software Foundation, either version 3 of the License, or
1105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   (at your option) any later version.
12cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
1305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   This program is distributed in the hope that it will be useful,
1405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   but WITHOUT ANY WARRANTY; without even the implied warranty of
1505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   GNU General Public License for more details.
17cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
18cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   You should have received a copy of the GNU General Public License
1905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
21cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#include <config.h>
22cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#include "system.h"
23cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
24cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#include <error.h>
2505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <dirname.h>
26cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#include <get-errno.h>
27cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#include <quote.h>
2805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <quotearg.h>
2905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <stdio-safer.h>
30cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#include <xstrndup.h>
31cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
32cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#include "complain.h"
33cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#include "files.h"
34cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#include "getargs.h"
35cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#include "gram.h"
36cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
37cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project/* Initializing some values below (such SPEC_NAME_PREFIX to `yy') is
38cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   tempting, but don't do that: for the time being our handling of the
39cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   %directive vs --option leaves precedence to the options by deciding
40cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   that if a %directive sets a variable which is really set (i.e., not
41cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   NULL), then the %directive is ignored.  As a result, %name-prefix,
42cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   for instance, will not be honored.  */
43cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
44cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Projectchar const *spec_outfile = NULL;       /* for -o. */
45cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Projectchar const *spec_file_prefix = NULL;   /* for -b. */
46cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Projectchar const *spec_name_prefix = NULL;   /* for -p. */
4705436638acc7c010349a69c3395f1a57c642dc62Ying Wangchar *spec_verbose_file = NULL;  /* for --verbose. */
4805436638acc7c010349a69c3395f1a57c642dc62Ying Wangchar *spec_graph_file = NULL;    /* for -g. */
4905436638acc7c010349a69c3395f1a57c642dc62Ying Wangchar *spec_xml_file = NULL;      /* for -x. */
5005436638acc7c010349a69c3395f1a57c642dc62Ying Wangchar *spec_defines_file = NULL;  /* for --defines. */
5105436638acc7c010349a69c3395f1a57c642dc62Ying Wangchar *parser_file_name;
5205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
5305436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* All computed output file names.  */
5405436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic char **file_names = NULL;
5505436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic int file_names_count = 0;
56cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
57cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Projectuniqstr grammar_file = NULL;
58cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Projectuniqstr current_file = NULL;
59cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
60cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project/* If --output=dir/foo.c was specified,
61cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   DIR_PREFIX is `dir/' and ALL_BUT_EXT and ALL_BUT_TAB_EXT are `dir/foo'.
62cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
63cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   If --output=dir/foo.tab.c was specified, DIR_PREFIX is `dir/',
64cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   ALL_BUT_EXT is `dir/foo.tab', and ALL_BUT_TAB_EXT is `dir/foo'.
65cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
66cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   If --output was not specified but --file-prefix=dir/foo was specified,
67cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   ALL_BUT_EXT = `foo.tab' and ALL_BUT_TAB_EXT = `foo'.
68cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
69cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   If neither --output nor --file was specified but the input grammar
70cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   is name dir/foo.y, ALL_BUT_EXT and ALL_BUT_TAB_EXT are `foo'.
71cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
72cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   If neither --output nor --file was specified, DIR_PREFIX is the
73cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   empty string (meaning the current directory); otherwise it is
74cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   `dir/'.  */
75cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
7605436638acc7c010349a69c3395f1a57c642dc62Ying Wangchar *all_but_ext;
7705436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic char *all_but_tab_ext;
7805436638acc7c010349a69c3395f1a57c642dc62Ying Wangchar *dir_prefix;
79cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
80cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project/* C source file extension (the parser source).  */
8105436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic char *src_extension = NULL;
82cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project/* Header file extension (if option ``-d'' is specified).  */
8305436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic char *header_extension = NULL;
84cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
85cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project/*-----------------------------------------------------------------.
86cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project| Return a newly allocated string composed of the concatenation of |
87cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project| STR1, and STR2.                                                  |
88cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project`-----------------------------------------------------------------*/
89cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
90cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Projectstatic char *
91cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Projectconcat2 (char const *str1, char const *str2)
92cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project{
93cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  size_t len = strlen (str1) + strlen (str2);
94cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  char *res = xmalloc (len + 1);
95cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  char *cp;
96cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  cp = stpcpy (res, str1);
97cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  cp = stpcpy (cp, str2);
98cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  return res;
99cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project}
100cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
101cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project/*-----------------------------------------------------------------.
102cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project| Try to open file NAME with mode MODE, and print an error message |
103cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project| if fails.                                                        |
104cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project`-----------------------------------------------------------------*/
105cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
106cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source ProjectFILE *
107cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Projectxfopen (const char *name, const char *mode)
108cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project{
109cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  FILE *ptr;
110cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
111cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  ptr = fopen_safer (name, mode);
112cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  if (!ptr)
11305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    error (EXIT_FAILURE, get_errno (),
11405436638acc7c010349a69c3395f1a57c642dc62Ying Wang           _("%s: cannot open"), quotearg_colon (name));
115cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
116cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  return ptr;
117cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project}
118cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
119cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project/*-------------------------------------------------------------.
120cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project| Try to close file PTR, and print an error message if fails.  |
121cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project`-------------------------------------------------------------*/
122cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
123cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Projectvoid
124cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Projectxfclose (FILE *ptr)
125cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project{
126cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  if (ptr == NULL)
127cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project    return;
128cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
129cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  if (ferror (ptr))
13005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    error (EXIT_FAILURE, 0, _("input/output error"));
131cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
132cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  if (fclose (ptr) != 0)
133cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project    error (EXIT_FAILURE, get_errno (), _("cannot close file"));
134cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project}
135cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
136cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
137cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project/*------------------------------------------------------------------.
138cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project| Compute ALL_BUT_EXT, ALL_BUT_TAB_EXT and output files extensions. |
139cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project`------------------------------------------------------------------*/
140cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
141cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project/* Compute extensions from the grammar file extension.  */
142cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Projectstatic void
143cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Projectcompute_exts_from_gf (const char *ext)
144cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project{
14505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (strcmp (ext, ".y") == 0)
14605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
14705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      src_extension = xstrdup (language->src_extension);
14805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      header_extension = xstrdup (language->header_extension);
14905436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
15005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  else
15105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
15205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      src_extension = xstrdup (ext);
15305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      header_extension = xstrdup (ext);
15405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      tr (src_extension, 'y', 'c');
15505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      tr (src_extension, 'Y', 'C');
15605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      tr (header_extension, 'y', 'h');
15705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      tr (header_extension, 'Y', 'H');
15805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
159cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project}
160cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
161cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project/* Compute extensions from the given c source file extension.  */
162cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Projectstatic void
163cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Projectcompute_exts_from_src (const char *ext)
164cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project{
165cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  /* We use this function when the user specifies `-o' or `--output',
166cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project     so the extenions must be computed unconditionally from the file name
167cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project     given by this option.  */
168cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  src_extension = xstrdup (ext);
16905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  header_extension = xstrdup (ext);
17005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  tr (header_extension, 'c', 'h');
17105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  tr (header_extension, 'C', 'H');
172cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project}
173cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
174cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
175cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project/* Decompose FILE_NAME in four parts: *BASE, *TAB, and *EXT, the fourth
176cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   part, (the directory) is ranging from FILE_NAME to the char before
177cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   *BASE, so we don't need an additional parameter.
178cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
179cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   *EXT points to the last period in the basename, or NULL if none.
180cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
181cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   If there is no *EXT, *TAB is NULL.  Otherwise, *TAB points to
182cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   `.tab' or `_tab' if present right before *EXT, or is NULL. *TAB
183cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   cannot be equal to *BASE.
184cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
185cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   None are allocated, they are simply pointers to parts of FILE_NAME.
186cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   Examples:
187cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
188cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   '/tmp/foo.tab.c' -> *BASE = 'foo.tab.c', *TAB = '.tab.c', *EXT =
189cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   '.c'
190cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
191cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   'foo.c' -> *BASE = 'foo.c', *TAB = NULL, *EXT = '.c'
192cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
193cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   'tab.c' -> *BASE = 'tab.c', *TAB = NULL, *EXT = '.c'
194cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
195cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   '.tab.c' -> *BASE = '.tab.c', *TAB = NULL, *EXT = '.c'
196cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
197cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   'foo.tab' -> *BASE = 'foo.tab', *TAB = NULL, *EXT = '.tab'
198cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
199cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   'foo_tab' -> *BASE = 'foo_tab', *TAB = NULL, *EXT = NULL
200cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
201cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   'foo' -> *BASE = 'foo', *TAB = NULL, *EXT = NULL.  */
202cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
203cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Projectstatic void
204cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Projectfile_name_split (const char *file_name,
205cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project		 const char **base, const char **tab, const char **ext)
206cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project{
20705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  *base = last_component (file_name);
208cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
209cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  /* Look for the extension, i.e., look for the last dot. */
21005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  *ext = mbsrchr (*base, '.');
211cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  *tab = NULL;
212cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
213cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  /* If there is an extension, check if there is a `.tab' part right
214cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project     before.  */
215cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  if (*ext)
216cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project    {
217cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project      size_t baselen = *ext - *base;
218cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project      size_t dottablen = 4;
219cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project      if (dottablen < baselen
220cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project	  && (strncmp (*ext - dottablen, ".tab", dottablen) == 0
221cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project	      || strncmp (*ext - dottablen, "_tab", dottablen) == 0))
222cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project	*tab = *ext - dottablen;
223cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project    }
224cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project}
225cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
226cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
227cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Projectstatic void
228cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Projectcompute_file_name_parts (void)
229cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project{
230cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  const char *base, *tab, *ext;
231cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
232cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  /* Compute ALL_BUT_EXT and ALL_BUT_TAB_EXT from SPEC_OUTFILE
233cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project     or GRAMMAR_FILE.
234cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
235cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project     The precise -o name will be used for FTABLE.  For other output
236cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project     files, remove the ".c" or ".tab.c" suffix.  */
237cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  if (spec_outfile)
238cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project    {
239cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project      file_name_split (spec_outfile, &base, &tab, &ext);
240cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project      dir_prefix = xstrndup (spec_outfile, base - spec_outfile);
241cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
242cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project      /* ALL_BUT_EXT goes up the EXT, excluding it. */
243cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project      all_but_ext =
244cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project	xstrndup (spec_outfile,
245cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project		  (strlen (spec_outfile) - (ext ? strlen (ext) : 0)));
246cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
247cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project      /* ALL_BUT_TAB_EXT goes up to TAB, excluding it.  */
248cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project      all_but_tab_ext =
249cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project	xstrndup (spec_outfile,
250cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project		  (strlen (spec_outfile)
251cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project		   - (tab ? strlen (tab) : (ext ? strlen (ext) : 0))));
252cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
253cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project      if (ext)
254cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project	compute_exts_from_src (ext);
255cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project    }
256cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  else
257cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project    {
258cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project      file_name_split (grammar_file, &base, &tab, &ext);
259cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
260cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project      if (spec_file_prefix)
261cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project	{
262cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project	  /* If --file-prefix=foo was specified, ALL_BUT_TAB_EXT = `foo'.  */
26305436638acc7c010349a69c3395f1a57c642dc62Ying Wang	  dir_prefix =
26405436638acc7c010349a69c3395f1a57c642dc62Ying Wang            xstrndup (spec_file_prefix,
26505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      last_component (spec_file_prefix) - spec_file_prefix);
266cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project	  all_but_tab_ext = xstrdup (spec_file_prefix);
267cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project	}
268cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project      else if (yacc_flag)
269cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project	{
270cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project	  /* If --yacc, then the output is `y.tab.c'.  */
27105436638acc7c010349a69c3395f1a57c642dc62Ying Wang	  dir_prefix = xstrdup ("");
27205436638acc7c010349a69c3395f1a57c642dc62Ying Wang	  all_but_tab_ext = xstrdup ("y");
273cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project	}
274cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project      else
275cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project	{
276cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project	  /* Otherwise, ALL_BUT_TAB_EXT is computed from the input
277cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project	     grammar: `foo/bar.yy' => `bar'.  */
27805436638acc7c010349a69c3395f1a57c642dc62Ying Wang	  dir_prefix = xstrdup ("");
279cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project	  all_but_tab_ext =
280cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project	    xstrndup (base, (strlen (base) - (ext ? strlen (ext) : 0)));
281cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project	}
282cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
28305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (language->add_tab)
28405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        all_but_ext = concat2 (all_but_tab_ext, TAB_EXT);
28505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
28605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        all_but_ext = xstrdup (all_but_tab_ext);
287cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
288cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project      /* Compute the extensions from the grammar file name.  */
289cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project      if (ext && !yacc_flag)
290cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project	compute_exts_from_gf (ext);
291cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project    }
292cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project}
293cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
294cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
295cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project/* Compute the output file names.  Warn if we detect conflicting
296cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project   outputs to the same file.  */
297cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
298cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Projectvoid
299cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Projectcompute_output_file_names (void)
300cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project{
301cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  compute_file_name_parts ();
302cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
303cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  /* If not yet done. */
304cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  if (!src_extension)
30505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    src_extension = xstrdup (".c");
306cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  if (!header_extension)
30705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    header_extension = xstrdup (".h");
308cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
30905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  parser_file_name =
31005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    (spec_outfile
31105436638acc7c010349a69c3395f1a57c642dc62Ying Wang     ? xstrdup (spec_outfile)
31205436638acc7c010349a69c3395f1a57c642dc62Ying Wang     : concat2 (all_but_ext, src_extension));
313cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
314cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  if (defines_flag)
315cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project    {
316cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project      if (! spec_defines_file)
317cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project	spec_defines_file = concat2 (all_but_ext, header_extension);
318cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project    }
319cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
320cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  if (graph_flag)
321cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project    {
322cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project      if (! spec_graph_file)
32305436638acc7c010349a69c3395f1a57c642dc62Ying Wang	spec_graph_file = concat2 (all_but_tab_ext, ".dot");
32405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      output_file_name_check (&spec_graph_file);
32505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
32605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
32705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (xml_flag)
32805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
32905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (! spec_xml_file)
33005436638acc7c010349a69c3395f1a57c642dc62Ying Wang	spec_xml_file = concat2 (all_but_tab_ext, ".xml");
33105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      output_file_name_check (&spec_xml_file);
332cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project    }
333cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
334cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project  if (report_flag)
335cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project    {
33605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (!spec_verbose_file)
33705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        spec_verbose_file = concat2 (all_but_tab_ext, OUTPUT_EXT);
33805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      output_file_name_check (&spec_verbose_file);
33905436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
34005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
34105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  free (all_but_tab_ext);
34205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  free (src_extension);
34305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  free (header_extension);
34405436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
34505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
34605436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid
34705436638acc7c010349a69c3395f1a57c642dc62Ying Wangoutput_file_name_check (char **file_name)
34805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
34905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  bool conflict = false;
35005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (0 == strcmp (*file_name, grammar_file))
35105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
35205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      complain (_("refusing to overwrite the input file %s"),
35305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                quote (*file_name));
35405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      conflict = true;
35505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
35605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  else
35705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
35805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      int i;
35905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      for (i = 0; i < file_names_count; i++)
36005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (0 == strcmp (file_names[i], *file_name))
36105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          {
36205436638acc7c010349a69c3395f1a57c642dc62Ying Wang            warn (_("conflicting outputs to file %s"),
36305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  quote (*file_name));
36405436638acc7c010349a69c3395f1a57c642dc62Ying Wang            conflict = true;
36505436638acc7c010349a69c3395f1a57c642dc62Ying Wang          }
366cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project    }
36705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (conflict)
36805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
36905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      free (*file_name);
37005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      *file_name = strdup ("/dev/null");
37105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
37205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  else
37305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
37405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      file_names = xnrealloc (file_names, ++file_names_count,
37505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              sizeof *file_names);
37605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      file_names[file_names_count-1] = xstrdup (*file_name);
37705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
37805436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
379cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project
38005436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid
38105436638acc7c010349a69c3395f1a57c642dc62Ying Wangoutput_file_names_free (void)
38205436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
38305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  free (all_but_ext);
38405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  free (spec_verbose_file);
38505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  free (spec_graph_file);
38605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  free (spec_xml_file);
38705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  free (spec_defines_file);
38805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  free (parser_file_name);
38905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  free (dir_prefix);
39005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  {
39105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    int i;
39205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    for (i = 0; i < file_names_count; i++)
39305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      free (file_names[i]);
39405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  }
39505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  free (file_names);
396cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project}
397