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