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