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