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