]> git.ipfire.org Git - thirdparty/bash.git/blame_incremental - mksyntax.c
Bash-4.3 patch 7
[thirdparty/bash.git] / mksyntax.c
... / ...
CommitLineData
1/*
2 * mksyntax.c - construct shell syntax table for fast char attribute lookup.
3 */
4
5/* Copyright (C) 2000-2009 Free Software Foundation, Inc.
6
7 This file is part of GNU Bash, the Bourne Again SHell.
8
9 Bash is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Bash is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Bash. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23#include "config.h"
24
25#include <stdio.h>
26#include "bashansi.h"
27#include "chartypes.h"
28#include <errno.h>
29
30#ifdef HAVE_UNISTD_H
31# include <unistd.h>
32#endif
33
34#include "syntax.h"
35
36extern int optind;
37extern char *optarg;
38
39#ifndef errno
40extern int errno;
41#endif
42
43#ifndef HAVE_STRERROR
44extern char *strerror();
45#endif
46
47struct wordflag {
48 int flag;
49 char *fstr;
50} wordflags[] = {
51 { CWORD, "CWORD" },
52 { CSHMETA, "CSHMETA" },
53 { CSHBRK, "CSHBRK" },
54 { CBACKQ, "CBACKQ" },
55 { CQUOTE, "CQUOTE" },
56 { CSPECL, "CSPECL" },
57 { CEXP, "CEXP" },
58 { CBSDQUOTE, "CBSDQUOTE" },
59 { CBSHDOC, "CBSHDOC" },
60 { CGLOB, "CGLOB" },
61 { CXGLOB, "CXGLOB" },
62 { CXQUOTE, "CXQUOTE" },
63 { CSPECVAR, "CSPECVAR" },
64 { CSUBSTOP, "CSUBSTOP" },
65 { CBLANK, "CBLANK" },
66};
67
68#define N_WFLAGS (sizeof (wordflags) / sizeof (wordflags[0]))
69#define SYNSIZE 256
70
71int lsyntax[SYNSIZE];
72int debug;
73char *progname;
74
75char preamble[] = "\
76/*\n\
77 * This file was generated by mksyntax. DO NOT EDIT.\n\
78 */\n\
79\n";
80
81char includes[] = "\
82#include \"config.h\"\n\
83#include \"stdc.h\"\n\
84#include \"syntax.h\"\n\n";
85
86static void
87usage()
88{
89 fprintf (stderr, "%s: usage: %s [-d] [-o filename]\n", progname, progname);
90 exit (2);
91}
92
93#ifdef INCLUDE_UNUSED
94static int
95getcflag (s)
96 char *s;
97{
98 int i;
99
100 for (i = 0; i < N_WFLAGS; i++)
101 if (strcmp (s, wordflags[i].fstr) == 0)
102 return wordflags[i].flag;
103 return -1;
104}
105#endif
106
107static char *
108cdesc (i)
109 int i;
110{
111 static char xbuf[16];
112
113 if (i == ' ')
114 return "SPC";
115 else if (ISPRINT (i))
116 {
117 xbuf[0] = i;
118 xbuf[1] = '\0';
119 return (xbuf);
120 }
121 else if (i == CTLESC)
122 return "CTLESC";
123 else if (i == CTLNUL)
124 return "CTLNUL";
125 else if (i == '\033') /* ASCII */
126 return "ESC";
127
128 xbuf[0] = '\\';
129 xbuf[2] = '\0';
130
131 switch (i)
132 {
133#ifdef __STDC__
134 case '\a': xbuf[1] = 'a'; break;
135 case '\v': xbuf[1] = 'v'; break;
136#else
137 case '\007': xbuf[1] = 'a'; break;
138 case 0x0B: xbuf[1] = 'v'; break;
139#endif
140 case '\b': xbuf[1] = 'b'; break;
141 case '\f': xbuf[1] = 'f'; break;
142 case '\n': xbuf[1] = 'n'; break;
143 case '\r': xbuf[1] = 'r'; break;
144 case '\t': xbuf[1] = 't'; break;
145 default: sprintf (xbuf, "%d", i); break;
146 }
147
148 return xbuf;
149}
150
151static char *
152getcstr (f)
153 int f;
154{
155 int i;
156
157 for (i = 0; i < N_WFLAGS; i++)
158 if (f == wordflags[i].flag)
159 return (wordflags[i].fstr);
160 return ((char *)NULL);
161}
162
163static void
164addcstr (str, flag)
165 char *str;
166 int flag;
167{
168 char *s, *fstr;
169 unsigned char uc;
170
171 for (s = str; s && *s; s++)
172 {
173 uc = *s;
174
175 if (debug)
176 {
177 fstr = getcstr (flag);
178 fprintf(stderr, "added %s for character %s\n", fstr, cdesc(uc));
179 }
180
181 lsyntax[uc] |= flag;
182 }
183}
184
185static void
186addcchar (c, flag)
187 unsigned char c;
188 int flag;
189{
190 char *fstr;
191
192 if (debug)
193 {
194 fstr = getcstr (flag);
195 fprintf (stderr, "added %s for character %s\n", fstr, cdesc(c));
196 }
197 lsyntax[c] |= flag;
198}
199
200static void
201addblanks ()
202{
203 register int i;
204 unsigned char uc;
205
206 for (i = 0; i < SYNSIZE; i++)
207 {
208 uc = i;
209 /* Since we don't call setlocale(), this defaults to the "C" locale, and
210 the default blank characters will be space and tab. */
211 if (isblank (uc))
212 lsyntax[uc] |= CBLANK;
213 }
214}
215
216/* load up the correct flag values in lsyntax */
217static void
218load_lsyntax ()
219{
220 /* shell metacharacters */
221 addcstr (shell_meta_chars, CSHMETA);
222
223 /* shell word break characters */
224 addcstr (shell_break_chars, CSHBRK);
225
226 addcchar ('`', CBACKQ);
227
228 addcstr (shell_quote_chars, CQUOTE);
229
230 addcchar (CTLESC, CSPECL);
231 addcchar (CTLNUL, CSPECL);
232
233 addcstr (shell_exp_chars, CEXP);
234
235 addcstr (slashify_in_quotes, CBSDQUOTE);
236 addcstr (slashify_in_here_document, CBSHDOC);
237
238 addcstr (shell_glob_chars, CGLOB);
239
240#if defined (EXTENDED_GLOB)
241 addcstr (ext_glob_chars, CXGLOB);
242#endif
243
244 addcstr (shell_quote_chars, CXQUOTE);
245 addcchar ('\\', CXQUOTE);
246
247 addcstr ("@*#?-$!", CSPECVAR); /* omits $0...$9 and $_ */
248
249 addcstr ("-=?+", CSUBSTOP); /* OP in ${paramOPword} */
250
251 addblanks ();
252}
253
254static void
255dump_lflags (fp, ind)
256 FILE *fp;
257 int ind;
258{
259 int xflags, first, i;
260
261 xflags = lsyntax[ind];
262 first = 1;
263
264 if (xflags == 0)
265 fputs (wordflags[0].fstr, fp);
266 else
267 {
268 for (i = 1; i < N_WFLAGS; i++)
269 if (xflags & wordflags[i].flag)
270 {
271 if (first)
272 first = 0;
273 else
274 putc ('|', fp);
275 fputs (wordflags[i].fstr, fp);
276 }
277 }
278}
279
280static void
281wcomment (fp, i)
282 FILE *fp;
283 int i;
284{
285 fputs ("\t\t/* ", fp);
286
287 fprintf (fp, "%s", cdesc(i));
288
289 fputs (" */", fp);
290}
291
292static void
293dump_lsyntax (fp)
294 FILE *fp;
295{
296 int i;
297
298 fprintf (fp, "int sh_syntabsiz = %d;\n", SYNSIZE);
299 fprintf (fp, "int sh_syntaxtab[%d] = {\n", SYNSIZE);
300
301 for (i = 0; i < SYNSIZE; i++)
302 {
303 putc ('\t', fp);
304 dump_lflags (fp, i);
305 putc (',', fp);
306 wcomment (fp, i);
307 putc ('\n', fp);
308 }
309
310 fprintf (fp, "};\n");
311}
312
313int
314main(argc, argv)
315 int argc;
316 char **argv;
317{
318 int opt, i;
319 char *filename;
320 FILE *fp;
321
322 if ((progname = strrchr (argv[0], '/')) == 0)
323 progname = argv[0];
324 else
325 progname++;
326
327 filename = (char *)NULL;
328 debug = 0;
329
330 while ((opt = getopt (argc, argv, "do:")) != EOF)
331 {
332 switch (opt)
333 {
334 case 'd':
335 debug = 1;
336 break;
337 case 'o':
338 filename = optarg;
339 break;
340 default:
341 usage();
342 }
343 }
344
345 argc -= optind;
346 argv += optind;
347
348 if (filename)
349 {
350 fp = fopen (filename, "w");
351 if (fp == 0)
352 {
353 fprintf (stderr, "%s: %s: cannot open: %s\n", progname, filename, strerror(errno));
354 exit (1);
355 }
356 }
357 else
358 {
359 filename = "stdout";
360 fp = stdout;
361 }
362
363
364 for (i = 0; i < SYNSIZE; i++)
365 lsyntax[i] = CWORD;
366
367 load_lsyntax ();
368
369 fprintf (fp, "%s\n", preamble);
370 fprintf (fp, "%s\n", includes);
371
372 dump_lsyntax (fp);
373
374 if (fp != stdout)
375 fclose (fp);
376 exit (0);
377}
378
379
380#if !defined (HAVE_STRERROR)
381
382#include <bashtypes.h>
383#if defined (HAVE_SYS_PARAM_H)
384# include <sys/param.h>
385#endif
386
387#if defined (HAVE_UNISTD_H)
388# include <unistd.h>
389#endif
390
391/* Return a string corresponding to the error number E. From
392 the ANSI C spec. */
393#if defined (strerror)
394# undef strerror
395#endif
396
397char *
398strerror (e)
399 int e;
400{
401 static char emsg[40];
402#if defined (HAVE_SYS_ERRLIST)
403 extern int sys_nerr;
404 extern char *sys_errlist[];
405
406 if (e > 0 && e < sys_nerr)
407 return (sys_errlist[e]);
408 else
409#endif /* HAVE_SYS_ERRLIST */
410 {
411 sprintf (emsg, "Unknown system error %d", e);
412 return (&emsg[0]);
413 }
414}
415#endif /* HAVE_STRERROR */