]> git.ipfire.org Git - thirdparty/bash.git/blob - mksyntax.c
Imported from ../bash-2.05.tar.gz.
[thirdparty/bash.git] / mksyntax.c
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"
24 #include <stdio.h>
25 #include "bashansi.h"
26 #include <ctype.h>
27 #include <errno.h>
28
29 #include "syntax.h"
30
31 extern int optind;
32 extern char *optarg;
33
34 #ifndef errno
35 extern int errno;
36 #endif
37
38 #ifndef HAVE_STRERROR
39 extern char *strerror();
40 #endif
41
42 struct wordflag {
43 int flag;
44 char *fstr;
45 } wordflags[] = {
46 { CWORD, "CWORD" },
47 { CSHMETA, "CSHMETA" },
48 { CSHBRK, "CSHBRK" },
49 { CBACKQ, "CBACKQ" },
50 { CQUOTE, "CQUOTE" },
51 { CSPECL, "CSPECL" },
52 { CEXP, "CEXP" },
53 { CBSDQUOTE, "CBSDQUOTE" },
54 { CBSHDOC, "CBSHDOC" },
55 { CGLOB, "CGLOB" },
56 { CXGLOB, "CXGLOB" },
57 { CXQUOTE, "CXQUOTE" },
58 { CSPECVAR, "CSPECVAR" }
59 };
60
61 #define N_WFLAGS (sizeof (wordflags) / sizeof (wordflags[0]))
62 #define SYNSIZE 256
63
64 int lsyntax[SYNSIZE];
65 int debug;
66 char *progname;
67
68 char preamble[] = "\
69 /*\n\
70 * This file was generated by mksyntax. DO NOT EDIT.\n\
71 */\n\
72 \n";
73
74 char includes[] = "\
75 #include \"stdc.h\"\n\
76 #include \"syntax.h\"\n\n";
77
78 static void
79 usage()
80 {
81 fprintf (stderr, "%s: usage: %s [-d] [-o filename]\n", progname, progname);
82 exit (2);
83 }
84
85 static int
86 getcflag (s)
87 char *s;
88 {
89 int i;
90
91 for (i = 0; i < N_WFLAGS; i++)
92 if (strcmp (s, wordflags[i].fstr) == 0)
93 return wordflags[i].flag;
94 return -1;
95 }
96
97 static char *
98 cdesc (i)
99 int i;
100 {
101 static char xbuf[16];
102
103 if (i == ' ')
104 return "SPC";
105 else if (isprint (i))
106 {
107 xbuf[0] = i;
108 xbuf[1] = '\0';
109 return (xbuf);
110 }
111 else if (i == CTLESC)
112 return "CTLESC";
113 else if (i == CTLNUL)
114 return "CTLNUL";
115 else if (i == '\033') /* ASCII */
116 return "ESC";
117
118 xbuf[0] = '\\';
119 xbuf[2] = '\0';
120
121 switch (i)
122 {
123 case '\a': xbuf[1] = 'a'; break;
124 case '\v': xbuf[1] = 'v'; break;
125 case '\b': xbuf[1] = 'b'; break;
126 case '\f': xbuf[1] = 'f'; break;
127 case '\n': xbuf[1] = 'n'; break;
128 case '\r': xbuf[1] = 'r'; break;
129 case '\t': xbuf[1] = 't'; break;
130 default: sprintf (xbuf, "%d", i); break;
131 }
132
133 return xbuf;
134 }
135
136 static char *
137 getcstr (f)
138 int f;
139 {
140 int i;
141
142 for (i = 0; i < N_WFLAGS; i++)
143 if (f == wordflags[i].flag)
144 return (wordflags[i].fstr);
145 return ((char *)NULL);
146 }
147
148 static void
149 addcstr (str, flag)
150 char *str;
151 int flag;
152 {
153 unsigned char *s;
154 char *fstr;
155
156 for (s = (unsigned char *)str; s && *s; s++)
157 {
158 if (debug)
159 {
160 fstr = getcstr (flag);
161 fprintf(stderr, "added %s for character %s\n", fstr, cdesc(*s));
162 }
163
164 lsyntax[*s] |= flag;
165 }
166 }
167
168 static void
169 addcchar (c, flag)
170 unsigned char c;
171 int flag;
172 {
173 char *fstr;
174
175 if (debug)
176 {
177 fstr = getcstr (flag);
178 fprintf (stderr, "added %s for character %s\n", fstr, cdesc(c));
179 }
180 lsyntax[c] |= flag;
181 }
182
183 /* load up the correct flag values in lsyntax */
184 static void
185 load_lsyntax ()
186 {
187 /* shell metacharacters */
188 addcstr (shell_meta_chars, CSHMETA);
189
190 /* shell word break characters */
191 addcstr (shell_break_chars, CSHBRK);
192
193 addcchar ('`', CBACKQ);
194
195 addcstr (shell_quote_chars, CQUOTE);
196
197 addcchar (CTLESC, CSPECL);
198 addcchar (CTLNUL, CSPECL);
199
200 addcstr (shell_exp_chars, CEXP);
201
202 addcstr (slashify_in_quotes, CBSDQUOTE);
203 addcstr (slashify_in_here_document, CBSHDOC);
204
205 addcstr (shell_glob_chars, CGLOB);
206
207 #if defined (EXTENDED_GLOB)
208 addcstr (ext_glob_chars, CXGLOB);
209 #endif
210
211 addcstr (shell_quote_chars, CXQUOTE);
212 addcchar ('\\', CXQUOTE);
213
214 addcstr ("@*#?-$!", CSPECVAR); /* omits $0...$9 and $_ */
215 }
216
217 static void
218 dump_lflags (fp, ind)
219 FILE *fp;
220 int ind;
221 {
222 int xflags, first, i;
223
224 xflags = lsyntax[ind];
225 first = 1;
226
227 if (xflags == 0)
228 fputs (wordflags[0].fstr, fp);
229 else
230 {
231 for (i = 1; i < N_WFLAGS; i++)
232 if (xflags & wordflags[i].flag)
233 {
234 if (first)
235 first = 0;
236 else
237 putc ('|', fp);
238 fputs (wordflags[i].fstr, fp);
239 }
240 }
241 }
242
243 static void
244 wcomment (fp, i)
245 FILE *fp;
246 int i;
247 {
248 fputs ("\t\t/* ", fp);
249
250 fprintf (fp, "%s", cdesc(i));
251
252 fputs (" */", fp);
253 }
254
255 static void
256 dump_lsyntax (fp)
257 FILE *fp;
258 {
259 int i, cflag;
260 char *cstr;
261
262 fprintf (fp, "const int sh_syntaxtab[%d] = {\n", SYNSIZE);
263
264 for (i = 0; i < SYNSIZE; i++)
265 {
266 putc ('\t', fp);
267 dump_lflags (fp, i);
268 putc (',', fp);
269 wcomment (fp, i);
270 putc ('\n', fp);
271 }
272
273 fprintf (fp, "};\n");
274 }
275
276 main(argc, argv)
277 int argc;
278 char **argv;
279 {
280 int opt, i;
281 char *filename;
282 FILE *fp;
283
284 if ((progname = strrchr (argv[0], '/')) == 0)
285 progname = argv[0];
286 else
287 progname++;
288
289 filename = (char *)NULL;
290 debug = 0;
291
292 while ((opt = getopt (argc, argv, "do:")) != EOF)
293 {
294 switch (opt)
295 {
296 case 'd':
297 debug = 1;
298 break;
299 case 'o':
300 filename = optarg;
301 break;
302 default:
303 usage();
304 }
305 }
306
307 argc -= optind;
308 argv += optind;
309
310 if (filename)
311 {
312 fp = fopen (filename, "w");
313 if (fp == 0)
314 {
315 fprintf (stderr, "%s: %s: cannot open: %s\n", progname, filename, strerror(errno));
316 exit (1);
317 }
318 }
319 else
320 {
321 filename = "stdout";
322 fp = stdout;
323 }
324
325
326 for (i = 0; i < SYNSIZE; i++)
327 lsyntax[i] = CWORD;
328
329 load_lsyntax ();
330
331 fprintf (fp, "%s\n", preamble);
332 fprintf (fp, "%s\n", includes);
333
334 dump_lsyntax (fp);
335
336 if (fp != stdout)
337 fclose (fp);
338 exit (0);
339 }
340
341
342 #if !defined (HAVE_STRERROR)
343
344 #include <bashtypes.h>
345 #ifndef _MINIX
346 # include <sys/param.h>
347 #endif
348
349 #if defined (HAVE_UNISTD_H)
350 # include <unistd.h>
351 #endif
352
353 /* Return a string corresponding to the error number E. From
354 the ANSI C spec. */
355 #if defined (strerror)
356 # undef strerror
357 #endif
358
359 char *
360 strerror (e)
361 int e;
362 {
363 static char emsg[40];
364 #if defined (HAVE_SYS_ERRLIST)
365 extern int sys_nerr;
366 extern char *sys_errlist[];
367
368 if (e > 0 && e < sys_nerr)
369 return (sys_errlist[e]);
370 else
371 #endif /* HAVE_SYS_ERRLIST */
372 {
373 sprintf (emsg, "Unknown system error %d", e);
374 return (&emsg[0]);
375 }
376 }
377 #endif /* HAVE_STRERROR */