]> git.ipfire.org Git - thirdparty/bash.git/blame - mksyntax.c
Bash-4.3 patch 32
[thirdparty/bash.git] / mksyntax.c
CommitLineData
28ef6c31
JA
1/*
2 * mksyntax.c - construct shell syntax table for fast char attribute lookup.
3 */
4
3185942a 5/* Copyright (C) 2000-2009 Free Software Foundation, Inc.
28ef6c31
JA
6
7 This file is part of GNU Bash, the Bourne Again SHell.
8
3185942a
JA
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.
28ef6c31 13
3185942a
JA
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.
28ef6c31 18
3185942a
JA
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*/
28ef6c31
JA
22
23#include "config.h"
f73dda09 24
28ef6c31
JA
25#include <stdio.h>
26#include "bashansi.h"
f73dda09 27#include "chartypes.h"
28ef6c31
JA
28#include <errno.h>
29
f73dda09
JA
30#ifdef HAVE_UNISTD_H
31# include <unistd.h>
32#endif
33
28ef6c31
JA
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" },
7117c2d2
JA
63 { CSPECVAR, "CSPECVAR" },
64 { CSUBSTOP, "CSUBSTOP" },
0628567a 65 { CBLANK, "CBLANK" },
28ef6c31
JA
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[] = "\
b80f6443 82#include \"config.h\"\n\
28ef6c31
JA
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
f73dda09 93#ifdef INCLUDE_UNUSED
28ef6c31
JA
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}
f73dda09 105#endif
28ef6c31
JA
106
107static char *
108cdesc (i)
109 int i;
110{
111 static char xbuf[16];
112
113 if (i == ' ')
114 return "SPC";
f73dda09 115 else if (ISPRINT (i))
28ef6c31
JA
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 {
b80f6443 133#ifdef __STDC__
28ef6c31
JA
134 case '\a': xbuf[1] = 'a'; break;
135 case '\v': xbuf[1] = 'v'; break;
b80f6443
JA
136#else
137 case '\007': xbuf[1] = 'a'; break;
138 case 0x0B: xbuf[1] = 'v'; break;
139#endif
28ef6c31
JA
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{
f73dda09
JA
168 char *s, *fstr;
169 unsigned char uc;
28ef6c31 170
f73dda09 171 for (s = str; s && *s; s++)
28ef6c31 172 {
f73dda09
JA
173 uc = *s;
174
28ef6c31
JA
175 if (debug)
176 {
177 fstr = getcstr (flag);
f73dda09 178 fprintf(stderr, "added %s for character %s\n", fstr, cdesc(uc));
28ef6c31
JA
179 }
180
f73dda09 181 lsyntax[uc] |= flag;
28ef6c31
JA
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
0628567a
JA
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
28ef6c31
JA
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 $_ */
7117c2d2
JA
248
249 addcstr ("-=?+", CSUBSTOP); /* OP in ${paramOPword} */
0628567a
JA
250
251 addblanks ();
28ef6c31
JA
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{
f73dda09 296 int i;
28ef6c31 297
b80f6443
JA
298 fprintf (fp, "int sh_syntabsiz = %d;\n", SYNSIZE);
299 fprintf (fp, "int sh_syntaxtab[%d] = {\n", SYNSIZE);
28ef6c31
JA
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
f73dda09 313int
28ef6c31
JA
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>
ac50fbac 383#if defined (HAVE_SYS_PARAM_H)
28ef6c31
JA
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 */