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