Pristine Ack-5.5
[Ack-5.5.git] / util / cmisc / tabgen.c
1 /*
2  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  */
5 /*
6         chtabgen - character table generator
7
8         Author: Erik Baalbergen (..tjalk!erikb)
9         Many mods by Ceriel Jacobs
10 */
11
12 #include <stdio.h>
13
14 #ifndef NORCSID
15 static char *RcsId = "$Id: tabgen.c,v 1.7 1997/05/15 12:03:05 ceriel Exp $";
16 #endif
17
18 #define MAXBUF  256
19 #define MAXTAB 10000
20 #define COMCOM  '-'
21 #define FILECOM '%'
22
23 int InputForm = 'c';    /* default input format (and, currently, only one) */
24 char OutputForm[MAXBUF] = "%s,\n";
25                         /* format for spitting out a string */
26 char *Table[MAXTAB];
27 char *ProgCall;         /* callname of this program */
28 int TabSize = 128;      /* default size of generated table */
29 char *InitialValue;     /* initial value of all table entries */
30
31 extern char *malloc(), *strcpy();
32
33 main(argc, argv)
34         char *argv[];
35 {
36
37         ProgCall = *argv++;
38         argc--;
39         while (argc-- > 0) {
40                 if (**argv == COMCOM) {
41                         option(*argv++);
42                 }
43                 else {
44                         if (! process(*argv++, InputForm)) {
45                                 exit(1);
46                         }
47                 }
48         }
49         exit(0);
50         /*NOTREACHED*/
51 }
52
53 char *
54 Salloc(s)
55         char *s;
56 {
57         char *ns = malloc((unsigned)strlen(s) + 1);
58
59         if (ns) {
60                 strcpy(ns, s);
61         }
62         else {
63                 fprintf(stderr, "%s: out of memory\n", ProgCall);
64                 exit(1);
65         }
66         return ns;
67 }
68
69 option(str)
70         char *str;
71 {
72         /*      note that *str indicates the source of the option:
73                 either COMCOM (from command line) or FILECOM (from a file).
74         */
75         switch (*++str) {
76
77         case ' ':       /* command */
78         case '\t':
79         case '\0':
80                 break;
81         case 'I':       /* for future extension */
82                 InputForm = *++str;
83                 break;
84         case 'f':       /* input from file ... */
85                 if (*++str == '\0') {
86                         fprintf(stderr, "%s: -f: name expected\n", ProgCall);
87                         exit(1);
88                 }
89                 DoFile(str);
90                 break;
91         case 'F':       /* new output format string */
92                 sprintf(OutputForm, "%s\n", ++str);
93                 break;
94         case 'T':       /* insert text literally */
95                 printf("%s\n", ++str);
96                 break;
97         case 'p':       /* print table */
98                 PrintTable();
99                 break;
100         case 'C':       /* clear table */
101                 InitTable((char *)0);
102                 break;
103         case 'i':       /* initialize table with given value */
104                 if (*++str == '\0') {
105                         InitTable((char *)0);
106                 }
107                 else    InitTable(str);
108                 break;
109         case 'S':
110         {
111                 int i = atoi(++str);
112
113                 if (i <= 0 || i > MAXTAB) {
114                         fprintf(stderr, "%s: size would exceed maximum\n",
115                                 ProgCall);
116                 }
117                 else {
118                         TabSize = i;
119                 }
120                 break;
121         }
122         default:
123                 fprintf(stderr, "%s: bad option -%s\n", ProgCall, str);
124         }
125 }
126
127 InitTable(ival)
128         char *ival;
129 {
130         int i;
131
132         for (i = 0; i < TabSize; i++) {
133                 Table[i] = 0;
134         }
135         InitialValue = 0;
136         if (ival) {
137                 InitialValue = Salloc(ival);
138         }
139 }
140
141 PrintTable()
142 {
143         int i;
144
145         for (i = 0; i < TabSize; i++) {
146                 if (Table[i]) {
147                         printf(OutputForm, Table[i]);
148                 }
149                 else if (InitialValue) {
150                         printf(OutputForm, InitialValue);
151                 }
152                 else {
153                         printf(OutputForm, "0");
154                 }
155         }
156 }
157
158 int
159 process(str, format)
160         char *str;
161 {
162         char *cstr = str;
163         char *Name = cstr;      /* overwrite original string!   */
164
165         /* strip of the entry name
166         */
167         while (*str && *str != ':') {
168                 if (*str == '\\') {
169                         ++str;
170                 }
171                 *cstr++ = *str++;
172         }
173
174         if (*str != ':') {
175                 fprintf(stderr, "%s: bad specification: \"%s\", ignored\n",
176                         ProgCall, Name);
177                 return 0;
178         }
179         *cstr = '\0';
180         str++;
181
182         switch (format) {
183
184         case 'c':
185                 return c_proc(str, Name);
186         default:
187                 fprintf(stderr, "%s: bad input format\n", ProgCall);
188         }
189         return 0;
190 }
191
192 c_proc(str, Name)
193         char *str;
194         char *Name;
195 {
196         int ch, ch2;
197         int quoted();
198         char *name = Salloc(Name);
199
200         while (*str)    {
201                 if (*str == '\\')       {
202                         ch = quoted(&str);
203                 }
204                 else    {
205                         ch = *str++ & 0377;
206                 }
207                 if (*str == '-')        {
208                         if (*++str == '\\')     {
209                                 ch2 = quoted(&str);
210                         }
211                         else    {
212                                 if (ch2 = (*str++ & 0377));
213                                 else str--;
214                         }
215                         if (ch > ch2) {
216                                 fprintf(stderr, "%s: bad range\n", ProgCall);
217                                 return 0;
218                         }
219                         while (ch <= ch2) {
220                                 if (! setval(ch, name)) return 0;
221                                 ch++;
222                         }
223                 }
224                 else    {
225                         if (! setval(ch, name)) return 0;
226                 }
227         }
228         return 1;
229 }
230
231 int
232 setval(ch, nm)
233         char *nm;
234 {
235         char **p = &Table[ch];
236
237         if (ch < 0 || ch >= TabSize) {
238                 fprintf(stderr, "Illegal index: %d\n", ch);
239                 return 0;
240         }
241         if (*(p = &Table[ch])) {
242                 fprintf(stderr, "Warning: redefinition of index %d\n", ch);
243         }
244         *p = nm;
245         return 1;
246 }
247
248 int
249 quoted(pstr)
250         char **pstr;
251 {
252         int ch;
253         int i;
254         char *str = *pstr;
255
256         if ((*++str >= '0') && (*str <= '9'))   {
257                 ch = 0;
258                 for (i = 0; i < 3; i++) {
259                         ch = 8 * ch + (*str - '0');
260                         if (*++str < '0' || *str > '9')
261                                 break;
262                 }
263         }
264         else    {
265                 switch (*str++) {
266                 case 'n':
267                         ch = '\n';
268                         break;
269                 case 't':
270                         ch = '\t';
271                         break;
272                 case 'b':
273                         ch = '\b';
274                         break;
275                 case 'r':
276                         ch = '\r';
277                         break;
278                 case 'f':
279                         ch = '\f';
280                         break;
281                 case 'v':
282                         ch = 013;
283                         break;
284                 default :
285                         ch = *(str - 1);
286                         break;
287                 }
288         }
289         *pstr = str;
290         return ch & 0377;
291 }
292
293 char *
294 getline(s, n, fp)
295         char *s;
296         FILE *fp;
297 {
298         int c = getc(fp);
299         char *str = s;
300
301         while (n--) {
302                 if (c == EOF) {
303                         return NULL;
304                 }
305                 else
306                 if (c == '\n') {
307                         *str++ = '\0';
308                         return s;
309                 }
310                 *str++ = c;
311                 c = getc(fp);
312         }
313         s[n - 1] = '\0';
314         return s;
315 }
316
317 #define BUFSIZE 1024
318
319 DoFile(name)
320         char *name;
321 {
322         char text[BUFSIZE];
323         FILE *fp;
324
325         if ((fp = fopen(name, "r")) == NULL) {
326                 fprintf(stderr, "%s: cannot read file %s\n", ProgCall, name);
327                 exit(1);
328         }
329         while (getline(text, BUFSIZE, fp) != NULL) {
330                 if (text[0] == FILECOM) {
331                         option(text);
332                 }
333                 else {
334                         if (! process(text, InputForm)) {
335                                 exit(1);
336                         }
337                 }
338         }
339 }