]>
git.saurik.com Git - apple/xnu.git/blob - osfmk/ddb/makedis.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
28 * Revision 1.1.1.1 1998/09/22 21:05:48 wsanchez
29 * Import of Mac OS X kernel (~semeria)
31 * Revision 1.1.1.1 1998/03/07 02:26:09 wsanchez
32 * Import of OSF Mach kernel (~mburg)
34 * Revision 1.1.2.1 1997/03/27 18:46:52 barbou
36 * [1997/03/27 13:58:42 barbou]
41 /* makedis.c - make a disassembler. */
44 By Eamonn McManus <emcmanus@gr.osf.org>, April 1995.
45 Copyright 1995 by Eamonn McManus. Non-commercial use is permitted. */
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.
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.
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
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.
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.
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.
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.
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.
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
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.
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.
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.
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.
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.
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.
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:
160 typedef unsigned long bits;
161 char *inst(bits code) {...}
163 The simplest sort of line in the description file is one that looks
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".
174 A more complex line is one looking like this:
176 inst 001aa111 {daa|cpl|scf|ccf}[$a]
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
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",
190 The description defines a helper function "reg8" like this:
192 reg8 rrr {b|c|d|e|h|l|(hl)|a}[$r]
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:
198 reg8 (%r) {b|c|d|e|h|l|(hl)|a}[$r]
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.
204 The reg8 function is used in lines like this one:
206 inst 01rrrsss ld $reg8($r),$reg8($s)
208 Thus if the argument to inst is
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
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.
218 The description also uses an external C function "hexprint" defined
221 char *hexprint(bits digits, bits n) {
222 char *p = dis_alloc(digits + 1);
223 sprintf(p, "%0*lx", (int) digits, n);
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:
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.
236 The hexprint function is used in lines like this one:
238 inst 11vvv111 rst $hexprint(2,$v << 3)
240 If the argument to inst is
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
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.
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:
255 im21l aaaaabbccddddddddddde l'$hex($[edddddddddddbbaaaaacc00000000000])
257 So 111110011000000000001 produces 10000000000000111111100000000000.
259 The $[...] operation can also be used to spell out binary constants,
260 since C has no syntax for this.
263 ...More to come... */
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.
287 #define LONG_BIT (CHAR_BIT * sizeof (long))
288 #endif /* LONG_BIT */
290 #define MAXfunction 32 /* Max function name length. */
291 #define MAXBITS LONG_BIT /* Max bitstring length. */
292 typedef unsigned long bits
;
293 enum type
{T_ERROR
, T_UNKNOWN
, T_INTEGER
, T_STRING
};
294 const char *const typename
[] = {"error", "unknown", "integer", "string"};
295 enum walkstringop
{COUNTARRAYS
, DECLAREARRAYS
, COMPILEARRAYS
};
296 char *bitstype
= "unsigned long";
298 int maxfunctionname
, maxargwidth
;
299 char *progname
= "makedis";
302 char *headerfilename
;
306 int debug
, dump
, warnings
;
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. */
323 int main(int argc
, char **argv
);
324 int makedis(FILE *f
, char *fname
);
325 struct function
*findfunction(char *function
);
326 int parseextern(struct function
*fp
, FILE *f
);
327 struct function
*makefunction(char *function
);
328 int parsebits(struct function
*fp
, char *bitstring
, int nbits
);
329 int parseentrybits(struct entry
*ep
, char *bitstring
, int nbits
, int issplice
);
330 int parsecontrol(char *name
, char *value
);
331 int parseargs(struct function
*fp
, FILE *f
, int *cp
);
332 int parsestring(struct function
*fp
, char *str
);
333 enum type
makestring(struct function
*fp
, struct string
**stringlink
,
334 char **stringp
, char *magic
, enum type targettype
);
335 int parsedollar(struct function
*fp
, char **stringp
, struct string
*sp
);
336 int parsebitsplice(struct function
*fp
, char *bitstring
, int nbits
,
338 int findvariable(struct function
*fp
, int name
, struct string
*sp
);
339 int parsefunctioncall(struct function
*fp
, char *start
, char **stringp
,
341 int parsearray(struct function
*fp
, char **stringp
, struct string
*sp
,
343 void dumpfunctions(void);
344 void dumpfunction(struct function
*fp
);
345 void showentry(FILE *f
, struct function
*fp
, struct entry
*ep
, bits highlight
);
346 void showbits(FILE *f
, struct entry
*ep
, int nbits
, bits highlight
);
347 void showargs(FILE *f
, struct arg
*ap
, int fieldwidth
);
348 void showstring(FILE *f
, struct string
*sp
);
349 void showstringelement(FILE *f
, struct string
*sp
);
350 void showfunctioncall(FILE *f
, struct functioncall
*fcp
);
351 void showarray(FILE *f
, struct array
*ap
);
352 int outputfunctions(void);
353 void outputidentity(FILE *f
);
354 int outputdeclarations(void);
355 void outputconcats(void);
356 void outputconcat(int n
);
357 void outputconcatheader(FILE *f
, int n
);
358 void findarrays(void);
359 int checkfixedlength(struct array
*ap
);
360 int outputfunction(struct function
*fp
);
361 void functionarray(struct function
*fp
);
362 void functionheader(FILE *f
, struct function
*fp
);
363 int simplearray(struct array
*ap
);
364 void compiletype(FILE *f
, enum type
*tp
);
365 int functionswitch(struct function
*fp
, bits mask
, bits value
);
366 int compilestring(int assignto
, struct string
*sp
, enum type type
);
367 int compilecheckedstring(int assignto
, struct string
*sp
, enum type type
);
368 void compileassign(int assignto
);
369 void compiletemp(int tempno
);
370 void compiletext(char *s
);
371 int compileconcat(struct string
*sp
, enum type type
);
372 int compilenull(enum type type
);
373 int compilesimple(struct string
*sp
, enum type type
);
374 int compilearrayref(struct array
*ap
);
375 int compilefunctioncall(struct string
*sp
);
376 int walkstring(struct string
*sp
, enum walkstringop op
, int tempno
);
377 int compilearray(struct array
*ap
);
378 void compilesimplearray(enum type
*tp
, char *name
, int num
, struct array
*ap
);
379 void declarearray(struct array
*ap
);
380 void compilebitstring(struct bits
*bp
);
381 void compilebitsplice(struct bitsplice
*splicep
);
382 int bitcount(bits x
);
383 bits
allbitsset(int nbits
);
384 void findent(FILE *f
);
386 void *xrealloc(char *oldp
, size_t size
);
387 void *xmalloc(size_t size
);
388 void *xstrdup(char *s
);
389 int prematureeof(void);
392 int main(int argc
, char **argv
) {
399 for (i
= 1; i
< argc
&& argv
[i
][0] == '-'; i
++) {
400 switch (argv
[i
][1]) {
404 headerfilename
= argv
[i
]; break;
413 fprintf(stderr
, "Usage: %s [file]\n", progname
);
418 return makedis(stdin
, "<stdin>");
421 if ((f
= fopen(argv
[i
], "r")) == NULL
) {
422 fprintf(stderr
, "%s: %s: %s\n", progname
, argv
[i
], strerror(errno
));
425 return makedis(f
, argv
[i
]);
429 int makedis(FILE *f
, char *fname
) {
431 char function
[MAXfunction
], bitstring
[MAXBITS
];
432 static char *string
= NULL
;
438 /* Loop for every line in the description. */
440 /* Ignore initial spaces and newlines. */
441 while (isspace(c
= getc(f
)))
447 /* Ignore comments. # only allowed at start of line. */
449 while ((c
= getc(f
)) != '\n')
451 return prematureeof();
456 /* Read function name, terminated by space. */
457 for (i
= 0; i
< sizeof function
&& !isspace(c
); i
++, c
= getc(f
)) {
459 return prematureeof();
462 if (i
>= sizeof function
) {
463 fprintf(stderr
, "%s: %s(%d): function name is too long: %.*s\n",
464 progname
, filename
, lineno
, i
, function
);
469 /* Skip to next field. */
470 while (isspace(c
) && c
!= '\n')
473 /* If not a control statement, read bitstring and/or arguments. */
474 if (function
[0] == ':')
475 fp
= 0; /* Silence gcc. */
477 fp
= makefunction(function
);
481 /* Read optional bitstring. */
482 for (i
= 0; i
< sizeof bitstring
&& isalnum(c
); i
++, c
= getc(f
)) {
484 return prematureeof();
488 fprintf(stderr
, "%s: %s(%d): bit string is too long: %.*s\n",
489 progname
, filename
, lineno
, i
, bitstring
);
492 if (parsebits(fp
, bitstring
, i
) != 0)
495 /* Read optional arguments. */
496 if (parseargs(fp
, f
, &c
) != 0)
499 /* Skip to next field. */
500 while (isspace(c
) && c
!= '\n')
503 /* : indicates an external (C) function. */
505 if (parseextern(fp
, f
) != 0)
511 /* Read associated text. */
514 for ( ; c
!= '\n'; i
++, c
= getc(f
)) {
516 return prematureeof();
517 if (i
>= stringlen
) {
518 stringlen
= stringlen
* 2 + 16;
519 string
= xrealloc(string
, stringlen
);
525 switch (string
[i
- 1]) {
530 while (isspace(c
= getc(f
)) && c
!= '\n') ;
536 if (i
>= stringlen
) {
537 stringlen
= stringlen
* 2 + 16;
538 string
= xrealloc(string
, stringlen
);
542 /* Parse the line just read. */
543 if (function
[0] == ':') {
544 if (parsecontrol(function
+ 1, string
) != 0)
547 if (parsestring(fp
, string
) != 0)
553 return outputfunctions();
557 /* A function in the description file. nbits and nargs are -1 until the
558 real values are known. */
560 struct function
*next
;
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. */
571 struct function
*functions
;
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. */
576 struct function
*findfunction(char *name
) {
579 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
580 if (strcmp(fp
->name
, name
) == 0)
583 if (strlen(name
) > maxfunctionname
)
584 maxfunctionname
= strlen(name
);
585 fp
= xmalloc(sizeof *fp
);
586 fp
->next
= functions
;
588 fp
->name
= xstrdup(name
);
589 fp
->type
= T_UNKNOWN
;
590 fp
->nbits
= fp
->nargs
= -1; /* nbits will be set correctly later. */
592 fp
->first
= fp
->last
= NULL
;
597 /* Parse an external (C) function declaration. This will look something like:
599 We're called just after seeing the ':'.
600 Return 0 if parsing is successful, 1 otherwise. */
601 int parseextern(struct function
*fp
, FILE *f
) {
604 if ((c
= getc(f
)) != '\n') {
606 "%s: %s(%d): extern declaration should be a lone `:'\n",
607 progname
, filename
, lineno
);
610 if (fp
->nbits
!= 0) {
612 "%s: %s(%d): extern functions should not have bitstrings\n",
613 progname
, filename
, lineno
);
617 fp
->first
= fp
->last
= NULL
;
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). */
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. */
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.
640 struct function
*makefunction(char *name
) {
642 struct entry
*ep
= xmalloc(sizeof *ep
);
645 if (name
[0] == '%') {
650 fp
= findfunction(name
);
651 if (fp
->type
== T_UNKNOWN
)
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
]);
662 if (fp
->first
!= NULL
)
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. */
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. */
684 int parsebits(struct function
*fp
, char *bitstring
, int 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
);
694 return parseentrybits(fp
->last
, bitstring
, nbits
, 0);
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. */
700 int parseentrybits(struct entry
*ep
, char *bitstring
, int nbits
, int issplice
) {
703 bits mask
, value
, entrymask
;
707 for (i
= 0; i
< nbits
; i
++) {
708 bit
= bitstring
[nbits
- 1 - i
];
718 fprintf(stderr
, "%s: %s(%d): invalid character in bitstring: %c\n",
719 progname
, filename
, lineno
, bit
);
723 for (bp
= ep
->bits
; bp
!= NULL
; bp
= bp
->next
) {
724 if (bp
->name
== bit
) {
726 "%s: %s(%d): bitstring name %c used twice\n",
727 progname
, filename
, lineno
, bit
);
733 for (j
= i
+ 1; j
< nbits
&& bitstring
[nbits
- 1 - j
] == bit
; j
++)
735 bp
= xmalloc(sizeof *bp
);
737 bp
->mask
= entrymask
;
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". */
753 int parsecontrol(char *name
, char *value
) {
754 if (strcmp(name
, "bitstype") == 0)
755 bitstype
= xstrdup(value
);
757 fprintf(stderr
, "%s: %s(%d): unrecognised control keyword %s\n",
758 progname
, filename
, lineno
, name
);
765 /* A parameter to a function, e.g., x in:
766 %f aaa(%x) $a + $x */
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. */
781 int parseargs(struct function
*fp
, FILE *f
, int *cp
) {
782 struct arg
**arglink
, *ap
;
797 if (fp
->nargs
>= 0 && nargs
> fp
->nargs
) {
799 "%s: %s(%d): %d arg(s) instead of %d for %s\n",
800 progname
, filename
, lineno
, nargs
, fp
->nargs
,
811 if (!isalpha(name
)) {
813 "%s: %s(%d): argument should be letter: %c\n",
814 progname
, filename
, lineno
, name
);
817 for (bp
= fp
->last
->bits
; bp
!= NULL
; bp
= bp
->next
) {
818 if (bp
->name
== name
) {
820 "%s: %s(%d): %c is a bitstring and an arg\n",
821 progname
, filename
, lineno
, name
);
825 if (fp
->nargs
>= 0) {
826 if ((*arglink
)->name
!= name
) {
828 "%s: %s(%d): arg %d of %s is %c not %c\n",
829 progname
, filename
, lineno
, nargs
, fp
->name
,
830 (*arglink
)->name
, name
);
833 if ((*arglink
)->type
!= t
) {
835 "%s: %s(%d): arg %c of %s: inconsistent type\n",
836 progname
, filename
, lineno
, name
, fp
->name
);
840 for (ap
= fp
->args
; ap
!= *arglink
; ap
= ap
->next
) {
841 if (ap
->name
== name
) {
843 "%s: %s(%d): argument name %c used twice\n",
844 progname
, filename
, lineno
, name
);
848 *arglink
= xmalloc(sizeof **arglink
);
849 (*arglink
)->name
= name
;
850 (*arglink
)->type
= t
;
852 arglink
= &(*arglink
)->next
;
858 "%s: %s(%d): bad character in argument list: %c\n"
859 " (arguments must be single letters)\n",
860 progname
, filename
, lineno
, *cp
);
871 if (width
> maxargwidth
)
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
);
885 /* Parse the string describing the value of this entry for our
886 function. Return 0 on success. */
887 int parsestring(struct function
*fp
, char *str
) {
890 t
= makestring(fp
, &fp
->last
->string
, &str
, NULL
, fp
->type
);
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
);
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. */
908 S_TEXT
, S_BITSTRING
, S_BITSPLICE
, S_PARAMETER
, S_FUNCTIONCALL
, S_ARRAY
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
; /* {...}[...] */
920 /* The representation of a function call $func(...) in the description of a
922 struct functioncall
{
923 struct function
*function
;
924 struct stringlist
*args
;
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. */
931 struct string
*index
; /* what's between [...] */
932 struct stringlist
*elements
; /* what's between {...} */
933 enum type type
; /* the type of each element */
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. */
940 struct stringlist
*next
;
942 struct string
*string
;
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 "${"/*}*/
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. */
959 enum type
makestring(struct function
*fp
, struct string
**stringlink
,
960 char **stringp
, char *magic
, enum type targettype
) {
962 struct string
*sp
, **firststringlink
;
965 enum type t
= targettype
, newt
;
968 magic
= MAKESTRING_MAGIC
;
970 firststringlink
= stringlink
;
973 sp
= xmalloc(sizeof *sp
);
977 if (strchr(magic
, *q
) != NULL
) {
978 if (*q
!= ')' || parenlevel
== 0)
992 } while (*++q
!= '\0');
995 sp
->value
.text
= q
= xmalloc(n
+ 1);
1003 } else if (*p
== '$') {
1004 if (parsedollar(fp
, &p
, sp
) != 0)
1012 newt
= sp
->value
.parameter
->type
;
1014 case S_FUNCTIONCALL
:
1015 newt
= sp
->value
.functioncall
->function
->type
;
1018 fprintf(stderr
, "makestring type %d\n", sp
->type
);
1021 } else if (*p
== '{'/*}*/) {
1022 if (parsearray(fp
, &p
, sp
, t
) != 0)
1024 newt
= sp
->value
.array
->type
;
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
);
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
]);
1048 stringlink
= &sp
->next
;
1053 if (components
>= MAXBITS
) {
1054 fprintf(stderr
, "%s: %s(%d): excessively complicated string\n",
1055 progname
, filename
, lineno
);
1058 componentbits
|= 1 << components
;
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. */
1066 int parsedollar(struct function
*fp
, char **stringp
, struct string
*sp
) {
1074 while (isalnum(*p
) || *p
== '_')
1076 if (*start
== '[') {
1078 fprintf(stderr
, "%s: %s(%d): missing ] or bad character in $[\n",
1079 progname
, filename
, lineno
);
1083 return parsebitsplice(fp
, start
+ 1, p
- start
- 1, sp
);
1086 fprintf(stderr
, "%s: %s(%d): missing identifier after $\n", progname
,
1090 if (p
== start
+ 1) {
1091 if (findvariable(fp
, *start
, sp
) != 0)
1094 if (parsefunctioncall(fp
, start
, &p
, sp
) != 0)
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]. */
1131 struct bitsplicebits
*splice
;
1133 struct bitsplicebits
{
1134 struct bitsplicebits
*next
;
1136 enum elementtype type
;
1144 int parsebitsplice(struct function
*fp
, char *bitstring
, int nbits
,
1145 struct string
*sp
) {
1146 struct bitsplice
*splicep
;
1147 struct bitsplicebits
*bsp
, *lastbsp
, **bspp
;
1149 int shift
, nfrombits
, ntobits
;
1152 splicep
= xmalloc(sizeof *splicep
);
1153 splicep
->nbits
= nbits
;
1154 if (parseentrybits(&splicep
->entry
, bitstring
, nbits
, 1) != 0)
1156 bspp
= &splicep
->splice
;
1158 for (bp
= splicep
->entry
.bits
; bp
!= NULL
; bp
= bp
->next
) {
1159 if (findvariable(fp
, bp
->name
, sp
) != 0)
1162 if (sp
->type
== S_BITSTRING
) {
1163 nfrombits
= bitcount(sp
->value
.bits
->mask
);
1164 ntobits
= bitcount(bp
->mask
);
1166 if (nfrombits
!= ntobits
) {
1167 fprintf(stderr
, "%s: %s(%d): warning: "
1168 "bitstring $%c %ser than its place "
1170 progname
, filename
, lineno
, bp
->name
,
1171 (nfrombits
> ntobits
) ? "bigg" : "small");
1174 shift
-= sp
->value
.bits
->shift
;
1176 /* See if this bitfield can be combined with a previous contiguous
1178 if (lastbsp
!= NULL
&& lastbsp
->type
== S_BITSTRING
1179 && lastbsp
->shift
== shift
) {
1180 lastbsp
->value
.mask
|= sp
->value
.bits
->mask
;
1184 assert(sp
->type
== S_PARAMETER
);
1185 if (sp
->value
.parameter
->type
!= T_INTEGER
) {
1187 "%s: %s(%d): variable %c in $[...] should be integer\n",
1188 progname
, filename
, lineno
, sp
->value
.parameter
->name
);
1192 *bspp
= bsp
= xmalloc(sizeof *bsp
);
1193 bsp
->type
= sp
->type
;
1195 if (sp
->type
== S_PARAMETER
)
1196 bsp
->value
.arg
= sp
->value
.parameter
;
1198 bsp
->value
.mask
= sp
->value
.bits
->mask
;
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) ;
1211 bsp
->value
.mask
= 0;
1214 sp
->type
= S_BITSPLICE
;
1215 sp
->value
.bitsplice
= splicep
;
1220 int findvariable(struct function
*fp
, int name
, struct string
*sp
) {
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
;
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
;
1238 fprintf(stderr
, "%s: %s(%d): undefined parameter %c\n", progname
, filename
,
1244 int parsefunctioncall(struct function
*fp
, char *start
, char **stringp
,
1245 struct string
*sp
) {
1247 struct functioncall
*fcp
;
1248 struct stringlist
**arglink
, *arg
;
1253 fprintf(stderr
, "%s: %s(%d): missing ( after function %.*s\n", progname
,
1254 filename
, lineno
, p
- start
, start
);
1257 sp
->type
= S_FUNCTIONCALL
;
1258 sp
->value
.functioncall
= fcp
= xmalloc(sizeof *fcp
);
1259 *p
= '\0'; /* Ugly. */
1260 fcp
->function
= findfunction(start
);
1262 arglink
= &fcp
->args
;
1265 arg
= xmalloc(sizeof *arg
);
1266 t
= makestring(fp
, &arg
->string
, &p
, MAKESTRING_MAGIC
",)",
1272 arglink
= &arg
->next
;
1286 int parsearray(struct function
*fp
, char **stringp
, struct string
*sp
,
1290 struct stringlist
**elementlink
, *element
;
1293 assert(*p
== '{'/*}*/);
1295 sp
->value
.array
= ap
= xmalloc(sizeof *ap
);
1297 elementlink
= &ap
->elements
;
1299 if (*++p
!= /*{*/'}') {
1301 element
= xmalloc(sizeof *element
);
1302 t
= makestring(fp
, &element
->string
, &p
,
1303 MAKESTRING_MAGIC
/*{*/"|}", t
);
1307 if (ap
->type
== T_UNKNOWN
)
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
]);
1318 *elementlink
= element
;
1319 elementlink
= &element
->next
;
1326 *elementlink
= NULL
;
1327 assert(*p
== /*{*/'}');
1329 fprintf(stderr
, "%s: %s(%d): missing [index] after array\n",
1330 progname
, filename
, lineno
);
1334 t
= makestring(fp
, &ap
->index
, &p
, MAKESTRING_MAGIC
"]", T_INTEGER
);
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
);
1344 fprintf(stderr
, "%s: %s(%d): [ without ]\n", progname
, filename
,
1353 void dumpfunctions() {
1354 struct function
*fp
;
1356 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
)
1361 void dumpfunction(struct function
*fp
) {
1364 for (ep
= fp
->first
; ep
!= NULL
; ep
= ep
->next
)
1365 showentry(stderr
, fp
, ep
, 0);
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. */
1374 void showentry(FILE *f
, struct function
*fp
, struct entry
*ep
, bits highlight
) {
1375 if (fp
->type
== T_INTEGER
)
1377 fprintf(f
, "%-*s ", maxfunctionname
+ 1, fp
->name
);
1378 if (fp
->nbits
== 0 && fp
->nargs
== 0)
1379 fprintf(f
, "%-*s", maxargwidth
, "()");
1381 showbits(f
, ep
, fp
->nbits
, 0);
1382 showargs(f
, fp
->args
, maxargwidth
- fp
->nbits
);
1385 showstring(f
, ep
->string
);
1387 if (highlight
!= 0) {
1388 fprintf(f
, "%-*s ", maxfunctionname
+ 1, "");
1389 showbits(f
, ep
, fp
->nbits
, highlight
);
1395 void showbits(FILE *f
, struct entry
*ep
, int nbits
, bits highlight
) {
1402 i
= 1 << (nbits
- 1);
1414 if (highlight
!= 0 || (ep
->mask
& i
)) {
1415 putc((value
& i
) ? one
: zero
, f
);
1418 assert(bp
!= NULL
&& (bp
->mask
& i
));
1422 } while (bp
->mask
& i
);
1429 void showargs(FILE *f
, struct arg
*ap
, int fieldwidth
) {
1440 isint
= (ap
->type
== T_INTEGER
);
1441 fprintf(f
, "%c%s%c", lastc
, isint
? "%" : "", ap
->name
);
1445 } while (ap
!= NULL
);
1448 fprintf(f
, "%-*s", fieldwidth
- width
, "");
1452 void showstring(FILE *f
, struct string
*sp
) {
1453 for ( ; sp
!= NULL
; sp
= sp
->next
)
1454 showstringelement(f
, sp
);
1458 void showstringelement(FILE *f
, struct string
*sp
) {
1459 struct bitsplice
*bsp
;
1463 fputs(sp
->value
.text
, f
);
1466 fprintf(f
, "$%c", sp
->value
.bits
->name
);
1470 bsp
= sp
->value
.bitsplice
;
1471 showbits(f
, &bsp
->entry
, bsp
->nbits
, 0);
1475 fprintf(f
, "$%c", sp
->value
.parameter
->name
);
1477 case S_FUNCTIONCALL
:
1478 showfunctioncall(f
, sp
->value
.functioncall
);
1481 showarray(f
, sp
->value
.array
);
1484 fprintf(stderr
, "showstring case %d\n", sp
->type
);
1490 void showfunctioncall(FILE *f
, struct functioncall
*fcp
) {
1491 struct stringlist
*sp
;
1494 fprintf(f
, "$%s(", fcp
->function
->name
);
1496 for (sp
= fcp
->args
; sp
!= NULL
; sp
= sp
->next
) {
1499 showstring(f
, sp
->string
);
1505 void showarray(FILE *f
, struct array
*ap
) {
1506 struct stringlist
*sp
;
1511 for (sp
= ap
->elements
; sp
!= NULL
; sp
= sp
->next
) {
1514 showstring(f
, sp
->string
);
1516 fputs(/*{*/"}[", f
);
1517 showstring(f
, ap
->index
);
1522 const char commonpreamble
[] = "\
1527 const char concatpreamble
[] = "\
1528 static char *dis_buf;\n\
1529 static int dis_bufindex, dis_buflen;\n\
1531 void *dis_alloc(size_t size)\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\
1545 dis_bufindex = 0;\n\
1547 p = dis_buf + dis_bufindex;\n\
1548 dis_bufindex = newindex;\n\
1554 dis_bufindex = 0;\n\
1559 const char concatdeclarations
[] = "\
1560 #include <string.h>\n\
1561 #include <stdlib.h>\n\
1562 #include <errno.h>\n\
1564 extern void *dis_realloc(void *p, size_t size); /* User-provided. */\n\
1565 void *dis_alloc(size_t size);\n\
1566 void dis_done(void);\n\
1569 const char nonconcatpreamble
[] = "\
1570 void dis_done() {}\n\
1574 int outputfunctions() {
1575 struct function
*fp
;
1577 outputidentity(stdout
);
1578 if (headerfilename
!= NULL
) {
1579 if ((headerfile
= fopen(headerfilename
, "w")) == NULL
) {
1580 fprintf(stderr
, "%s: create %s: %s\n", progname
, headerfilename
,
1584 outputidentity(headerfile
);
1585 fprintf(headerfile
, commonpreamble
, bitstype
);
1586 printf("\n#include \"%s\"\n", headerfilename
);
1588 printf(commonpreamble
, bitstype
);
1590 if (outputdeclarations() != 0)
1593 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
1597 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
1598 if (fp
->first
!= NULL
&& !fp
->isarray
) {
1599 if (outputfunction(fp
) != 0)
1607 void outputidentity(FILE *f
) {
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");
1617 int outputdeclarations() {
1618 FILE *f
= headerfile
? headerfile
: stdout
;
1619 struct function
*fp
;
1621 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
1622 if (fp
->type
!= T_UNKNOWN
) {
1624 fprintf(f
, "extern ");
1625 if (fp
->fixedlength
> 0)
1626 fprintf(f
, "char %s[][%d]", fp
->name
, fp
->fixedlength
);
1628 compiletype(f
, &fp
->type
);
1629 fprintf(f
, "%s[]", fp
->name
);
1632 functionheader(f
, fp
);
1640 void outputconcats() {
1643 if (componentbits
& ~3) {
1644 fputs(concatdeclarations
, headerfile
? headerfile
: stdout
);
1645 fputs(concatpreamble
, stdout
);
1647 fputs(nonconcatpreamble
, stdout
);
1648 for (i
= 2; i
< MAXBITS
; i
++) {
1649 if (componentbits
& (1 << i
))
1655 void outputconcat(int n
) {
1661 outputconcatheader(headerfile
, n
);
1662 fprintf(headerfile
, ";\n");
1664 outputconcatheader(stdout
, n
);
1665 printf("\n{\n void *p;\n int len = ");
1667 for (i
= 0; i
< n
; i
++) {
1668 printf("%sstrlen(p%d)", last
, i
);
1671 printf(";\n p = dis_alloc(len + 1);\n return ");
1672 for (i
= 1; i
< n
; i
++)
1674 printf("strcpy(p, p0)");
1675 for (i
= 1; i
< n
; i
++)
1676 printf(", p%d)", i
);
1681 void outputconcatheader(FILE *f
, int n
) {
1685 fprintf(f
, "char *dis_concat%d(", n
);
1686 for (i
= 0; i
< n
; i
++) {
1687 fprintf(f
, "%schar *p%d", last
, i
);
1695 struct function
*fp
;
1697 struct string
*estr
, *indexstr
;
1700 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
1701 if (fp
->nbits
> 0 && fp
->nargs
> 0)
1706 if (ep
== NULL
|| ep
->next
!= NULL
)
1709 if (estr
== NULL
|| estr
->next
!= NULL
|| estr
->type
!= S_ARRAY
)
1711 indexstr
= estr
->value
.array
->index
;
1712 if (indexstr
->next
!= NULL
)
1714 if (fp
->nbits
> 0) {
1716 if (bp
== NULL
|| bp
->next
!= NULL
|| bp
->shift
!= 0)
1718 if (bp
->mask
!= allbitsset(fp
->nbits
))
1720 if (indexstr
->type
!= S_BITSTRING
|| indexstr
->value
.bits
!= bp
)
1723 if (indexstr
->type
!= S_PARAMETER
1724 || indexstr
->value
.parameter
!= fp
->args
)
1727 if (!simplearray(estr
->value
.array
))
1731 (fp
->type
== T_INTEGER
) ? 0 : checkfixedlength(estr
->value
.array
);
1736 int checkfixedlength(struct array
*ap
) {
1737 int len
, maxlen
, wasted
, n
;
1738 struct stringlist
*lp
;
1741 for (lp
= ap
->elements
; lp
!= NULL
; lp
= lp
->next
) {
1742 if (lp
->string
== NULL
)
1744 assert(lp
->string
->type
== S_TEXT
);
1745 len
= strlen(lp
->string
->value
.text
);
1749 for (wasted
= n
= 0, lp
= ap
->elements
; lp
!= NULL
; n
++, lp
= lp
->next
) {
1750 if (lp
->string
== NULL
)
1752 wasted
+= maxlen
- strlen(lp
->string
->value
.text
);
1754 if (wasted
< n
* sizeof(char *)) /* Should be target's sizeof. */
1760 int outputfunction(struct function
*fp
) {
1762 functionheader(stdout
, fp
);
1763 printf("\n{\n"/*}*/);
1764 switch (functionswitch(fp
, 0, 0)) {
1769 fprintf(stderr
, "%s: warning: not all cases of %s covered\n",
1770 progname
, fp
->name
);
1778 void functionarray(struct function
*fp
) {
1781 ap
= fp
->first
->string
->value
.array
;
1783 compilesimplearray(&fp
->type
, fp
->name
, 0, ap
);
1787 void functionheader(FILE *f
, struct function
*fp
) {
1791 compiletype(f
, &fp
->type
);
1792 fprintf(f
, "%s(", fp
->name
);
1794 if (fp
->nbits
> 0) {
1795 fprintf(f
, "bits code");
1798 for (ap
= fp
->args
; ap
!= NULL
; ap
= ap
->next
) {
1800 compiletype(f
, &ap
->type
);
1810 int simplearray(struct array
*ap
) {
1811 struct stringlist
*lp
;
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
))
1818 return (lp
== NULL
);
1822 void compiletype(FILE *f
, enum type
*tp
) {
1828 fprintf(f
, "char *");
1831 fprintf(f
, "bits ");
1834 fprintf(stderr
, "compiletype type %d\n", *tp
);
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. */
1856 int functionswitch(struct function
*fp
, bits mask
, bits value
) {
1857 struct entry
*ep
, *defaultcase
;
1858 bits allbits
, constbits
, missingcases
;
1859 int nhits
, ncases
, nconstbits
, alwaysreturns
;
1862 allbits
= allbitsset(fp
->nbits
);
1863 constbits
= allbits
& ~mask
;
1867 "functionswitch(%s): (x & 0x%lx) == 0x%lx; const == 0x%lx\n",
1868 fp
->name
, mask
, value
, constbits
);
1873 for (ep
= fp
->first
; ep
!= NULL
; ep
= ep
->next
) {
1874 /* If this is not one of the entries under consideration, skip. */
1876 || (ep
->mask
& mask
) != mask
|| (ep
->value
& mask
) != value
)
1880 showentry(stderr
, fp
, ep
, 0);
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
) {
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);
1896 fprintf(stderr
, "^^ default case\n");
1899 if (debug
&& (constbits
& ~ep
->mask
)) {
1901 fprintf(stderr
, "const now 0x%lx\n", constbits
& ep
->mask
);
1903 constbits
&= ep
->mask
;
1909 if (constbits
== allbits
)
1910 printf("switch (code) {\n"/*}*/);
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
)
1917 if (ep
->done
|| ep
== defaultcase
)
1921 printf("case 0x%lx:\n", ep
->value
& constbits
);
1922 switch (functionswitch(fp
, mask
| constbits
,
1923 value
| (ep
->value
& constbits
))) {
1928 indentation
++; indent(); indentation
--;
1935 nconstbits
= bitcount(constbits
);
1936 missingcases
= ((nconstbits
== MAXBITS
) ? 0 : 1 << nconstbits
) - ncases
;
1937 if (alwaysreturns
) {
1938 switch (missingcases
) {
1940 if (defaultcase
!= NULL
) {
1941 fprintf(stderr
, "%s: warning: redundant entry:\n", progname
);
1942 showentry(stderr
, fp
, defaultcase
, 0);
1947 if (defaultcase
!= NULL
&& nconstbits
!= 0) {
1949 "%s: warning: variable bit(s) could be constant:\n",
1951 showentry(stderr
, fp
, defaultcase
, constbits
);
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) {
1964 if (compilestring(-1, defaultcase
->string
, fp
->type
) != 0)
1966 defaultcase
->done
= 1;
1969 alwaysreturns
= functionswitch(fp
, mask
, value
);
1974 return alwaysreturns
;
1978 int compilestring(int assignto
, struct string
*sp
, enum type type
) {
1981 tempno
= walkstring(sp
, COUNTARRAYS
, assignto
);
1982 if (tempno
> assignto
) {
1986 (void) walkstring(sp
, DECLAREARRAYS
, assignto
);
1987 if (walkstring(sp
, COMPILEARRAYS
, assignto
) < 0)
1990 if (compilecheckedstring(assignto
, sp
, type
) != 0)
1992 if (tempno
> assignto
) {
2001 int compilecheckedstring(int assignto
, struct string
*sp
, enum type type
) {
2002 compileassign(assignto
);
2003 if (compileconcat(sp
, type
) != 0)
2010 void compileassign(int assignto
) {
2015 compiletemp(assignto
);
2021 void compiletemp(int tempno
) {
2022 printf("t__%d", tempno
);
2026 void compiletext(char *s
) {
2029 for ( ; *s
!= '\0'; s
++) {
2042 int compileconcat(struct string
*sp
, enum type type
) {
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
);
2056 for (sp1
= sp
; sp1
!= NULL
; sp1
= sp1
->next
) {
2058 if (type
!= T_INTEGER
)
2060 if (sp1
->type
== S_ARRAY
)
2061 compilearrayref(sp1
->value
.array
);
2063 if (compilesimple(sp1
, type
) != 0)
2066 if (type
!= T_INTEGER
)
2072 int compilenull(enum type type
) {
2073 if (type
== T_INTEGER
) {
2074 fprintf(stderr
, "%s: empty integer expression\n", progname
);
2082 int compilesimple(struct string
*sp
, enum type type
) {
2084 return compilenull(type
);
2087 if (type
== T_INTEGER
)
2088 printf("%s", sp
->value
.text
);
2090 compiletext(sp
->value
.text
);
2093 compilebitstring(sp
->value
.bits
);
2096 compilebitsplice(sp
->value
.bitsplice
);
2099 putchar(sp
->value
.parameter
->name
);
2101 case S_FUNCTIONCALL
:
2102 return compilefunctioncall(sp
);
2104 if (compilearrayref(sp
->value
.array
) != 0)
2108 fprintf(stderr
, "compilesimple case %d", sp
->type
);
2115 int compilearrayref(struct array
*ap
) {
2116 compiletemp(ap
->tempno
);
2117 if (simplearray(ap
)) {
2119 if (compileconcat(ap
->index
, T_INTEGER
) != 0)
2127 int compilefunctioncall(struct string
*sp
) {
2128 struct function
*fp
;
2129 struct stringlist
*actualp
;
2130 struct arg
*formalp
;
2133 enum type formaltype
;
2135 assert(sp
->type
== S_FUNCTIONCALL
);
2136 fp
= sp
->value
.functioncall
->function
;
2137 printf("%s%c", fp
->name
, fp
->isarray
? '[' : '(');
2141 actualp
= sp
->value
.functioncall
->args
;
2142 while (actualp
!= NULL
) {
2145 formaltype
= T_INTEGER
;
2147 if (formalp
== NULL
) {
2148 fprintf(stderr
, "%s: too many arguments to %s:\n", progname
,
2150 showstring(stderr
, sp
);
2154 formaltype
= formalp
->type
;
2155 formalp
= formalp
->next
;
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
);
2166 if (compileconcat(actualp
->string
, formaltype
) != 0)
2168 actualp
= actualp
->next
;
2170 putchar(fp
->isarray
? ']' : ')');
2175 int walkstring(struct string
*sp
, enum walkstringop op
, int tempno
) {
2176 struct stringlist
*lp
;
2179 for ( ; sp
!= NULL
; sp
= sp
->next
) {
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
;
2189 if (simplearray(ap
)) {
2192 compilesimplearray(&ap
->type
, NULL
, tempno
, ap
);
2197 if (!simplearray(ap
))
2198 if (compilearray(ap
) != 0)
2205 case S_FUNCTIONCALL
:
2206 for (lp
= sp
->value
.functioncall
->args
; lp
!= NULL
; lp
= lp
->next
)
2207 tempno
= walkstring(lp
->string
, op
, tempno
);
2217 int compilearray(struct array
*ap
) {
2218 struct stringlist
*ep
;
2223 if (compileconcat(ap
->index
, T_INTEGER
) != 0)
2225 printf(") {\n"/*}*/);
2226 for (i
= 0, ep
= ap
->elements
; ep
!= NULL
; i
++, ep
= ep
->next
) {
2228 printf("case %d:\n", i
);
2230 if (compilecheckedstring(ap
->tempno
, ep
->string
, ap
->type
) != 0)
2242 void compilesimplearray(enum type
*tp
, char *name
, int num
, struct array
*ap
) {
2243 struct stringlist
*lp
;
2246 fixedlength
= (*tp
== T_INTEGER
) ? 0 : checkfixedlength(ap
);
2247 if (fixedlength
> 0)
2250 compiletype(stdout
, tp
);
2256 if (fixedlength
> 0)
2257 printf("[%d]", fixedlength
);
2258 printf(" = {\n"/*}*/);
2260 for (lp
= ap
->elements
; lp
!= NULL
; lp
= lp
->next
) {
2262 compilesimple(lp
->string
, lp
->type
);
2267 printf(/*{*/"};\n");
2271 void declarearray(struct array
*ap
) {
2273 compiletype(stdout
, &ap
->type
);
2274 compiletemp(ap
->tempno
);
2279 void compilebitstring(struct bits
*bp
) {
2283 printf("code & 0x%lx", bp
->mask
);
2285 printf(") >> %d", bp
->shift
);
2290 void compilebitsplice(struct bitsplice
*splicep
) {
2291 struct bitsplicebits
*bsp
;
2295 for (bsp
= splicep
->splice
; bsp
!= NULL
; bsp
= bsp
->next
) {
2298 if (bsp
->type
== S_PARAMETER
)
2299 putchar(bsp
->value
.arg
->name
);
2301 assert(bsp
->type
== S_BITSTRING
);
2302 if (bsp
->value
.mask
== 0)
2305 printf("(code & 0x%lx)", bsp
->value
.mask
);
2308 printf(" << %d", bsp
->shift
);
2309 else if (bsp
->shift
< 0)
2310 printf(" >> %d", -bsp
->shift
);
2312 if (splicep
->entry
.value
!= 0)
2313 printf("%s0x%lx", last
, splicep
->entry
.value
);
2318 int bitcount(bits x
) {
2321 for (nbits
= 0; x
!= 0; x
>>= 1) {
2329 bits
allbitsset(int nbits
) {
2330 return (nbits
== MAXBITS
) ? ~0 : (1 << nbits
) - 1;
2334 void findent(FILE *f
) {
2337 for (i
= 1; i
< indentation
; i
+= 2)
2339 if (i
== indentation
)
2349 void *xrealloc(char *oldp
, size_t size
) {
2355 p
= realloc(oldp
, size
);
2357 fprintf(stderr
, "%s: allocate of %d bytes failed: %s\n", progname
,
2358 (int) size
, strerror(errno
));
2365 void *xmalloc(size_t size
) {
2366 return xrealloc(NULL
, size
);
2370 void *xstrdup(char *s
) {
2373 p
= xmalloc(strlen(s
) + 1);
2379 int prematureeof() {
2380 fprintf(stderr
, "%s: %s(%d): premature end of file\n", progname
, filename
,