]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ddb/makedis.c
a33bf216e2f9a146a388f1a933fa9bcb1c476b43
[apple/xnu.git] / osfmk / ddb / makedis.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * @OSF_COPYRIGHT@
30 */
31 /*
32 * HISTORY
33 *
34 * Revision 1.1.1.1 1998/09/22 21:05:48 wsanchez
35 * Import of Mac OS X kernel (~semeria)
36 *
37 * Revision 1.1.1.1 1998/03/07 02:26:09 wsanchez
38 * Import of OSF Mach kernel (~mburg)
39 *
40 * Revision 1.1.2.1 1997/03/27 18:46:52 barbou
41 * Created.
42 * [1997/03/27 13:58:42 barbou]
43 *
44 * $EndLog$
45 */
46
47 /* makedis.c - make a disassembler. */
48
49 /* ,
50 By Eamonn McManus <emcmanus@gr.osf.org>, April 1995.
51 Copyright 1995 by Eamonn McManus. Non-commercial use is permitted. */
52
53 /* DESCRIPTION
54
55 This program generates a disassembler in C from a file describing the
56 opcodes of the machine in question. Lines in the description file are
57 either comments beginning with #, or contain three fields, with the
58 first two being terminated by space and the third containing the rest
59 of the line. Long logical lines can be split onto several physical
60 lines by ending each one except the last with a \. A logical line
61 can also be split immediately after a |. Unlike \, | is considered
62 part of the logical line. Leading spaces on continuation lines
63 following either \ or | are ignored.
64
65 Here is a concise description of the meanings of the three fields.
66 Examples later will make it clearer what they are used for.
67
68 The first field of the three is a function name. This will produce
69 a function or array of the same name in the C output, so it should
70 not conflict with other identifiers or C keywords. By default the
71 function named returns a string (a (char *) in C), but if the first
72 field is preceded by %, the function returns an unsigned long
73 integer.
74
75 The second field describes the arguments of the function. It consists
76 of two parts, either but not both of which may be omitted. The first
77 part is a string which is a bitmask describing the first argument of
78 the function. Each character of the string represents one bit,
79 with the least significant bit being the last. A character can be
80 0 or 1, representing that constant value, or a letter, representing
81 part of a bitfield. A given bitfield consists of all of the
82 contiguous bits containing the same letter. Upper and lower case
83 letters are considered different.
84
85 The second part of the second field is a list of parameters
86 describing the parameters of the function, or the parameters after
87 the first if the bitfield part was present. The list is contained
88 in parentheses () and the individual parameters are separated by
89 commas. Spaces are not allowed. Each parameter name is a single
90 letter, optionally preceded by %. The parameter is an unsigned
91 long integer if % is present, otherwise a string. Again, upper and
92 lower case parameter names are different.
93
94 The third field describes the value of the function. If a bitmask
95 is present in the second field and it contains constant bits (0s or
96 1s), then the third field is the value of the function only in the
97 case where its first argument contains matching values in those bit
98 positions. There can be many different lines naming the same
99 function but with different bitpatterns. The generated C code will
100 arrange to return the value corresponding to the pattern that
101 matches the actual first argument of the function when it is
102 called. This argument should not have bits set in positions beyond
103 those present in the bitpattern.
104
105 It is only allowed for two different lines to name the same function
106 if there is a bitstring in the second field. It is not allowed for
107 two such lines to specify exactly the same constant bit values. But
108 it is allowed for a line to have all the same constant bit values as
109 another plus some extra constant values. In this case the more
110 specific line applies when all of its constant bits match, and
111 otherwise the less specific line applies.
112
113 Apart from the contents of the bitstring, the second field must be
114 identical on every line referring to a given function, and the
115 bitstring must always be of the same length.
116
117 For string-valued functions, the third field is the string value.
118 For integer-valued functions, it is a C integer expression
119 generating the value. In both cases there may be several special
120 values:
121
122 - A $ followed by a single letter is replaced by the value of the
123 argument or bitfield with that name. The value of a bitfield is
124 shifted as if that bitfield were in the least-significant bit
125 position. Thus, a single-bit field always has value 0 or 1.
126
127 - A $ followed by the name of a function and an argument list in
128 parentheses () is replaced by the value returned by the function
129 with those arguments. An integer value cannot be inserted into a
130 string without being converted by a function, nor can a string
131 value be used in an integer expression.
132
133 - A $ followed by a bitstring enclosed in [] is replaced by the
134 value of that bitstring. The bitstring has the same syntax as in
135 the second field, described above. Each contiguous sequence of
136 the same repeated letter in the bitstring is replaced by the
137 value of the argument or bitfield-argument with that name,
138 shifted into the appropriate position.
139
140 - A list of strings, separated by |, enclosed in
141 {}, and followed by an integer expression enclosed in [], is
142 replaced by the string in the list whose number matches the value
143 of the expression. The first string in the list is numbered 0.
144 If there is no string corresponding to the value of the
145 expression, the behaviour is undefined. The strings in the list
146 may themselves contain $ or {} operations.
147
148 - A \ followed by any character is replaced by that
149 character, without regard to any meaning it may usually have.
150 This is used to obtain strings containing characters such as
151 {, $, or \. The use of backslash to split long logical
152 lines takes precedence over this use, so \\ should not appear
153 at the end of a line.
154
155 The third field may also be a lone colon ":", in which case the
156 function is assumed to be defined externally and only a function
157 declaration (prototype) is generated.
158
159
160 EXAMPLES
161
162 Here are some examples from the description file for the Z80
163 microprocessor. This processor has 8-bit opcodes which are
164 disassembled by a generated function "inst" which looks like this:
165
166 typedef unsigned long bits;
167 char *inst(bits code) {...}
168
169 The simplest sort of line in the description file is one that looks
170 like this:
171
172 inst 01110110 halt
173
174 The first field names the function, "inst". The second field
175 implies that that function has exactly one argument which is an
176 integer, and that this line specifies the value of the function
177 when this integer has the binary value 01110110 (hex 0x76). This
178 value will be the string "halt".
179
180 A more complex line is one looking like this:
181
182 inst 001aa111 {daa|cpl|scf|ccf}[$a]
183
184 This line is compatible with the previous one, because it has the
185 same number of bits and the constant bits are different. It
186 specifies the value of inst when its argument looks like
187 001aa111, i.e., for the binary values
188 00100111,
189 00101111,
190 00110111, and
191 00111111. The value of $a for these four values will be
192 respectively binary 00, 01, 10, 11, i.e., 0 to 3. The
193 corresponding values of the inst function will be "daa", "cpl",
194 "scf", and "ccf".
195
196 The description defines a helper function "reg8" like this:
197
198 reg8 rrr {b|c|d|e|h|l|(hl)|a}[$r]
199
200 This simply selects one of the eight strings between {} depending
201 on the value of the argument, which is assumed to be a three-bit
202 value. This could just as easily have been written:
203
204 reg8 (%r) {b|c|d|e|h|l|(hl)|a}[$r]
205
206 The generated C code is the same -- in each case makedis realises
207 that the function can be represented by an array rather than
208 compiling a C function.
209
210 The reg8 function is used in lines like this one:
211
212 inst 01rrrsss ld $reg8($r),$reg8($s)
213
214 Thus if the argument to inst is
215 01010011
216 then $r is 010 (2) and $s is 011 (3). Since reg8(2) is "d" and
217 reg8(3) is "e", the value of inst with this argument will be the
218 string "ld d,e".
219
220 Note that the opcode for "halt" given above matches this pattern,
221 but because the bitpattern for "halt" is more specific (has more
222 constant bits) it is the one chosen when the argument is 01110110.
223
224 The description also uses an external C function "hexprint" defined
225 like this:
226
227 char *hexprint(bits digits, bits n) {
228 char *p = dis_alloc(digits + 1);
229 sprintf(p, "%0*lx", (int) digits, n);
230 return p;
231 }
232
233 The value of this function is a string containing the number n
234 spelt out in hex with "digits" digits. In the description
235 file this function is declared like this:
236
237 hexprint (%w,%n) :
238
239 The names of the parameters are not important in this case as long
240 as they are letters and are different from each other.
241
242 The hexprint function is used in lines like this one:
243
244 inst 11vvv111 rst $hexprint(2,$v << 3)
245
246 If the argument to inst is
247 11011111
248 then $v is 011 (3) and the arguments to hexprint are 2 and (3 << 3),
249 i.e., 0x18. So the value of inst with this argument will be the
250 string "rst 18".
251
252 Instead of writing $v << 3, it would be possible to write
253 $[00vvv000]. For instance when $v is binary 011, this becomes
254 00011000. The leading 0s could be omitted.
255
256 The $[...] operation is particularly useful for moving bits around.
257 For instance, the HP PA-RISC opcodes contain bits assigned to
258 apparently random parts of the instruction word. One of the helper
259 functions in its description file looks like this:
260
261 im21l aaaaabbccddddddddddde l'$hex($[edddddddddddbbaaaaacc00000000000])
262
263 So 111110011000000000001 produces 10000000000000111111100000000000.
264
265 The $[...] operation can also be used to spell out binary constants,
266 since C has no syntax for this.
267
268
269 ...More to come... */
270
271 /* To do:
272 - More error detection, e.g., bitstring or arg not used in entry.
273 - Better error recovery -- nearly all errors are currently fatal.
274 - Clean up type handling, which is somewhat haphazard. It works but there
275 is stuff that is surely redundant.
276 - Make generated functions void by default, with $ prefix to indicate
277 string-value. In a void function, instead of returning a string (or
278 integer) it would be output via a user-supplied function.
279 - Further optimise and tidy generated code, e.g.: arrays of one-character
280 strings could be replaced by arrays of characters; switches with just
281 one case could be replaced by ifs.
282 */
283
284 #include <assert.h>
285 #include <ctype.h>
286 #include <sys/errno.h>
287 #include <limits.h>
288 #include <stdio.h>
289 #include <stdlib.h>
290 #include <string.h>
291
292 #define MAXfunction 32 /* Max function name length. */
293 #define MAXBITS 32 /* Max bitstring length. */
294 typedef unsigned long bits;
295 enum type {T_ERROR, T_UNKNOWN, T_INTEGER, T_STRING};
296 const char *const typename[] = {"error", "unknown", "integer", "string"};
297 enum walkstringop {COUNTARRAYS, DECLAREARRAYS, COMPILEARRAYS};
298 char *bitstype = "unsigned long";
299
300 int maxfunctionname, maxargwidth;
301 char *progname = "makedis";
302 char **global_argv;
303 char *filename;
304 char *headerfilename;
305 FILE *headerfile;
306 int lineno;
307 int indentation;
308 int debug, dump, warnings;
309
310 /* componentbits has a 1 bit for every possible number of strings we may want
311 to concatenate together at some stage. A separate C function is compiled
312 for each such case. */
313 bits componentbits;
314
315
316 struct entry;
317 struct arg;
318 struct string;
319 struct functioncall;
320 struct array;
321 struct bits;
322 struct bitsplice;
323
324
325 int main(int argc, char **argv);
326 int makedis(FILE *f, char *fname);
327 struct function *findfunction(char *function);
328 int parseextern(struct function *fp, FILE *f);
329 struct function *makefunction(char *function);
330 int parsebits(struct function *fp, char *bitstring, int nbits);
331 int parseentrybits(struct entry *ep, char *bitstring, int nbits, int issplice);
332 int parsecontrol(char *name, char *value);
333 int parseargs(struct function *fp, FILE *f, int *cp);
334 int parsestring(struct function *fp, char *str);
335 enum type makestring(struct function *fp, struct string **stringlink,
336 char **stringp, char *magic, enum type targettype);
337 int parsedollar(struct function *fp, char **stringp, struct string *sp);
338 int parsebitsplice(struct function *fp, char *bitstring, int nbits,
339 struct string *sp);
340 int findvariable(struct function *fp, int name, struct string *sp);
341 int parsefunctioncall(struct function *fp, char *start, char **stringp,
342 struct string *sp);
343 int parsearray(struct function *fp, char **stringp, struct string *sp,
344 enum type t);
345 void dumpfunctions(void);
346 void dumpfunction(struct function *fp);
347 void showentry(FILE *f, struct function *fp, struct entry *ep, bits highlight);
348 void showbits(FILE *f, struct entry *ep, int nbits, bits highlight);
349 void showargs(FILE *f, struct arg *ap, int fieldwidth);
350 void showstring(FILE *f, struct string *sp);
351 void showstringelement(FILE *f, struct string *sp);
352 void showfunctioncall(FILE *f, struct functioncall *fcp);
353 void showarray(FILE *f, struct array *ap);
354 int outputfunctions(void);
355 void outputidentity(FILE *f);
356 int outputdeclarations(void);
357 void outputconcats(void);
358 void outputconcat(int n);
359 void outputconcatheader(FILE *f, int n);
360 void findarrays(void);
361 int checkfixedlength(struct array *ap);
362 int outputfunction(struct function *fp);
363 void functionarray(struct function *fp);
364 void functionheader(FILE *f, struct function *fp);
365 int simplearray(struct array *ap);
366 void compiletype(FILE *f, enum type *tp);
367 int functionswitch(struct function *fp, bits mask, bits value);
368 int compilestring(int assignto, struct string *sp, enum type type);
369 int compilecheckedstring(int assignto, struct string *sp, enum type type);
370 void compileassign(int assignto);
371 void compiletemp(int tempno);
372 void compiletext(char *s);
373 int compileconcat(struct string *sp, enum type type);
374 int compilenull(enum type type);
375 int compilesimple(struct string *sp, enum type type);
376 int compilearrayref(struct array *ap);
377 int compilefunctioncall(struct string *sp);
378 int walkstring(struct string *sp, enum walkstringop op, int tempno);
379 int compilearray(struct array *ap);
380 void compilesimplearray(enum type *tp, char *name, int num, struct array *ap);
381 void declarearray(struct array *ap);
382 void compilebitstring(struct bits *bp);
383 void compilebitsplice(struct bitsplice *splicep);
384 int bitcount(bits x);
385 bits allbitsset(int nbits);
386 void findent(FILE *f);
387 void indent(void);
388 void *xrealloc(char *oldp, size_t size);
389 void *xmalloc(size_t size);
390 void *xstrdup(char *s);
391 int prematureeof(void);
392
393
394 int main(int argc, char **argv) {
395 int i;
396 FILE *f;
397
398 global_argv = argv;
399 if (argc > 0)
400 progname = argv[0];
401 for (i = 1; i < argc && argv[i][0] == '-'; i++) {
402 switch (argv[i][1]) {
403 case 'h':
404 if (++i >= argc)
405 goto Usage;
406 headerfilename = argv[i]; break;
407 case 'd':
408 debug = 1; break;
409 case 'D':
410 dump = 1; break;
411 case 'w':
412 warnings = 1; break;
413 default:
414 Usage:
415 fprintf(stderr, "Usage: %s [file]\n", progname);
416 return 1;
417 }
418 }
419 if (i == argc)
420 return makedis(stdin, "<stdin>");
421 if (i + 1 != argc)
422 goto Usage;
423 if ((f = fopen(argv[i], "r")) == NULL) {
424 fprintf(stderr, "%s: %s: %s\n", progname, argv[i], strerror(errno));
425 return 1;
426 }
427 return makedis(f, argv[i]);
428 }
429
430
431 int makedis(FILE *f, char *fname) {
432 int c, i;
433 char function[MAXfunction], bitstring[MAXBITS];
434 static char *string = NULL;
435 int stringlen = 0;
436 struct function *fp;
437
438 filename = fname;
439 lineno = 1;
440 /* Loop for every line in the description. */
441 while (1) {
442 /* Ignore initial spaces and newlines. */
443 while (isspace(c = getc(f)))
444 if (c == '\n')
445 lineno++;
446 if (c == EOF)
447 break;
448
449 /* Ignore comments. # only allowed at start of line. */
450 if (c == '#') {
451 while ((c = getc(f)) != '\n')
452 if (c == EOF)
453 return prematureeof();
454 lineno++;
455 continue;
456 }
457
458 /* Read function name, terminated by space. */
459 for (i = 0; i < sizeof function && !isspace(c); i++, c = getc(f)) {
460 if (c == EOF)
461 return prematureeof();
462 function[i] = c;
463 }
464 if (i >= sizeof function) {
465 fprintf(stderr, "%s: %s(%d): function name is too long: %.*s\n",
466 progname, filename, lineno, i, function);
467 return 1;
468 }
469 function[i] = '\0';
470
471 /* Skip to next field. */
472 while (isspace(c) && c != '\n')
473 c = getc(f);
474
475 /* If not a control statement, read bitstring and/or arguments. */
476 if (function[0] == ':')
477 fp = 0; /* Silence gcc. */
478 else {
479 fp = makefunction(function);
480 if (fp == NULL)
481 return 1;
482
483 /* Read optional bitstring. */
484 for (i = 0; i < sizeof bitstring && isalnum(c); i++, c = getc(f)) {
485 if (c == EOF)
486 return prematureeof();
487 bitstring[i] = c;
488 }
489 if (isalnum(c)) {
490 fprintf(stderr, "%s: %s(%d): bit string is too long: %.*s\n",
491 progname, filename, lineno, i, bitstring);
492 return 1;
493 }
494 if (parsebits(fp, bitstring, i) != 0)
495 return 1;
496
497 /* Read optional arguments. */
498 if (parseargs(fp, f, &c) != 0)
499 return 1;
500
501 /* Skip to next field. */
502 while (isspace(c) && c != '\n')
503 c = getc(f);
504
505 /* : indicates an external (C) function. */
506 if (c == ':') {
507 if (parseextern(fp, f) != 0)
508 return 1;
509 continue;
510 }
511 }
512
513 /* Read associated text. */
514 i = 0;
515 while (1) {
516 for ( ; c != '\n'; i++, c = getc(f)) {
517 if (c == EOF)
518 return prematureeof();
519 if (i >= stringlen) {
520 stringlen = stringlen * 2 + 16;
521 string = xrealloc(string, stringlen);
522 }
523 string[i] = c;
524 }
525 lineno++;
526 if (i > 0) {
527 switch (string[i - 1]) {
528 case '\\':
529 i--;
530 /* Fall in... */
531 case '|':
532 while (isspace(c = getc(f)) && c != '\n') ;
533 continue;
534 }
535 }
536 break;
537 }
538 if (i >= stringlen) {
539 stringlen = stringlen * 2 + 16;
540 string = xrealloc(string, stringlen);
541 }
542 string[i] = '\0';
543
544 /* Parse the line just read. */
545 if (function[0] == ':') {
546 if (parsecontrol(function + 1, string) != 0)
547 return 1;
548 } else {
549 if (parsestring(fp, string) != 0)
550 return 1;
551 }
552 }
553 if (dump)
554 dumpfunctions();
555 return outputfunctions();
556 }
557
558
559 /* A function in the description file. nbits and nargs are -1 until the
560 real values are known. */
561 struct function {
562 struct function *next;
563 char *name;
564 enum type type;
565 int nbits; /* Number of bits in the bitpattern, 0 if none. */
566 int nargs; /* Number of (x,y,...) parameters, 0 if none. */
567 char isarray; /* Will be represented by a C array. */
568 int fixedlength; /* If a C array, will be a char [][N] not a char *[]. */
569 struct entry *first, *last;
570 /* Links to the value(s) supplied. */
571 struct arg *args; /* List of (x,y,...) names and types. */
572 };
573 struct function *functions;
574
575
576 /* Find the function with the given name. If not found, create a structure
577 for it, fill it out with a template, and return that. */
578 struct function *findfunction(char *name) {
579 struct function *fp;
580
581 for (fp = functions; fp != NULL; fp = fp->next) {
582 if (strcmp(fp->name, name) == 0)
583 return fp;
584 }
585 if (strlen(name) > maxfunctionname)
586 maxfunctionname = strlen(name);
587 fp = xmalloc(sizeof *fp);
588 fp->next = functions;
589 functions = fp;
590 fp->name = xstrdup(name);
591 fp->type = T_UNKNOWN;
592 fp->nbits = fp->nargs = -1; /* nbits will be set correctly later. */
593 fp->isarray = 0;
594 fp->first = fp->last = NULL;
595 return fp;
596 }
597
598
599 /* Parse an external (C) function declaration. This will look something like:
600 malloc (%s) :
601 We're called just after seeing the ':'.
602 Return 0 if parsing is successful, 1 otherwise. */
603 int parseextern(struct function *fp, FILE *f) {
604 int c;
605
606 if ((c = getc(f)) != '\n') {
607 fprintf(stderr,
608 "%s: %s(%d): extern declaration should be a lone `:'\n",
609 progname, filename, lineno);
610 return 1;
611 }
612 if (fp->nbits != 0) {
613 fprintf(stderr,
614 "%s: %s(%d): extern functions should not have bitstrings\n",
615 progname, filename, lineno);
616 return 1;
617 }
618 free(fp->first);
619 fp->first = fp->last = NULL;
620 return 0;
621 }
622
623
624 /* A value supplied for a function (the third field in a description line).
625 In general there can be any number of such values, differing in the
626 bitpattern supplied. The mask and value fields describe the constant
627 bits in the bitpattern: mask indicates which bits they are and value
628 indicates the values of those bits. So this entry matches
629 ((x & mask) == value). */
630 struct entry {
631 struct entry *next;
632 bits mask, value;
633 struct bits *bits; /* List of named bitfields. */
634 struct string *string; /* Value of function when bitpattern matched. */
635 char done; /* This entry has already been compiled. */
636 };
637
638
639 /* We've just seen a definition of function "name". Make a structure for it
640 if necessary, and a template entry that will describe the value given here.
641 */
642 struct function *makefunction(char *name) {
643 struct function *fp;
644 struct entry *ep = xmalloc(sizeof *ep);
645 enum type type;
646
647 if (name[0] == '%') {
648 name++;
649 type = T_INTEGER;
650 } else
651 type = T_STRING;
652 fp = findfunction(name);
653 if (fp->type == T_UNKNOWN)
654 fp->type = type;
655 else if (fp->type != type) {
656 fprintf(stderr, "%s: %s(%d): function %s previously declared as %s, "
657 "here as %s\n", progname, filename, lineno, name,
658 typename[fp->type], typename[type]);
659 return NULL;
660 }
661 ep->next = NULL;
662 ep->bits = NULL;
663 ep->done = 0;
664 if (fp->first != NULL)
665 fp->last->next = ep;
666 else
667 fp->first = ep;
668 fp->last = ep;
669 return fp;
670 }
671
672
673 /* A named bitfield within the bitpattern of a function entry, or within a
674 $[...] bitsplice. The mask covers the bitfield and the shift says how
675 many 0 bits there are after the last 1 in the mask. */
676 struct bits {
677 struct bits *next;
678 int shift;
679 bits mask;
680 char name;
681 };
682
683
684 /* Parse the bitstring supplied for the given function. nbits says how many
685 bits there are; it can legitimately be 0. Return value is 0 on success. */
686 int parsebits(struct function *fp, char *bitstring, int nbits) {
687 if (fp->nbits < 0)
688 fp->nbits = nbits;
689 else if (fp->nbits != nbits) {
690 fprintf(stderr, "%s: %s(%d): bit string of length %d;\n",
691 progname, filename, lineno, nbits);
692 fprintf(stderr, " function %s has bit strings of length %d\n",
693 fp->name, fp->nbits);
694 return 1;
695 }
696 return parseentrybits(fp->last, bitstring, nbits, 0);
697 }
698
699
700 /* Parse a bitstring that is the pattern for a function entry or that is in a
701 $[...] bitsplice. Put the result in ep. Return value is 0 on success. */
702 int parseentrybits(struct entry *ep, char *bitstring, int nbits, int issplice) {
703 int i, j;
704 char bit;
705 bits mask, value, entrymask;
706 struct bits *bp;
707
708 mask = value = 0;
709 for (i = 0; i < nbits; i++) {
710 bit = bitstring[nbits - 1 - i];
711 switch (bit) {
712 case '1':
713 value |= 1 << i;
714 /* Fall in... */
715 case '0':
716 mask |= 1 << i;
717 continue;
718 }
719 if (!isalpha(bit)) {
720 fprintf(stderr, "%s: %s(%d): invalid character in bitstring: %c\n",
721 progname, filename, lineno, bit);
722 return 1;
723 }
724 if (!issplice) {
725 for (bp = ep->bits; bp != NULL; bp = bp->next) {
726 if (bp->name == bit) {
727 fprintf(stderr,
728 "%s: %s(%d): bitstring name %c used twice\n",
729 progname, filename, lineno, bit);
730 return 1;
731 }
732 }
733 }
734 entrymask = 1 << i;
735 for (j = i + 1; j < nbits && bitstring[nbits - 1 - j] == bit; j++)
736 entrymask |= 1 << j;
737 bp = xmalloc(sizeof *bp);
738 bp->shift = i;
739 bp->mask = entrymask;
740 bp->name = bit;
741 bp->next = ep->bits;
742 ep->bits = bp;
743 i = j - 1;
744 }
745 ep->mask = mask;
746 ep->value = value;
747 return 0;
748 }
749
750
751 /* Parse a control line. This looks something like:
752 :bitstype unsigned int
753 in which case we will be called with name "bitstype" and
754 value "unsigned int". */
755 int parsecontrol(char *name, char *value) {
756 if (strcmp(name, "bitstype") == 0)
757 bitstype = xstrdup(value);
758 else {
759 fprintf(stderr, "%s: %s(%d): unrecognised control keyword %s\n",
760 progname, filename, lineno, name);
761 return 1;
762 }
763 return 0;
764 }
765
766
767 /* A parameter to a function, e.g., x in:
768 %f aaa(%x) $a + $x */
769 struct arg {
770 struct arg *next;
771 enum type type;
772 char name;
773 };
774
775
776 /* Parse the parameters (x,y,...) to a function and put the result in fp.
777 The entry that is being built is fp->last. cp points to the opening
778 (; if it does not point to a ( then there are no parameters. If
779 this is the first entry for the function, fp->nargs will be -1 and
780 we will build up an argument list. Otherwise, fp->nargs will be
781 >= 0 and we will only check that the arguments here are consistent
782 with what went before. Return value is 0 on success. */
783 int parseargs(struct function *fp, FILE *f, int *cp) {
784 struct arg **arglink, *ap;
785 struct bits *bp;
786 int nargs, width;
787 char name;
788 enum type t;
789
790 arglink = &fp->args;
791 width = nargs = 0;
792 if (*cp == '(') {
793 *cp = getc(f);
794 if (*cp != ')') {
795 width = 1;
796 while (1) {
797 nargs++;
798 width += 2;
799 if (fp->nargs >= 0 && nargs > fp->nargs) {
800 fprintf(stderr,
801 "%s: %s(%d): %d arg(s) instead of %d for %s\n",
802 progname, filename, lineno, nargs, fp->nargs,
803 fp->name);
804 return 1;
805 }
806 t = T_STRING;
807 if (*cp == '%') {
808 width++;
809 t = T_INTEGER;
810 *cp = getc(f);
811 }
812 name = *cp;
813 if (!isalpha(name)) {
814 fprintf(stderr,
815 "%s: %s(%d): argument should be letter: %c\n",
816 progname, filename, lineno, name);
817 return 1;
818 }
819 for (bp = fp->last->bits; bp != NULL; bp = bp->next) {
820 if (bp->name == name) {
821 fprintf(stderr,
822 "%s: %s(%d): %c is a bitstring and an arg\n",
823 progname, filename, lineno, name);
824 return 1;
825 }
826 }
827 if (fp->nargs >= 0) {
828 if ((*arglink)->name != name) {
829 fprintf(stderr,
830 "%s: %s(%d): arg %d of %s is %c not %c\n",
831 progname, filename, lineno, nargs, fp->name,
832 (*arglink)->name, name);
833 return 1;
834 }
835 if ((*arglink)->type != t) {
836 fprintf(stderr,
837 "%s: %s(%d): arg %c of %s: inconsistent type\n",
838 progname, filename, lineno, name, fp->name);
839 return 1;
840 }
841 } else {
842 for (ap = fp->args; ap != *arglink; ap = ap->next) {
843 if (ap->name == name) {
844 fprintf(stderr,
845 "%s: %s(%d): argument name %c used twice\n",
846 progname, filename, lineno, name);
847 return 1;
848 }
849 }
850 *arglink = xmalloc(sizeof **arglink);
851 (*arglink)->name = name;
852 (*arglink)->type = t;
853 }
854 arglink = &(*arglink)->next;
855 *cp = getc(f);
856 if (*cp == ')')
857 break;
858 if (*cp != ',') {
859 fprintf(stderr,
860 "%s: %s(%d): bad character in argument list: %c\n"
861 " (arguments must be single letters)\n",
862 progname, filename, lineno, *cp);
863 return 1;
864 }
865 *cp = getc(f);
866 }
867 }
868 *cp = getc(f);
869 }
870 if (fp->nargs < 0) {
871 fp->nargs = nargs;
872 width += fp->nbits;
873 if (width > maxargwidth)
874 maxargwidth = width;
875 } else if (fp->nargs != nargs) {
876 fprintf(stderr, "%s: %s(%d): argument list of length %d;\n",
877 progname, filename, lineno, nargs);
878 fprintf(stderr, " function %s has argument lists of length %d\n",
879 fp->name, fp->nargs);
880 return 1;
881 }
882 *arglink = NULL;
883 return 0;
884 }
885
886
887 /* Parse the string describing the value of this entry for our
888 function. Return 0 on success. */
889 int parsestring(struct function *fp, char *str) {
890 enum type t;
891
892 t = makestring(fp, &fp->last->string, &str, NULL, fp->type);
893 if (t == T_ERROR)
894 return 1;
895 if (fp->type != t && t != T_UNKNOWN) {
896 fprintf(stderr, "%s: %s(%d): function %s has inconsistent types\n",
897 progname, filename, lineno, fp->name);
898 return 1;
899 }
900 return 0;
901 }
902
903
904 /* A parsed representation of the whole string describing a value of a
905 function, or certain strings within that (e.g., array indices). This is a
906 linked list of substrings whose type is given by the type field. */
907 struct string {
908 struct string *next;
909 enum elementtype {
910 S_TEXT, S_BITSTRING, S_BITSPLICE, S_PARAMETER, S_FUNCTIONCALL, S_ARRAY
911 } type;
912 union value { /* The fields here correspond to the enum values. */
913 char *text; /* plain text */
914 struct bits *bits; /* $x where x is a bitfield */
915 struct bitsplice *bitsplice; /* $[...] */
916 struct arg *parameter; /* $x where x is a parameter */
917 struct functioncall *functioncall; /* $func(...) */
918 struct array *array; /* {...}[...] */
919 } value;
920 };
921
922 /* The representation of a function call $func(...) in the description of a
923 function value. */
924 struct functioncall {
925 struct function *function;
926 struct stringlist *args;
927 };
928
929 /* The representation of an array selection {...|...}[...] in the description
930 of a function value. tempno is used when constructing a C variable name
931 that will contain the strings or numbers in an array. */
932 struct array {
933 struct string *index; /* what's between [...] */
934 struct stringlist *elements; /* what's between {...} */
935 enum type type; /* the type of each element */
936 int tempno;
937 };
938
939 /* A list of strings, being the list of arguments in a function call or the
940 list of elements of an array. This is a linked list of linked lists. */
941 struct stringlist {
942 struct stringlist *next;
943 enum type type;
944 struct string *string;
945 };
946
947
948 /* The following are the only characters with special meaning at the top level
949 of parsing of a function value. When parsing arrays or function calls,
950 other characters become special. */
951 #define MAKESTRING_MAGIC "${"/*}*/
952
953
954 /* Parse a function return-value string or substring and make a struct string
955 list for it. The string starts at *stringp and ends at a \0 or at any
956 character in the `magic' string other than { or $. *stringp is updated
957 to point to the terminating character. The parsed representation is put
958 at *stringlink. `fp' is the function whose return value is being parsed.
959 `targettype' is the expected type of the result, if known.
960 The return value is the actual type. */
961 enum type makestring(struct function *fp, struct string **stringlink,
962 char **stringp, char *magic, enum type targettype) {
963 char *p, *q;
964 struct string *sp, **firststringlink;
965 int n, components;
966 int parenlevel = 0;
967 enum type t = targettype, newt;
968
969 if (magic == NULL)
970 magic = MAKESTRING_MAGIC;
971 p = *stringp;
972 firststringlink = stringlink;
973 components = 0;
974 while (*p != '\0') {
975 sp = xmalloc(sizeof *sp);
976 q = p;
977 n = 0;
978 do {
979 if (strchr(magic, *q) != NULL) {
980 if (*q != ')' || parenlevel == 0)
981 break;
982 }
983 switch (*q) {
984 case '(':
985 parenlevel++; break;
986 case ')':
987 parenlevel--; break;
988 case '\\':
989 if (q[1] != '\0')
990 q++;
991 break;
992 }
993 n++;
994 } while (*++q != '\0');
995 if (n > 0) {
996 sp->type = S_TEXT;
997 sp->value.text = q = xmalloc(n + 1);
998 do {
999 if (*p == '\\')
1000 p++;
1001 *q++ = *p++;
1002 } while (--n > 0);
1003 *q = '\0';
1004 newt = t;
1005 } else if (*p == '$') {
1006 if (parsedollar(fp, &p, sp) != 0)
1007 return T_ERROR;
1008 switch (sp->type) {
1009 case S_BITSTRING:
1010 case S_BITSPLICE:
1011 newt = T_INTEGER;
1012 break;
1013 case S_PARAMETER:
1014 newt = sp->value.parameter->type;
1015 break;
1016 case S_FUNCTIONCALL:
1017 newt = sp->value.functioncall->function->type;
1018 break;
1019 default:
1020 fprintf(stderr, "makestring type %d\n", sp->type);
1021 abort();
1022 }
1023 } else if (*p == '{'/*}*/) {
1024 if (parsearray(fp, &p, sp, t) != 0)
1025 return T_ERROR;
1026 newt = sp->value.array->type;
1027 } else {
1028 free(sp);
1029 break;
1030 }
1031 if (t == T_UNKNOWN)
1032 t = newt;
1033 else if (newt != T_UNKNOWN && t != newt) {
1034 if (stringlink == firststringlink) {
1035 fprintf(stderr, "%s: %s(%d): expected %s type:\n", progname,
1036 filename, lineno, typename[t]);
1037 showstringelement(stderr, sp);
1038 return T_ERROR;
1039 }
1040 *stringlink = NULL;
1041 fprintf(stderr, "%s: %s(%d): mixed types in string:\n",
1042 progname, filename, lineno);
1043 showstring(stderr, *firststringlink);
1044 fprintf(stderr, " -- %s\n", typename[t]);
1045 showstringelement(stderr, sp);
1046 fprintf(stderr, " -- %s\n", typename[newt]);
1047 return T_ERROR;
1048 }
1049 *stringlink = sp;
1050 stringlink = &sp->next;
1051 components++;
1052 }
1053 *stringlink = NULL;
1054 *stringp = p;
1055 if (components >= MAXBITS) {
1056 fprintf(stderr, "%s: %s(%d): excessively complicated string\n",
1057 progname, filename, lineno);
1058 return T_ERROR;
1059 }
1060 componentbits |= 1 << components;
1061 return t;
1062 }
1063
1064
1065 /* Parse a $ operation at **stringp and update *stringp to point past it.
1066 `fp' is the function whose return value is being parsed. The parsed
1067 item will be put at *sp. Return 0 on success, nonzero on error. */
1068 int parsedollar(struct function *fp, char **stringp, struct string *sp) {
1069 char *p, *start;
1070
1071 p = *stringp;
1072 assert(*p == '$');
1073 start = ++p;
1074 if (*p == '[')
1075 p++;
1076 while (isalnum(*p) || *p == '_')
1077 p++;
1078 if (*start == '[') {
1079 if (*p != ']') {
1080 fprintf(stderr, "%s: %s(%d): missing ] or bad character in $[\n",
1081 progname, filename, lineno);
1082 return 1;
1083 }
1084 *stringp = p + 1;
1085 return parsebitsplice(fp, start + 1, p - start - 1, sp);
1086 }
1087 if (p == start) {
1088 fprintf(stderr, "%s: %s(%d): missing identifier after $\n", progname,
1089 filename, lineno);
1090 return 1;
1091 }
1092 if (p == start + 1) {
1093 if (findvariable(fp, *start, sp) != 0)
1094 return 1;
1095 } else {
1096 if (parsefunctioncall(fp, start, &p, sp) != 0)
1097 return 1;
1098 }
1099 *stringp = p;
1100 return 0;
1101 }
1102
1103
1104 /* The representation of a $[...] bitsplice. It is parsed into a
1105 struct entry just as if it were a bitfield parameter, then analysed
1106 into a chain of struct bitsplicebits. These in conjunction with
1107 the constant portion of the struct entry will allow the bitsplice to
1108 be compiled. Each bitsplicebits element represents either a numeric
1109 argument to the current function, in which case it will be shifted
1110 into place; or a bitfield name from the bitfield description of the
1111 current function, in which case it will be shifted by the difference
1112 between the position of the bitfield in the argument and the position
1113 it occurs in the bitsplice. `shift' indicates how much to shift left
1114 the associated value; if it is negative the value is shifted right.
1115 For instance, in a function like this:
1116 %oh xx00(%y) $[yyxx]
1117 the bitsplicebits for y will have shift = 2 and value.arg pointing to y,
1118 and those for x will have shift = -2 and value.mask = binary 1100.
1119 As an optimisation, contiguous bitfields that are also contiguous in the
1120 bitsplice will be combined. For instance:
1121 %oh xxyy00 $[0xxyy0]
1122 will compile the same code as:
1123 %oh zzzz00 $[0zzzz0].
1124 As another optimisation, a bitfield that occupies the entire bitstring
1125 for a function will be treated like a parameter in that it will not be
1126 masked in the bitsplice. For instance:
1127 %oh xxxxxx $[0xxxxxx0]
1128 will compile the same code as:
1129 %oh (%x) $[0xxxxxx0]. */
1130 struct bitsplice {
1131 struct entry entry;
1132 int nbits;
1133 struct bitsplicebits *splice;
1134 };
1135 struct bitsplicebits {
1136 struct bitsplicebits *next;
1137 int shift;
1138 enum elementtype type;
1139 union {
1140 struct arg *arg;
1141 bits mask;
1142 } value;
1143 };
1144
1145
1146 int parsebitsplice(struct function *fp, char *bitstring, int nbits,
1147 struct string *sp) {
1148 struct bitsplice *splicep;
1149 struct bitsplicebits *bsp, *lastbsp, **bspp;
1150 struct bits *bp;
1151 int shift, nfrombits, ntobits;
1152 bits allbits, b;
1153
1154 splicep = xmalloc(sizeof *splicep);
1155 splicep->nbits = nbits;
1156 if (parseentrybits(&splicep->entry, bitstring, nbits, 1) != 0)
1157 return 1;
1158 bspp = &splicep->splice;
1159 lastbsp = NULL;
1160 for (bp = splicep->entry.bits; bp != NULL; bp = bp->next) {
1161 if (findvariable(fp, bp->name, sp) != 0)
1162 return 1;
1163 shift = bp->shift;
1164 if (sp->type == S_BITSTRING) {
1165 nfrombits = bitcount(sp->value.bits->mask);
1166 ntobits = bitcount(bp->mask);
1167 if (warnings) {
1168 if (nfrombits != ntobits) {
1169 fprintf(stderr, "%s: %s(%d): warning: "
1170 "bitstring $%c %ser than its place "
1171 "in bitsplice\n",
1172 progname, filename, lineno, bp->name,
1173 (nfrombits > ntobits) ? "bigg" : "small");
1174 }
1175 }
1176 shift -= sp->value.bits->shift;
1177
1178 /* See if this bitfield can be combined with a previous contiguous
1179 bitfield. */
1180 if (lastbsp != NULL && lastbsp->type == S_BITSTRING
1181 && lastbsp->shift == shift) {
1182 lastbsp->value.mask |= sp->value.bits->mask;
1183 continue;
1184 }
1185 } else {
1186 assert(sp->type == S_PARAMETER);
1187 if (sp->value.parameter->type != T_INTEGER) {
1188 fprintf(stderr,
1189 "%s: %s(%d): variable %c in $[...] should be integer\n",
1190 progname, filename, lineno, sp->value.parameter->name);
1191 return 1;
1192 }
1193 }
1194 *bspp = bsp = xmalloc(sizeof *bsp);
1195 bsp->type = sp->type;
1196 bsp->shift = shift;
1197 if (sp->type == S_PARAMETER)
1198 bsp->value.arg = sp->value.parameter;
1199 else
1200 bsp->value.mask = sp->value.bits->mask;
1201 bspp = &bsp->next;
1202 lastbsp = bsp;
1203 }
1204 *bspp = NULL;
1205
1206 /* Look for a spliced element that is the entire bitstring argument to
1207 this function and therefore doesn't need to be masked. */
1208 allbits = allbitsset(fp->nbits);
1209 for (bsp = splicep->splice; bsp != NULL; bsp = bsp->next) {
1210 if (bsp->type == S_BITSTRING) {
1211 for (b = bsp->value.mask; b != 0 && !(b & 1); b >>= 1) ;
1212 if (b == allbits)
1213 bsp->value.mask = 0;
1214 }
1215 }
1216 sp->type = S_BITSPLICE;
1217 sp->value.bitsplice = splicep;
1218 return 0;
1219 }
1220
1221
1222 int findvariable(struct function *fp, int name, struct string *sp) {
1223 struct bits *bp;
1224 struct arg *ap;
1225
1226 for (bp = fp->last->bits; bp != NULL; bp = bp->next) {
1227 if (bp->name == name) {
1228 sp->type = S_BITSTRING;
1229 sp->value.bits = bp;
1230 return 0;
1231 }
1232 }
1233 for (ap = fp->args; ap != NULL; ap = ap->next) {
1234 if (ap->name == name) {
1235 sp->type = S_PARAMETER;
1236 sp->value.parameter = ap;
1237 return 0;
1238 }
1239 }
1240 fprintf(stderr, "%s: %s(%d): undefined parameter %c\n", progname, filename,
1241 lineno, name);
1242 return 1;
1243 }
1244
1245
1246 int parsefunctioncall(struct function *fp, char *start, char **stringp,
1247 struct string *sp) {
1248 char *p;
1249 struct functioncall *fcp;
1250 struct stringlist **arglink, *arg;
1251 enum type t;
1252
1253 p = *stringp;
1254 if (*p != '(') {
1255 fprintf(stderr, "%s: %s(%d): missing ( after function %.*s\n", progname,
1256 filename, lineno, (int)(p - start), start);
1257 return 1;
1258 }
1259 sp->type = S_FUNCTIONCALL;
1260 sp->value.functioncall = fcp = xmalloc(sizeof *fcp);
1261 *p = '\0'; /* Ugly. */
1262 fcp->function = findfunction(start);
1263 *p = '(';
1264 arglink = &fcp->args;
1265 if (*++p != ')') {
1266 while (1) {
1267 arg = xmalloc(sizeof *arg);
1268 t = makestring(fp, &arg->string, &p, MAKESTRING_MAGIC ",)",
1269 T_UNKNOWN);
1270 if (t == T_ERROR)
1271 return 1;
1272 arg->type = t;
1273 *arglink = arg;
1274 arglink = &arg->next;
1275 if (*p == ')')
1276 break;
1277 assert(*p == ',');
1278 p++;
1279 }
1280 }
1281 *arglink = NULL;
1282 assert(*p == ')');
1283 *stringp = p + 1;
1284 return 0;
1285 }
1286
1287
1288 int parsearray(struct function *fp, char **stringp, struct string *sp,
1289 enum type t) {
1290 char *p;
1291 struct array *ap;
1292 struct stringlist **elementlink, *element;
1293
1294 p = *stringp;
1295 assert(*p == '{'/*}*/);
1296 sp->type = S_ARRAY;
1297 sp->value.array = ap = xmalloc(sizeof *ap);
1298 ap->tempno = -1;
1299 elementlink = &ap->elements;
1300 ap->type = t;
1301 if (*++p != /*{*/'}') {
1302 while (1) {
1303 element = xmalloc(sizeof *element);
1304 t = makestring(fp, &element->string, &p,
1305 MAKESTRING_MAGIC /*{*/"|}", t);
1306 if (t == T_ERROR)
1307 return 1;
1308 element->type = t;
1309 if (ap->type == T_UNKNOWN)
1310 ap->type = t;
1311 else if (t != T_UNKNOWN && ap->type != t) {
1312 fprintf(stderr, "%s: %s(%d): mixed types in array:\n",
1313 progname, filename, lineno);
1314 showstring(stderr, ap->elements->string);
1315 fprintf(stderr, " -- %s\n", typename[ap->type]);
1316 showstring(stderr, element->string);
1317 fprintf(stderr, " -- %s\n", typename[t]);
1318 return 1;
1319 }
1320 *elementlink = element;
1321 elementlink = &element->next;
1322 if (*p == /*{*/'}')
1323 break;
1324 assert(*p == '|');
1325 p++;
1326 }
1327 }
1328 *elementlink = NULL;
1329 assert(*p == /*{*/'}');
1330 if (*++p != '[') {
1331 fprintf(stderr, "%s: %s(%d): missing [index] after array\n",
1332 progname, filename, lineno);
1333 return 1;
1334 }
1335 ++p;
1336 t = makestring(fp, &ap->index, &p, MAKESTRING_MAGIC "]", T_INTEGER);
1337 if (t == T_ERROR)
1338 return 1;
1339 if (t == T_STRING) {
1340 fprintf(stderr, "%s: %s(%d): array index cannot be string:\n",
1341 progname, filename, lineno);
1342 showstring(stderr, ap->index);
1343 return 1;
1344 }
1345 if (*p != ']') {
1346 fprintf(stderr, "%s: %s(%d): [ without ]\n", progname, filename,
1347 lineno);
1348 return 1;
1349 }
1350 *stringp = p + 1;
1351 return 0;
1352 }
1353
1354
1355 void dumpfunctions() {
1356 struct function *fp;
1357
1358 for (fp = functions; fp != NULL; fp = fp->next)
1359 dumpfunction(fp);
1360 }
1361
1362
1363 void dumpfunction(struct function *fp) {
1364 struct entry *ep;
1365
1366 for (ep = fp->first; ep != NULL; ep = ep->next)
1367 showentry(stderr, fp, ep, 0);
1368 }
1369
1370
1371 /* Entries are not shown exactly as they would be input, since \ would
1372 need to be provided before some characters such as $ or {. But the
1373 characters "|},]" pose a problem since a \ is only needed in certain
1374 contexts and is annoying otherwise. It's not worth doing this right,
1375 since it's only used for error messages. */
1376 void showentry(FILE *f, struct function *fp, struct entry *ep, bits highlight) {
1377 if (fp->type == T_INTEGER)
1378 putc('%', f);
1379 fprintf(f, "%-*s ", maxfunctionname + 1, fp->name);
1380 if (fp->nbits == 0 && fp->nargs == 0)
1381 fprintf(f, "%-*s", maxargwidth, "()");
1382 else {
1383 showbits(f, ep, fp->nbits, 0);
1384 showargs(f, fp->args, maxargwidth - fp->nbits);
1385 }
1386 putc(' ', f);
1387 showstring(f, ep->string);
1388 putc('\n', f);
1389 if (highlight != 0) {
1390 fprintf(f, "%-*s ", maxfunctionname + 1, "");
1391 showbits(f, ep, fp->nbits, highlight);
1392 putc('\n', f);
1393 }
1394 }
1395
1396
1397 void showbits(FILE *f, struct entry *ep, int nbits, bits highlight) {
1398 struct bits *bp;
1399 bits i, value;
1400 char zero, one;
1401
1402 if (nbits == 0)
1403 return;
1404 i = 1 << (nbits - 1);
1405 bp = ep->bits;
1406 if (highlight) {
1407 value = highlight;
1408 zero = ' ';
1409 one = '^';
1410 } else {
1411 value = ep->value;
1412 zero = '0';
1413 one = '1';
1414 }
1415 do {
1416 if (highlight != 0 || (ep->mask & i)) {
1417 putc((value & i) ? one : zero, f);
1418 i >>= 1;
1419 } else {
1420 assert(bp != NULL && (bp->mask & i));
1421 do {
1422 putc(bp->name, f);
1423 i >>= 1;
1424 } while (bp->mask & i);
1425 bp = bp->next;
1426 }
1427 } while (i != 0);
1428 }
1429
1430
1431 void showargs(FILE *f, struct arg *ap, int fieldwidth) {
1432 int width;
1433 int lastc;
1434 int isint;
1435
1436 if (ap == NULL)
1437 width = 0;
1438 else {
1439 width = 1;
1440 lastc = '(';
1441 do {
1442 isint = (ap->type == T_INTEGER);
1443 fprintf(f, "%c%s%c", lastc, isint ? "%" : "", ap->name);
1444 width += 2 + isint;
1445 ap = ap->next;
1446 lastc = ',';
1447 } while (ap != NULL);
1448 putc(')', f);
1449 }
1450 fprintf(f, "%-*s", fieldwidth - width, "");
1451 }
1452
1453
1454 void showstring(FILE *f, struct string *sp) {
1455 for ( ; sp != NULL; sp = sp->next)
1456 showstringelement(f, sp);
1457 }
1458
1459
1460 void showstringelement(FILE *f, struct string *sp) {
1461 struct bitsplice *bsp;
1462
1463 switch (sp->type) {
1464 case S_TEXT:
1465 fputs(sp->value.text, f);
1466 break;
1467 case S_BITSTRING:
1468 fprintf(f, "$%c", sp->value.bits->name);
1469 break;
1470 case S_BITSPLICE:
1471 fprintf(f, "$[");
1472 bsp = sp->value.bitsplice;
1473 showbits(f, &bsp->entry, bsp->nbits, 0);
1474 fprintf(f, "]");
1475 break;
1476 case S_PARAMETER:
1477 fprintf(f, "$%c", sp->value.parameter->name);
1478 break;
1479 case S_FUNCTIONCALL:
1480 showfunctioncall(f, sp->value.functioncall);
1481 break;
1482 case S_ARRAY:
1483 showarray(f, sp->value.array);
1484 break;
1485 default:
1486 fprintf(stderr, "showstring case %d\n", sp->type);
1487 abort();
1488 }
1489 }
1490
1491
1492 void showfunctioncall(FILE *f, struct functioncall *fcp) {
1493 struct stringlist *sp;
1494 char *last;
1495
1496 fprintf(f, "$%s(", fcp->function->name);
1497 last = "";
1498 for (sp = fcp->args; sp != NULL; sp = sp->next) {
1499 fputs(last, f);
1500 last = ",";
1501 showstring(f, sp->string);
1502 }
1503 putc(')', f);
1504 }
1505
1506
1507 void showarray(FILE *f, struct array *ap) {
1508 struct stringlist *sp;
1509 char *last;
1510
1511 putc('{'/*}*/, f);
1512 last = "";
1513 for (sp = ap->elements; sp != NULL; sp = sp->next) {
1514 fputs(last, f);
1515 last = "|";
1516 showstring(f, sp->string);
1517 }
1518 fputs(/*{*/"}[", f);
1519 showstring(f, ap->index);
1520 putc(']', f);
1521 }
1522
1523
1524 const char commonpreamble[] = "\
1525 typedef %s bits;\n\
1526 \n\
1527 ";
1528
1529 const char concatpreamble[] = "\
1530 static char *dis_buf;\n\
1531 static int dis_bufindex, dis_buflen;\n\
1532 \n\
1533 void *dis_alloc(size_t size)\n\
1534 {\n\
1535 void *p;\n\
1536 int newindex = dis_bufindex + size;\n\
1537 if (newindex > dis_buflen) {\n\
1538 dis_buflen = newindex * 4;\n\
1539 dis_buf = malloc(dis_buflen);\n\
1540 /* We can't use realloc because there might be pointers extant into\n\
1541 the old buffer. So we waste the memory of the old buffer. We\n\
1542 should soon reach an adequate buffer size and stop leaking. */\n\
1543 if (dis_buf == 0) {\n\
1544 perror(\"malloc\");\n\
1545 exit(1);\n\
1546 }\n\
1547 dis_bufindex = 0;\n\
1548 }\n\
1549 p = dis_buf + dis_bufindex;\n\
1550 dis_bufindex = newindex;\n\
1551 return p;\n\
1552 }\n\
1553 \n\
1554 void dis_done()\n\
1555 {\n\
1556 dis_bufindex = 0;\n\
1557 }\n\
1558 \n\
1559 ";
1560
1561 const char concatdeclarations[] = "\
1562 #include <string.h>\n\
1563 #include <stdlib.h>\n\
1564 #include <sys/errno.h>\n\
1565 \n\
1566 extern void *dis_realloc(void *p, size_t size); /* User-provided. */\n\
1567 void *dis_alloc(size_t size);\n\
1568 void dis_done(void);\n\
1569 ";
1570
1571 const char nonconcatpreamble[] = "\
1572 void dis_done() {}\n\
1573 ";
1574
1575
1576 int outputfunctions() {
1577 struct function *fp;
1578
1579 outputidentity(stdout);
1580 if (headerfilename != NULL) {
1581 if ((headerfile = fopen(headerfilename, "w")) == NULL) {
1582 fprintf(stderr, "%s: create %s: %s\n", progname, headerfilename,
1583 strerror(errno));
1584 return 1;
1585 }
1586 outputidentity(headerfile);
1587 fprintf(headerfile, commonpreamble, bitstype);
1588 printf("\n#include \"%s\"\n", headerfilename);
1589 } else
1590 printf(commonpreamble, bitstype);
1591 findarrays();
1592 if (outputdeclarations() != 0)
1593 return 1;
1594 outputconcats();
1595 for (fp = functions; fp != NULL; fp = fp->next) {
1596 if (fp->isarray)
1597 functionarray(fp);
1598 }
1599 for (fp = functions; fp != NULL; fp = fp->next) {
1600 if (fp->first != NULL && !fp->isarray) {
1601 if (outputfunction(fp) != 0)
1602 return 1;
1603 }
1604 }
1605 return 0;
1606 }
1607
1608
1609 void outputidentity(FILE *f) {
1610 char **p;
1611
1612 fprintf(f, "/*\n * This file was generated by:\n *");
1613 for (p = global_argv; *p != NULL; p++)
1614 fprintf(f, " %s", *p);
1615 fprintf(f, "\n */\n\n");
1616 }
1617
1618
1619 int outputdeclarations() {
1620 FILE *f = headerfile ? headerfile : stdout;
1621 struct function *fp;
1622
1623 for (fp = functions; fp != NULL; fp = fp->next) {
1624 if (fp->type != T_UNKNOWN) {
1625 if (fp->isarray) {
1626 fprintf(f, "extern ");
1627 if (fp->fixedlength > 0)
1628 fprintf(f, "char %s[][%d]", fp->name, fp->fixedlength);
1629 else {
1630 compiletype(f, &fp->type);
1631 fprintf(f, "%s[]", fp->name);
1632 }
1633 } else
1634 functionheader(f, fp);
1635 fprintf(f, ";\n");
1636 }
1637 }
1638 return 0;
1639 }
1640
1641
1642 void outputconcats() {
1643 int i;
1644
1645 if (componentbits & ~3) {
1646 fputs(concatdeclarations, headerfile ? headerfile : stdout);
1647 fputs(concatpreamble, stdout);
1648 } else
1649 fputs(nonconcatpreamble, stdout);
1650 for (i = 2; i < MAXBITS; i++) {
1651 if (componentbits & (1 << i))
1652 outputconcat(i);
1653 }
1654 }
1655
1656
1657 void outputconcat(int n) {
1658 int i;
1659 char *last;
1660
1661 assert(n > 1);
1662 if (headerfile) {
1663 outputconcatheader(headerfile, n);
1664 fprintf(headerfile, ";\n");
1665 }
1666 outputconcatheader(stdout, n);
1667 printf("\n{\n void *p;\n int len = ");
1668 last = "";
1669 for (i = 0; i < n; i++) {
1670 printf("%sstrlen(p%d)", last, i);
1671 last = " + ";
1672 }
1673 printf(";\n p = dis_alloc(len + 1);\n return ");
1674 for (i = 1; i < n; i++)
1675 printf("strcat(");
1676 printf("strcpy(p, p0)");
1677 for (i = 1; i < n; i++)
1678 printf(", p%d)", i);
1679 printf(";\n}\n\n");
1680 }
1681
1682
1683 void outputconcatheader(FILE *f, int n) {
1684 int i;
1685 char *last = "";
1686
1687 fprintf(f, "char *dis_concat%d(", n);
1688 for (i = 0; i < n; i++) {
1689 fprintf(f, "%schar *p%d", last, i);
1690 last = ", ";
1691 }
1692 fprintf(f, ")");
1693 }
1694
1695
1696 void findarrays() {
1697 struct function *fp;
1698 struct entry *ep;
1699 struct string *estr, *indexstr;
1700 struct bits *bp;
1701
1702 for (fp = functions; fp != NULL; fp = fp->next) {
1703 if (fp->nbits > 0 && fp->nargs > 0)
1704 continue;
1705 if (fp->nargs > 1)
1706 continue;
1707 ep = fp->first;
1708 if (ep == NULL || ep->next != NULL)
1709 continue;
1710 estr = ep->string;
1711 if (estr == NULL || estr->next != NULL || estr->type != S_ARRAY)
1712 continue;
1713 indexstr = estr->value.array->index;
1714 if (indexstr->next != NULL)
1715 continue;
1716 if (fp->nbits > 0) {
1717 bp = ep->bits;
1718 if (bp == NULL || bp->next != NULL || bp->shift != 0)
1719 continue;
1720 if (bp->mask != allbitsset(fp->nbits))
1721 continue;
1722 if (indexstr->type != S_BITSTRING || indexstr->value.bits != bp)
1723 continue;
1724 } else {
1725 if (indexstr->type != S_PARAMETER
1726 || indexstr->value.parameter != fp->args)
1727 continue;
1728 }
1729 if (!simplearray(estr->value.array))
1730 continue;
1731 fp->isarray = 1;
1732 fp->fixedlength =
1733 (fp->type == T_INTEGER) ? 0 : checkfixedlength(estr->value.array);
1734 }
1735 }
1736
1737
1738 int checkfixedlength(struct array *ap) {
1739 int len, maxlen, wasted, n;
1740 struct stringlist *lp;
1741
1742 maxlen = 0;
1743 for (lp = ap->elements; lp != NULL; lp = lp->next) {
1744 if (lp->string == NULL)
1745 continue;
1746 assert(lp->string->type == S_TEXT);
1747 len = strlen(lp->string->value.text);
1748 if (len > maxlen)
1749 maxlen = len;
1750 }
1751 for (wasted = n = 0, lp = ap->elements; lp != NULL; n++, lp = lp->next) {
1752 if (lp->string == NULL)
1753 continue;
1754 wasted += maxlen - strlen(lp->string->value.text);
1755 }
1756 if (wasted < n * sizeof(char *)) /* Should be target's sizeof. */
1757 return maxlen + 1;
1758 return 0;
1759 }
1760
1761
1762 int outputfunction(struct function *fp) {
1763 printf("\n");
1764 functionheader(stdout, fp);
1765 printf("\n{\n"/*}*/);
1766 switch (functionswitch(fp, 0, 0)) {
1767 case -1:
1768 return 1;
1769 case 0:
1770 if (warnings) {
1771 fprintf(stderr, "%s: warning: not all cases of %s covered\n",
1772 progname, fp->name);
1773 }
1774 }
1775 printf(/*{*/"}\n");
1776 return 0;
1777 }
1778
1779
1780 void functionarray(struct function *fp) {
1781 struct array *ap;
1782
1783 ap = fp->first->string->value.array;
1784 printf("\n");
1785 compilesimplearray(&fp->type, fp->name, 0, ap);
1786 }
1787
1788
1789 void functionheader(FILE *f, struct function *fp) {
1790 char *last;
1791 struct arg *ap;
1792
1793 compiletype(f, &fp->type);
1794 fprintf(f, "%s(", fp->name);
1795 last = "";
1796 if (fp->nbits > 0) {
1797 fprintf(f, "bits code");
1798 last = ", ";
1799 }
1800 for (ap = fp->args; ap != NULL; ap = ap->next) {
1801 fprintf(f, "%s", last);
1802 compiletype(f, &ap->type);
1803 putc(ap->name, f);
1804 last = ", ";
1805 }
1806 if (*last == '\0')
1807 fprintf(f, "void");
1808 putc(')', f);
1809 }
1810
1811
1812 int simplearray(struct array *ap) {
1813 struct stringlist *lp;
1814
1815 for (lp = ap->elements; lp != NULL; lp = lp->next) {
1816 if (lp->string != NULL
1817 && (lp->string->next != NULL || lp->string->type != S_TEXT))
1818 break;
1819 }
1820 return (lp == NULL);
1821 }
1822
1823
1824 void compiletype(FILE *f, enum type *tp) {
1825 switch (*tp) {
1826 case T_UNKNOWN:
1827 *tp = T_STRING;
1828 /* Fall in... */
1829 case T_STRING:
1830 fprintf(f, "char *");
1831 break;
1832 case T_INTEGER:
1833 fprintf(f, "bits ");
1834 break;
1835 default:
1836 fprintf(stderr, "compiletype type %d\n", *tp);
1837 abort();
1838 }
1839 }
1840
1841
1842 /* Generate code for entries in function fp whose bitstring b satisfies
1843 the constraint (b & mask) == value. Return 1 if generated switch
1844 always does `return', 0 if not, -1 on error.
1845 The algorithm is as follows. Scan the eligible entries to find the
1846 largest set of bits not in the passed-in mask which always have a
1847 constant value (are not variable). One `default' entry is allowed
1848 all of whose bits are variable. For each value of the constant bits,
1849 generate a `switch' case and invoke the function recursively with
1850 that value included in the constraint parameters. The recursion
1851 stops when no set of constant bits is found, perhaps because the
1852 mask parameter has all bits set.
1853 This algorithm could be improved. Currently it will fail if there
1854 are input lines "xxyy", "00xx" and "yy00", each of which is default with
1855 respect to the others. The correct behaviour would then be to select
1856 a bit that is sometimes constant and deal with those cases first.
1857 But this problem has not yet arisen in real life. */
1858 int functionswitch(struct function *fp, bits mask, bits value) {
1859 struct entry *ep, *defaultcase;
1860 bits allbits, constbits, missingcases;
1861 int nhits, ncases, nconstbits, alwaysreturns;
1862
1863 indentation++;
1864 allbits = allbitsset(fp->nbits);
1865 constbits = allbits & ~mask;
1866 if (debug) {
1867 findent(stderr);
1868 fprintf(stderr,
1869 "functionswitch(%s): (x & 0x%lx) == 0x%lx; const == 0x%lx\n",
1870 fp->name, mask, value, constbits);
1871 }
1872 defaultcase = NULL;
1873 ncases = nhits = 0;
1874 alwaysreturns = 1;
1875 for (ep = fp->first; ep != NULL; ep = ep->next) {
1876 /* If this is not one of the entries under consideration, skip. */
1877 if (ep->done
1878 || (ep->mask & mask) != mask || (ep->value & mask) != value)
1879 continue;
1880 if (debug) {
1881 findent(stderr);
1882 showentry(stderr, fp, ep, 0);
1883 }
1884 /* If this entry has no constant bits in the still-variable portion,
1885 it's the default. */
1886 if ((constbits & ep->mask) == 0) {
1887 if (defaultcase != NULL) {
1888 fprintf(stderr,
1889 "%s: function %s: unable to distinguish between:\n",
1890 progname, fp->name);
1891 showentry(stderr, fp, defaultcase, 0);
1892 showentry(stderr, fp, ep, 0);
1893 return -1;
1894 }
1895 defaultcase = ep;
1896 if (debug) {
1897 findent(stderr);
1898 fprintf(stderr, "^^ default case\n");
1899 }
1900 } else {
1901 if (debug && (constbits & ~ep->mask)) {
1902 findent(stderr);
1903 fprintf(stderr, "const now 0x%lx\n", constbits & ep->mask);
1904 }
1905 constbits &= ep->mask;
1906 nhits++;
1907 }
1908 }
1909 if (nhits > 0) {
1910 indent();
1911 if (constbits == allbits)
1912 printf("switch (code) {\n"/*}*/);
1913 else
1914 printf("switch (code & 0x%lx) {\n"/*}*/, constbits);
1915 for (ep = fp->first; ep != NULL; ep = ep->next) {
1916 /* If this is not one of the entries under consideration, skip. */
1917 if ((ep->mask & mask) != mask || (ep->value & mask) != value)
1918 continue;
1919 if (ep->done || ep == defaultcase)
1920 continue;
1921 ncases++;
1922 indent();
1923 printf("case 0x%lx:\n", ep->value & constbits);
1924 switch (functionswitch(fp, mask | constbits,
1925 value | (ep->value & constbits))) {
1926 case -1:
1927 return -1;
1928 case 0:
1929 alwaysreturns = 0;
1930 indentation++; indent(); indentation--;
1931 printf("break;\n");
1932 }
1933 }
1934 indent();
1935 printf(/*{*/"}\n");
1936 }
1937 nconstbits = bitcount(constbits);
1938 missingcases = ((nconstbits == MAXBITS) ? 0 : 1 << nconstbits) - ncases;
1939 if (alwaysreturns) {
1940 switch (missingcases) {
1941 case 0:
1942 if (defaultcase != NULL) {
1943 fprintf(stderr, "%s: warning: redundant entry:\n", progname);
1944 showentry(stderr, fp, defaultcase, 0);
1945 defaultcase = NULL;
1946 }
1947 break;
1948 case 1:
1949 if (defaultcase != NULL && nconstbits != 0) {
1950 fprintf(stderr,
1951 "%s: warning: variable bit(s) could be constant:\n",
1952 progname);
1953 showentry(stderr, fp, defaultcase, constbits);
1954 break;
1955 }
1956 /* Fall in... */
1957 default:
1958 alwaysreturns = 0;
1959 }
1960 }
1961 if (defaultcase != NULL) {
1962 /* If defaultcase has some constant bits of its own, recursion will
1963 check that they have the required value. */
1964 if ((defaultcase->mask & ~mask) == 0) {
1965 alwaysreturns = 1;
1966 if (compilestring(-1, defaultcase->string, fp->type) != 0)
1967 return -1;
1968 defaultcase->done = 1;
1969 } else {
1970 indentation--;
1971 alwaysreturns = functionswitch(fp, mask, value);
1972 indentation++;
1973 }
1974 }
1975 indentation--;
1976 return alwaysreturns;
1977 }
1978
1979
1980 int compilestring(int assignto, struct string *sp, enum type type) {
1981 int tempno;
1982
1983 tempno = walkstring(sp, COUNTARRAYS, assignto);
1984 if (tempno > assignto) {
1985 indent();
1986 printf("{\n"/*}*/);
1987 indentation++;
1988 (void) walkstring(sp, DECLAREARRAYS, assignto);
1989 if (walkstring(sp, COMPILEARRAYS, assignto) < 0)
1990 return 1;
1991 }
1992 if (compilecheckedstring(assignto, sp, type) != 0)
1993 return 1;
1994 if (tempno > assignto) {
1995 indentation--;
1996 indent();
1997 printf(/*{*/"}\n");
1998 }
1999 return 0;
2000 }
2001
2002
2003 int compilecheckedstring(int assignto, struct string *sp, enum type type) {
2004 compileassign(assignto);
2005 if (compileconcat(sp, type) != 0)
2006 return 1;
2007 printf(";\n");
2008 return 0;
2009 }
2010
2011
2012 void compileassign(int assignto) {
2013 indent();
2014 if (assignto < 0)
2015 printf("return ");
2016 else {
2017 compiletemp(assignto);
2018 printf(" = ");
2019 }
2020 }
2021
2022
2023 void compiletemp(int tempno) {
2024 printf("t__%d", tempno);
2025 }
2026
2027
2028 void compiletext(char *s) {
2029 putchar('"');
2030 if (s != NULL) {
2031 for ( ; *s != '\0'; s++) {
2032 switch (*s) {
2033 case '"':
2034 case '\\':
2035 putchar('\\');
2036 }
2037 putchar(*s);
2038 }
2039 }
2040 putchar('"');
2041 }
2042
2043
2044 int compileconcat(struct string *sp, enum type type) {
2045 int elements;
2046 struct string *sp1;
2047 char *last;
2048
2049 if (sp == NULL)
2050 return compilenull(type);
2051 if (sp->next == NULL)
2052 return compilesimple(sp, type);
2053 if (type != T_INTEGER) {
2054 for (elements = 0, sp1 = sp; sp1 != NULL; elements++, sp1 = sp1->next) ;
2055 printf("dis_concat%d(", elements);
2056 }
2057 last = "";
2058 for (sp1 = sp; sp1 != NULL; sp1 = sp1->next) {
2059 printf("%s", last);
2060 if (type != T_INTEGER)
2061 last = ", ";
2062 if (sp1->type == S_ARRAY)
2063 compilearrayref(sp1->value.array);
2064 else
2065 if (compilesimple(sp1, type) != 0)
2066 return 1;
2067 }
2068 if (type != T_INTEGER)
2069 printf(")");
2070 return 0;
2071 }
2072
2073
2074 int compilenull(enum type type) {
2075 if (type == T_INTEGER) {
2076 fprintf(stderr, "%s: empty integer expression\n", progname);
2077 return 1;
2078 }
2079 printf("\"\"");
2080 return 0;
2081 }
2082
2083
2084 int compilesimple(struct string *sp, enum type type) {
2085 if (sp == NULL)
2086 return compilenull(type);
2087 switch (sp->type) {
2088 case S_TEXT:
2089 if (type == T_INTEGER)
2090 printf("%s", sp->value.text);
2091 else
2092 compiletext(sp->value.text);
2093 break;
2094 case S_BITSTRING:
2095 compilebitstring(sp->value.bits);
2096 break;
2097 case S_BITSPLICE:
2098 compilebitsplice(sp->value.bitsplice);
2099 break;
2100 case S_PARAMETER:
2101 putchar(sp->value.parameter->name);
2102 break;
2103 case S_FUNCTIONCALL:
2104 return compilefunctioncall(sp);
2105 case S_ARRAY:
2106 if (compilearrayref(sp->value.array) != 0)
2107 return 1;
2108 break;
2109 default:
2110 fprintf(stderr, "compilesimple case %d", sp->type);
2111 abort();
2112 }
2113 return 0;
2114 }
2115
2116
2117 int compilearrayref(struct array *ap) {
2118 compiletemp(ap->tempno);
2119 if (simplearray(ap)) {
2120 printf("[");
2121 if (compileconcat(ap->index, T_INTEGER) != 0)
2122 return 1;
2123 printf("]");
2124 }
2125 return 0;
2126 }
2127
2128
2129 int compilefunctioncall(struct string *sp) {
2130 struct function *fp;
2131 struct stringlist *actualp;
2132 struct arg *formalp;
2133 char *last;
2134 int nbits;
2135 enum type formaltype;
2136
2137 assert(sp->type == S_FUNCTIONCALL);
2138 fp = sp->value.functioncall->function;
2139 printf("%s%c", fp->name, fp->isarray ? '[' : '(');
2140 last = "";
2141 nbits = fp->nbits;
2142 formalp = fp->args;
2143 actualp = sp->value.functioncall->args;
2144 while (actualp != NULL) {
2145 if (nbits > 0) {
2146 nbits = 0;
2147 formaltype = T_INTEGER;
2148 } else {
2149 if (formalp == NULL) {
2150 fprintf(stderr, "%s: too many arguments to %s:\n", progname,
2151 fp->name);
2152 showstring(stderr, sp);
2153 putc('\n', stderr);
2154 return 1;
2155 }
2156 formaltype = formalp->type;
2157 formalp = formalp->next;
2158 }
2159 if (actualp->type != T_UNKNOWN && actualp->type != formaltype) {
2160 fprintf(stderr, "%s: argument to %s has the wrong type:\n",
2161 progname, fp->name);
2162 showstring(stderr, actualp->string);
2163 putc('\n', stderr);
2164 return 1;
2165 }
2166 printf("%s", last);
2167 last = ", ";
2168 if (compileconcat(actualp->string, formaltype) != 0)
2169 return 1;
2170 actualp = actualp->next;
2171 }
2172 putchar(fp->isarray ? ']' : ')');
2173 return 0;
2174 }
2175
2176
2177 int walkstring(struct string *sp, enum walkstringop op, int tempno) {
2178 struct stringlist *lp;
2179 struct array *ap;
2180
2181 for ( ; sp != NULL; sp = sp->next) {
2182 switch (sp->type) {
2183 case S_ARRAY:
2184 ap = sp->value.array;
2185 for (lp = ap->elements; lp != NULL; lp = lp->next)
2186 tempno = walkstring(lp->string, op, tempno);
2187 tempno = walkstring(ap->index, op, tempno);
2188 ap->tempno = ++tempno;
2189 switch (op) {
2190 case DECLAREARRAYS:
2191 if (simplearray(ap)) {
2192 indent();
2193 printf("static ");
2194 compilesimplearray(&ap->type, NULL, tempno, ap);
2195 } else
2196 declarearray(ap);
2197 break;
2198 case COMPILEARRAYS:
2199 if (!simplearray(ap))
2200 if (compilearray(ap) != 0)
2201 return -1;
2202 break;
2203 default:
2204 break;
2205 }
2206 break;
2207 case S_FUNCTIONCALL:
2208 for (lp = sp->value.functioncall->args; lp != NULL; lp = lp->next)
2209 tempno = walkstring(lp->string, op, tempno);
2210 break;
2211 default:
2212 break;
2213 }
2214 }
2215 return tempno;
2216 }
2217
2218
2219 int compilearray(struct array *ap) {
2220 struct stringlist *ep;
2221 int i;
2222
2223 indent();
2224 printf("switch (");
2225 if (compileconcat(ap->index, T_INTEGER) != 0)
2226 return 1;
2227 printf(") {\n"/*}*/);
2228 for (i = 0, ep = ap->elements; ep != NULL; i++, ep = ep->next) {
2229 indent();
2230 printf("case %d:\n", i);
2231 indentation++;
2232 if (compilecheckedstring(ap->tempno, ep->string, ap->type) != 0)
2233 return 1;
2234 indent();
2235 printf("break;\n");
2236 indentation--;
2237 }
2238 indent();
2239 printf(/*{*/"}\n");
2240 return 0;
2241 }
2242
2243
2244 void compilesimplearray(enum type *tp, char *name, int num, struct array *ap) {
2245 struct stringlist *lp;
2246 int fixedlength;
2247
2248 fixedlength = (*tp == T_INTEGER) ? 0 : checkfixedlength(ap);
2249 if (fixedlength > 0)
2250 printf("char ");
2251 else
2252 compiletype(stdout, tp);
2253 if (name != NULL)
2254 printf("%s", name);
2255 else
2256 compiletemp(num);
2257 printf("[]");
2258 if (fixedlength > 0)
2259 printf("[%d]", fixedlength);
2260 printf(" = {\n"/*}*/);
2261 indentation++;
2262 for (lp = ap->elements; lp != NULL; lp = lp->next) {
2263 indent();
2264 compilesimple(lp->string, lp->type);
2265 printf(",\n");
2266 }
2267 indentation--;
2268 indent();
2269 printf(/*{*/"};\n");
2270 }
2271
2272
2273 void declarearray(struct array *ap) {
2274 indent();
2275 compiletype(stdout, &ap->type);
2276 compiletemp(ap->tempno);
2277 printf(";\n");
2278 }
2279
2280
2281 void compilebitstring(struct bits *bp) {
2282 printf("(");
2283 if (bp->shift != 0)
2284 printf("(");
2285 printf("code & 0x%lx", bp->mask);
2286 if (bp->shift != 0)
2287 printf(") >> %d", bp->shift);
2288 printf(")");
2289 }
2290
2291
2292 void compilebitsplice(struct bitsplice *splicep) {
2293 struct bitsplicebits *bsp;
2294 char *last = "";
2295
2296 printf("(");
2297 for (bsp = splicep->splice; bsp != NULL; bsp = bsp->next) {
2298 printf("%s", last);
2299 last = " | ";
2300 if (bsp->type == S_PARAMETER)
2301 putchar(bsp->value.arg->name);
2302 else {
2303 assert(bsp->type == S_BITSTRING);
2304 if (bsp->value.mask == 0)
2305 printf("code");
2306 else
2307 printf("(code & 0x%lx)", bsp->value.mask);
2308 }
2309 if (bsp->shift > 0)
2310 printf(" << %d", bsp->shift);
2311 else if (bsp->shift < 0)
2312 printf(" >> %d", -bsp->shift);
2313 }
2314 if (splicep->entry.value != 0)
2315 printf("%s0x%lx", last, splicep->entry.value);
2316 printf(")");
2317 }
2318
2319
2320 int bitcount(bits x) {
2321 int nbits;
2322
2323 for (nbits = 0; x != 0; x >>= 1) {
2324 if (x & 1)
2325 nbits++;
2326 }
2327 return nbits;
2328 }
2329
2330
2331 bits allbitsset(int nbits) {
2332 return (nbits == MAXBITS) ? ~0 : (1 << nbits) - 1;
2333 }
2334
2335
2336 void findent(FILE *f) {
2337 int i;
2338
2339 for (i = 1; i < indentation; i += 2)
2340 putc('\t', f);
2341 if (i == indentation)
2342 fputs(" ", f);
2343 }
2344
2345
2346 void indent() {
2347 findent(stdout);
2348 }
2349
2350
2351 void *xrealloc(char *oldp, size_t size) {
2352 void *p;
2353
2354 if (oldp == NULL)
2355 p = malloc(size);
2356 else
2357 p = realloc(oldp, size);
2358 if (p == NULL) {
2359 fprintf(stderr, "%s: allocate of %d bytes failed: %s\n", progname,
2360 (int) size, strerror(errno));
2361 exit(1);
2362 }
2363 return p;
2364 }
2365
2366
2367 void *xmalloc(size_t size) {
2368 return xrealloc(NULL, size);
2369 }
2370
2371
2372 void *xstrdup(char *s) {
2373 char *p;
2374 size_t i = strlen(s) + 1;
2375
2376 p = xmalloc(i);
2377 strlcpy(p, s, i);
2378 return p;
2379 }
2380
2381
2382 int prematureeof() {
2383 fprintf(stderr, "%s: %s(%d): premature end of file\n", progname, filename,
2384 lineno);
2385 return 1;
2386 }