]>
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 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
29 * Revision 1.1.1.1 1998/09/22 21:05:48 wsanchez
30 * Import of Mac OS X kernel (~semeria)
32 * Revision 1.1.1.1 1998/03/07 02:26:09 wsanchez
33 * Import of OSF Mach kernel (~mburg)
35 * Revision 1.1.2.1 1997/03/27 18:46:52 barbou
37 * [1997/03/27 13:58:42 barbou]
42 /* makedis.c - make a disassembler. */
45 By Eamonn McManus <emcmanus@gr.osf.org>, April 1995.
46 Copyright 1995 by Eamonn McManus. Non-commercial use is permitted. */
50 This program generates a disassembler in C from a file describing the
51 opcodes of the machine in question. Lines in the description file are
52 either comments beginning with #, or contain three fields, with the
53 first two being terminated by space and the third containing the rest
54 of the line. Long logical lines can be split onto several physical
55 lines by ending each one except the last with a \. A logical line
56 can also be split immediately after a |. Unlike \, | is considered
57 part of the logical line. Leading spaces on continuation lines
58 following either \ or | are ignored.
60 Here is a concise description of the meanings of the three fields.
61 Examples later will make it clearer what they are used for.
63 The first field of the three is a function name. This will produce
64 a function or array of the same name in the C output, so it should
65 not conflict with other identifiers or C keywords. By default the
66 function named returns a string (a (char *) in C), but if the first
67 field is preceded by %, the function returns an unsigned long
70 The second field describes the arguments of the function. It consists
71 of two parts, either but not both of which may be omitted. The first
72 part is a string which is a bitmask describing the first argument of
73 the function. Each character of the string represents one bit,
74 with the least significant bit being the last. A character can be
75 0 or 1, representing that constant value, or a letter, representing
76 part of a bitfield. A given bitfield consists of all of the
77 contiguous bits containing the same letter. Upper and lower case
78 letters are considered different.
80 The second part of the second field is a list of parameters
81 describing the parameters of the function, or the parameters after
82 the first if the bitfield part was present. The list is contained
83 in parentheses () and the individual parameters are separated by
84 commas. Spaces are not allowed. Each parameter name is a single
85 letter, optionally preceded by %. The parameter is an unsigned
86 long integer if % is present, otherwise a string. Again, upper and
87 lower case parameter names are different.
89 The third field describes the value of the function. If a bitmask
90 is present in the second field and it contains constant bits (0s or
91 1s), then the third field is the value of the function only in the
92 case where its first argument contains matching values in those bit
93 positions. There can be many different lines naming the same
94 function but with different bitpatterns. The generated C code will
95 arrange to return the value corresponding to the pattern that
96 matches the actual first argument of the function when it is
97 called. This argument should not have bits set in positions beyond
98 those present in the bitpattern.
100 It is only allowed for two different lines to name the same function
101 if there is a bitstring in the second field. It is not allowed for
102 two such lines to specify exactly the same constant bit values. But
103 it is allowed for a line to have all the same constant bit values as
104 another plus some extra constant values. In this case the more
105 specific line applies when all of its constant bits match, and
106 otherwise the less specific line applies.
108 Apart from the contents of the bitstring, the second field must be
109 identical on every line referring to a given function, and the
110 bitstring must always be of the same length.
112 For string-valued functions, the third field is the string value.
113 For integer-valued functions, it is a C integer expression
114 generating the value. In both cases there may be several special
117 - A $ followed by a single letter is replaced by the value of the
118 argument or bitfield with that name. The value of a bitfield is
119 shifted as if that bitfield were in the least-significant bit
120 position. Thus, a single-bit field always has value 0 or 1.
122 - A $ followed by the name of a function and an argument list in
123 parentheses () is replaced by the value returned by the function
124 with those arguments. An integer value cannot be inserted into a
125 string without being converted by a function, nor can a string
126 value be used in an integer expression.
128 - A $ followed by a bitstring enclosed in [] is replaced by the
129 value of that bitstring. The bitstring has the same syntax as in
130 the second field, described above. Each contiguous sequence of
131 the same repeated letter in the bitstring is replaced by the
132 value of the argument or bitfield-argument with that name,
133 shifted into the appropriate position.
135 - A list of strings, separated by |, enclosed in
136 {}, and followed by an integer expression enclosed in [], is
137 replaced by the string in the list whose number matches the value
138 of the expression. The first string in the list is numbered 0.
139 If there is no string corresponding to the value of the
140 expression, the behaviour is undefined. The strings in the list
141 may themselves contain $ or {} operations.
143 - A \ followed by any character is replaced by that
144 character, without regard to any meaning it may usually have.
145 This is used to obtain strings containing characters such as
146 {, $, or \. The use of backslash to split long logical
147 lines takes precedence over this use, so \\ should not appear
148 at the end of a line.
150 The third field may also be a lone colon ":", in which case the
151 function is assumed to be defined externally and only a function
152 declaration (prototype) is generated.
157 Here are some examples from the description file for the Z80
158 microprocessor. This processor has 8-bit opcodes which are
159 disassembled by a generated function "inst" which looks like this:
161 typedef unsigned long bits;
162 char *inst(bits code) {...}
164 The simplest sort of line in the description file is one that looks
169 The first field names the function, "inst". The second field
170 implies that that function has exactly one argument which is an
171 integer, and that this line specifies the value of the function
172 when this integer has the binary value 01110110 (hex 0x76). This
173 value will be the string "halt".
175 A more complex line is one looking like this:
177 inst 001aa111 {daa|cpl|scf|ccf}[$a]
179 This line is compatible with the previous one, because it has the
180 same number of bits and the constant bits are different. It
181 specifies the value of inst when its argument looks like
182 001aa111, i.e., for the binary values
186 00111111. The value of $a for these four values will be
187 respectively binary 00, 01, 10, 11, i.e., 0 to 3. The
188 corresponding values of the inst function will be "daa", "cpl",
191 The description defines a helper function "reg8" like this:
193 reg8 rrr {b|c|d|e|h|l|(hl)|a}[$r]
195 This simply selects one of the eight strings between {} depending
196 on the value of the argument, which is assumed to be a three-bit
197 value. This could just as easily have been written:
199 reg8 (%r) {b|c|d|e|h|l|(hl)|a}[$r]
201 The generated C code is the same -- in each case makedis realises
202 that the function can be represented by an array rather than
203 compiling a C function.
205 The reg8 function is used in lines like this one:
207 inst 01rrrsss ld $reg8($r),$reg8($s)
209 Thus if the argument to inst is
211 then $r is 010 (2) and $s is 011 (3). Since reg8(2) is "d" and
212 reg8(3) is "e", the value of inst with this argument will be the
215 Note that the opcode for "halt" given above matches this pattern,
216 but because the bitpattern for "halt" is more specific (has more
217 constant bits) it is the one chosen when the argument is 01110110.
219 The description also uses an external C function "hexprint" defined
222 char *hexprint(bits digits, bits n) {
223 char *p = dis_alloc(digits + 1);
224 sprintf(p, "%0*lx", (int) digits, n);
228 The value of this function is a string containing the number n
229 spelt out in hex with "digits" digits. In the description
230 file this function is declared like this:
234 The names of the parameters are not important in this case as long
235 as they are letters and are different from each other.
237 The hexprint function is used in lines like this one:
239 inst 11vvv111 rst $hexprint(2,$v << 3)
241 If the argument to inst is
243 then $v is 011 (3) and the arguments to hexprint are 2 and (3 << 3),
244 i.e., 0x18. So the value of inst with this argument will be the
247 Instead of writing $v << 3, it would be possible to write
248 $[00vvv000]. For instance when $v is binary 011, this becomes
249 00011000. The leading 0s could be omitted.
251 The $[...] operation is particularly useful for moving bits around.
252 For instance, the HP PA-RISC opcodes contain bits assigned to
253 apparently random parts of the instruction word. One of the helper
254 functions in its description file looks like this:
256 im21l aaaaabbccddddddddddde l'$hex($[edddddddddddbbaaaaacc00000000000])
258 So 111110011000000000001 produces 10000000000000111111100000000000.
260 The $[...] operation can also be used to spell out binary constants,
261 since C has no syntax for this.
264 ...More to come... */
267 - More error detection, e.g., bitstring or arg not used in entry.
268 - Better error recovery -- nearly all errors are currently fatal.
269 - Clean up type handling, which is somewhat haphazard. It works but there
270 is stuff that is surely redundant.
271 - Make generated functions void by default, with $ prefix to indicate
272 string-value. In a void function, instead of returning a string (or
273 integer) it would be output via a user-supplied function.
274 - Further optimise and tidy generated code, e.g.: arrays of one-character
275 strings could be replaced by arrays of characters; switches with just
276 one case could be replaced by ifs.
288 #define LONG_BIT (CHAR_BIT * sizeof (long))
289 #endif /* LONG_BIT */
291 #define MAXfunction 32 /* Max function name length. */
292 #define MAXBITS LONG_BIT /* Max bitstring length. */
293 typedef unsigned long bits
;
294 enum type
{T_ERROR
, T_UNKNOWN
, T_INTEGER
, T_STRING
};
295 const char *const typename
[] = {"error", "unknown", "integer", "string"};
296 enum walkstringop
{COUNTARRAYS
, DECLAREARRAYS
, COMPILEARRAYS
};
297 char *bitstype
= "unsigned long";
299 int maxfunctionname
, maxargwidth
;
300 char *progname
= "makedis";
303 char *headerfilename
;
307 int debug
, dump
, warnings
;
309 /* componentbits has a 1 bit for every possible number of strings we may want
310 to concatenate together at some stage. A separate C function is compiled
311 for each such case. */
324 int main(int argc
, char **argv
);
325 int makedis(FILE *f
, char *fname
);
326 struct function
*findfunction(char *function
);
327 int parseextern(struct function
*fp
, FILE *f
);
328 struct function
*makefunction(char *function
);
329 int parsebits(struct function
*fp
, char *bitstring
, int nbits
);
330 int parseentrybits(struct entry
*ep
, char *bitstring
, int nbits
, int issplice
);
331 int parsecontrol(char *name
, char *value
);
332 int parseargs(struct function
*fp
, FILE *f
, int *cp
);
333 int parsestring(struct function
*fp
, char *str
);
334 enum type
makestring(struct function
*fp
, struct string
**stringlink
,
335 char **stringp
, char *magic
, enum type targettype
);
336 int parsedollar(struct function
*fp
, char **stringp
, struct string
*sp
);
337 int parsebitsplice(struct function
*fp
, char *bitstring
, int nbits
,
339 int findvariable(struct function
*fp
, int name
, struct string
*sp
);
340 int parsefunctioncall(struct function
*fp
, char *start
, char **stringp
,
342 int parsearray(struct function
*fp
, char **stringp
, struct string
*sp
,
344 void dumpfunctions(void);
345 void dumpfunction(struct function
*fp
);
346 void showentry(FILE *f
, struct function
*fp
, struct entry
*ep
, bits highlight
);
347 void showbits(FILE *f
, struct entry
*ep
, int nbits
, bits highlight
);
348 void showargs(FILE *f
, struct arg
*ap
, int fieldwidth
);
349 void showstring(FILE *f
, struct string
*sp
);
350 void showstringelement(FILE *f
, struct string
*sp
);
351 void showfunctioncall(FILE *f
, struct functioncall
*fcp
);
352 void showarray(FILE *f
, struct array
*ap
);
353 int outputfunctions(void);
354 void outputidentity(FILE *f
);
355 int outputdeclarations(void);
356 void outputconcats(void);
357 void outputconcat(int n
);
358 void outputconcatheader(FILE *f
, int n
);
359 void findarrays(void);
360 int checkfixedlength(struct array
*ap
);
361 int outputfunction(struct function
*fp
);
362 void functionarray(struct function
*fp
);
363 void functionheader(FILE *f
, struct function
*fp
);
364 int simplearray(struct array
*ap
);
365 void compiletype(FILE *f
, enum type
*tp
);
366 int functionswitch(struct function
*fp
, bits mask
, bits value
);
367 int compilestring(int assignto
, struct string
*sp
, enum type type
);
368 int compilecheckedstring(int assignto
, struct string
*sp
, enum type type
);
369 void compileassign(int assignto
);
370 void compiletemp(int tempno
);
371 void compiletext(char *s
);
372 int compileconcat(struct string
*sp
, enum type type
);
373 int compilenull(enum type type
);
374 int compilesimple(struct string
*sp
, enum type type
);
375 int compilearrayref(struct array
*ap
);
376 int compilefunctioncall(struct string
*sp
);
377 int walkstring(struct string
*sp
, enum walkstringop op
, int tempno
);
378 int compilearray(struct array
*ap
);
379 void compilesimplearray(enum type
*tp
, char *name
, int num
, struct array
*ap
);
380 void declarearray(struct array
*ap
);
381 void compilebitstring(struct bits
*bp
);
382 void compilebitsplice(struct bitsplice
*splicep
);
383 int bitcount(bits x
);
384 bits
allbitsset(int nbits
);
385 void findent(FILE *f
);
387 void *xrealloc(char *oldp
, size_t size
);
388 void *xmalloc(size_t size
);
389 void *xstrdup(char *s
);
390 int prematureeof(void);
393 int main(int argc
, char **argv
) {
400 for (i
= 1; i
< argc
&& argv
[i
][0] == '-'; i
++) {
401 switch (argv
[i
][1]) {
405 headerfilename
= argv
[i
]; break;
414 fprintf(stderr
, "Usage: %s [file]\n", progname
);
419 return makedis(stdin
, "<stdin>");
422 if ((f
= fopen(argv
[i
], "r")) == NULL
) {
423 fprintf(stderr
, "%s: %s: %s\n", progname
, argv
[i
], strerror(errno
));
426 return makedis(f
, argv
[i
]);
430 int makedis(FILE *f
, char *fname
) {
432 char function
[MAXfunction
], bitstring
[MAXBITS
];
433 static char *string
= NULL
;
439 /* Loop for every line in the description. */
441 /* Ignore initial spaces and newlines. */
442 while (isspace(c
= getc(f
)))
448 /* Ignore comments. # only allowed at start of line. */
450 while ((c
= getc(f
)) != '\n')
452 return prematureeof();
457 /* Read function name, terminated by space. */
458 for (i
= 0; i
< sizeof function
&& !isspace(c
); i
++, c
= getc(f
)) {
460 return prematureeof();
463 if (i
>= sizeof function
) {
464 fprintf(stderr
, "%s: %s(%d): function name is too long: %.*s\n",
465 progname
, filename
, lineno
, i
, function
);
470 /* Skip to next field. */
471 while (isspace(c
) && c
!= '\n')
474 /* If not a control statement, read bitstring and/or arguments. */
475 if (function
[0] == ':')
476 fp
= 0; /* Silence gcc. */
478 fp
= makefunction(function
);
482 /* Read optional bitstring. */
483 for (i
= 0; i
< sizeof bitstring
&& isalnum(c
); i
++, c
= getc(f
)) {
485 return prematureeof();
489 fprintf(stderr
, "%s: %s(%d): bit string is too long: %.*s\n",
490 progname
, filename
, lineno
, i
, bitstring
);
493 if (parsebits(fp
, bitstring
, i
) != 0)
496 /* Read optional arguments. */
497 if (parseargs(fp
, f
, &c
) != 0)
500 /* Skip to next field. */
501 while (isspace(c
) && c
!= '\n')
504 /* : indicates an external (C) function. */
506 if (parseextern(fp
, f
) != 0)
512 /* Read associated text. */
515 for ( ; c
!= '\n'; i
++, c
= getc(f
)) {
517 return prematureeof();
518 if (i
>= stringlen
) {
519 stringlen
= stringlen
* 2 + 16;
520 string
= xrealloc(string
, stringlen
);
526 switch (string
[i
- 1]) {
531 while (isspace(c
= getc(f
)) && c
!= '\n') ;
537 if (i
>= stringlen
) {
538 stringlen
= stringlen
* 2 + 16;
539 string
= xrealloc(string
, stringlen
);
543 /* Parse the line just read. */
544 if (function
[0] == ':') {
545 if (parsecontrol(function
+ 1, string
) != 0)
548 if (parsestring(fp
, string
) != 0)
554 return outputfunctions();
558 /* A function in the description file. nbits and nargs are -1 until the
559 real values are known. */
561 struct function
*next
;
564 int nbits
; /* Number of bits in the bitpattern, 0 if none. */
565 int nargs
; /* Number of (x,y,...) parameters, 0 if none. */
566 char isarray
; /* Will be represented by a C array. */
567 int fixedlength
; /* If a C array, will be a char [][N] not a char *[]. */
568 struct entry
*first
, *last
;
569 /* Links to the value(s) supplied. */
570 struct arg
*args
; /* List of (x,y,...) names and types. */
572 struct function
*functions
;
575 /* Find the function with the given name. If not found, create a structure
576 for it, fill it out with a template, and return that. */
577 struct function
*findfunction(char *name
) {
580 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
581 if (strcmp(fp
->name
, name
) == 0)
584 if (strlen(name
) > maxfunctionname
)
585 maxfunctionname
= strlen(name
);
586 fp
= xmalloc(sizeof *fp
);
587 fp
->next
= functions
;
589 fp
->name
= xstrdup(name
);
590 fp
->type
= T_UNKNOWN
;
591 fp
->nbits
= fp
->nargs
= -1; /* nbits will be set correctly later. */
593 fp
->first
= fp
->last
= NULL
;
598 /* Parse an external (C) function declaration. This will look something like:
600 We're called just after seeing the ':'.
601 Return 0 if parsing is successful, 1 otherwise. */
602 int parseextern(struct function
*fp
, FILE *f
) {
605 if ((c
= getc(f
)) != '\n') {
607 "%s: %s(%d): extern declaration should be a lone `:'\n",
608 progname
, filename
, lineno
);
611 if (fp
->nbits
!= 0) {
613 "%s: %s(%d): extern functions should not have bitstrings\n",
614 progname
, filename
, lineno
);
618 fp
->first
= fp
->last
= NULL
;
623 /* A value supplied for a function (the third field in a description line).
624 In general there can be any number of such values, differing in the
625 bitpattern supplied. The mask and value fields describe the constant
626 bits in the bitpattern: mask indicates which bits they are and value
627 indicates the values of those bits. So this entry matches
628 ((x & mask) == value). */
632 struct bits
*bits
; /* List of named bitfields. */
633 struct string
*string
; /* Value of function when bitpattern matched. */
634 char done
; /* This entry has already been compiled. */
638 /* We've just seen a definition of function "name". Make a structure for it
639 if necessary, and a template entry that will describe the value given here.
641 struct function
*makefunction(char *name
) {
643 struct entry
*ep
= xmalloc(sizeof *ep
);
646 if (name
[0] == '%') {
651 fp
= findfunction(name
);
652 if (fp
->type
== T_UNKNOWN
)
654 else if (fp
->type
!= type
) {
655 fprintf(stderr
, "%s: %s(%d): function %s previously declared as %s, "
656 "here as %s\n", progname
, filename
, lineno
, name
,
657 typename
[fp
->type
], typename
[type
]);
663 if (fp
->first
!= NULL
)
672 /* A named bitfield within the bitpattern of a function entry, or within a
673 $[...] bitsplice. The mask covers the bitfield and the shift says how
674 many 0 bits there are after the last 1 in the mask. */
683 /* Parse the bitstring supplied for the given function. nbits says how many
684 bits there are; it can legitimately be 0. Return value is 0 on success. */
685 int parsebits(struct function
*fp
, char *bitstring
, int nbits
) {
688 else if (fp
->nbits
!= nbits
) {
689 fprintf(stderr
, "%s: %s(%d): bit string of length %d;\n",
690 progname
, filename
, lineno
, nbits
);
691 fprintf(stderr
, " function %s has bit strings of length %d\n",
692 fp
->name
, fp
->nbits
);
695 return parseentrybits(fp
->last
, bitstring
, nbits
, 0);
699 /* Parse a bitstring that is the pattern for a function entry or that is in a
700 $[...] bitsplice. Put the result in ep. Return value is 0 on success. */
701 int parseentrybits(struct entry
*ep
, char *bitstring
, int nbits
, int issplice
) {
704 bits mask
, value
, entrymask
;
708 for (i
= 0; i
< nbits
; i
++) {
709 bit
= bitstring
[nbits
- 1 - i
];
719 fprintf(stderr
, "%s: %s(%d): invalid character in bitstring: %c\n",
720 progname
, filename
, lineno
, bit
);
724 for (bp
= ep
->bits
; bp
!= NULL
; bp
= bp
->next
) {
725 if (bp
->name
== bit
) {
727 "%s: %s(%d): bitstring name %c used twice\n",
728 progname
, filename
, lineno
, bit
);
734 for (j
= i
+ 1; j
< nbits
&& bitstring
[nbits
- 1 - j
] == bit
; j
++)
736 bp
= xmalloc(sizeof *bp
);
738 bp
->mask
= entrymask
;
750 /* Parse a control line. This looks something like:
751 :bitstype unsigned int
752 in which case we will be called with name "bitstype" and
753 value "unsigned int". */
754 int parsecontrol(char *name
, char *value
) {
755 if (strcmp(name
, "bitstype") == 0)
756 bitstype
= xstrdup(value
);
758 fprintf(stderr
, "%s: %s(%d): unrecognised control keyword %s\n",
759 progname
, filename
, lineno
, name
);
766 /* A parameter to a function, e.g., x in:
767 %f aaa(%x) $a + $x */
775 /* Parse the parameters (x,y,...) to a function and put the result in fp.
776 The entry that is being built is fp->last. cp points to the opening
777 (; if it does not point to a ( then there are no parameters. If
778 this is the first entry for the function, fp->nargs will be -1 and
779 we will build up an argument list. Otherwise, fp->nargs will be
780 >= 0 and we will only check that the arguments here are consistent
781 with what went before. Return value is 0 on success. */
782 int parseargs(struct function
*fp
, FILE *f
, int *cp
) {
783 struct arg
**arglink
, *ap
;
798 if (fp
->nargs
>= 0 && nargs
> fp
->nargs
) {
800 "%s: %s(%d): %d arg(s) instead of %d for %s\n",
801 progname
, filename
, lineno
, nargs
, fp
->nargs
,
812 if (!isalpha(name
)) {
814 "%s: %s(%d): argument should be letter: %c\n",
815 progname
, filename
, lineno
, name
);
818 for (bp
= fp
->last
->bits
; bp
!= NULL
; bp
= bp
->next
) {
819 if (bp
->name
== name
) {
821 "%s: %s(%d): %c is a bitstring and an arg\n",
822 progname
, filename
, lineno
, name
);
826 if (fp
->nargs
>= 0) {
827 if ((*arglink
)->name
!= name
) {
829 "%s: %s(%d): arg %d of %s is %c not %c\n",
830 progname
, filename
, lineno
, nargs
, fp
->name
,
831 (*arglink
)->name
, name
);
834 if ((*arglink
)->type
!= t
) {
836 "%s: %s(%d): arg %c of %s: inconsistent type\n",
837 progname
, filename
, lineno
, name
, fp
->name
);
841 for (ap
= fp
->args
; ap
!= *arglink
; ap
= ap
->next
) {
842 if (ap
->name
== name
) {
844 "%s: %s(%d): argument name %c used twice\n",
845 progname
, filename
, lineno
, name
);
849 *arglink
= xmalloc(sizeof **arglink
);
850 (*arglink
)->name
= name
;
851 (*arglink
)->type
= t
;
853 arglink
= &(*arglink
)->next
;
859 "%s: %s(%d): bad character in argument list: %c\n"
860 " (arguments must be single letters)\n",
861 progname
, filename
, lineno
, *cp
);
872 if (width
> maxargwidth
)
874 } else if (fp
->nargs
!= nargs
) {
875 fprintf(stderr
, "%s: %s(%d): argument list of length %d;\n",
876 progname
, filename
, lineno
, nargs
);
877 fprintf(stderr
, " function %s has argument lists of length %d\n",
878 fp
->name
, fp
->nargs
);
886 /* Parse the string describing the value of this entry for our
887 function. Return 0 on success. */
888 int parsestring(struct function
*fp
, char *str
) {
891 t
= makestring(fp
, &fp
->last
->string
, &str
, NULL
, fp
->type
);
894 if (fp
->type
!= t
&& t
!= T_UNKNOWN
) {
895 fprintf(stderr
, "%s: %s(%d): function %s has inconsistent types\n",
896 progname
, filename
, lineno
, fp
->name
);
903 /* A parsed representation of the whole string describing a value of a
904 function, or certain strings within that (e.g., array indices). This is a
905 linked list of substrings whose type is given by the type field. */
909 S_TEXT
, S_BITSTRING
, S_BITSPLICE
, S_PARAMETER
, S_FUNCTIONCALL
, S_ARRAY
911 union value
{ /* The fields here correspond to the enum values. */
912 char *text
; /* plain text */
913 struct bits
*bits
; /* $x where x is a bitfield */
914 struct bitsplice
*bitsplice
; /* $[...] */
915 struct arg
*parameter
; /* $x where x is a parameter */
916 struct functioncall
*functioncall
; /* $func(...) */
917 struct array
*array
; /* {...}[...] */
921 /* The representation of a function call $func(...) in the description of a
923 struct functioncall
{
924 struct function
*function
;
925 struct stringlist
*args
;
928 /* The representation of an array selection {...|...}[...] in the description
929 of a function value. tempno is used when constructing a C variable name
930 that will contain the strings or numbers in an array. */
932 struct string
*index
; /* what's between [...] */
933 struct stringlist
*elements
; /* what's between {...} */
934 enum type type
; /* the type of each element */
938 /* A list of strings, being the list of arguments in a function call or the
939 list of elements of an array. This is a linked list of linked lists. */
941 struct stringlist
*next
;
943 struct string
*string
;
947 /* The following are the only characters with special meaning at the top level
948 of parsing of a function value. When parsing arrays or function calls,
949 other characters become special. */
950 #define MAKESTRING_MAGIC "${"/*}*/
953 /* Parse a function return-value string or substring and make a struct string
954 list for it. The string starts at *stringp and ends at a \0 or at any
955 character in the `magic' string other than { or $. *stringp is updated
956 to point to the terminating character. The parsed representation is put
957 at *stringlink. `fp' is the function whose return value is being parsed.
958 `targettype' is the expected type of the result, if known.
959 The return value is the actual type. */
960 enum type
makestring(struct function
*fp
, struct string
**stringlink
,
961 char **stringp
, char *magic
, enum type targettype
) {
963 struct string
*sp
, **firststringlink
;
966 enum type t
= targettype
, newt
;
969 magic
= MAKESTRING_MAGIC
;
971 firststringlink
= stringlink
;
974 sp
= xmalloc(sizeof *sp
);
978 if (strchr(magic
, *q
) != NULL
) {
979 if (*q
!= ')' || parenlevel
== 0)
993 } while (*++q
!= '\0');
996 sp
->value
.text
= q
= xmalloc(n
+ 1);
1004 } else if (*p
== '$') {
1005 if (parsedollar(fp
, &p
, sp
) != 0)
1013 newt
= sp
->value
.parameter
->type
;
1015 case S_FUNCTIONCALL
:
1016 newt
= sp
->value
.functioncall
->function
->type
;
1019 fprintf(stderr
, "makestring type %d\n", sp
->type
);
1022 } else if (*p
== '{'/*}*/) {
1023 if (parsearray(fp
, &p
, sp
, t
) != 0)
1025 newt
= sp
->value
.array
->type
;
1032 else if (newt
!= T_UNKNOWN
&& t
!= newt
) {
1033 if (stringlink
== firststringlink
) {
1034 fprintf(stderr
, "%s: %s(%d): expected %s type:\n", progname
,
1035 filename
, lineno
, typename
[t
]);
1036 showstringelement(stderr
, sp
);
1040 fprintf(stderr
, "%s: %s(%d): mixed types in string:\n",
1041 progname
, filename
, lineno
);
1042 showstring(stderr
, *firststringlink
);
1043 fprintf(stderr
, " -- %s\n", typename
[t
]);
1044 showstringelement(stderr
, sp
);
1045 fprintf(stderr
, " -- %s\n", typename
[newt
]);
1049 stringlink
= &sp
->next
;
1054 if (components
>= MAXBITS
) {
1055 fprintf(stderr
, "%s: %s(%d): excessively complicated string\n",
1056 progname
, filename
, lineno
);
1059 componentbits
|= 1 << components
;
1064 /* Parse a $ operation at **stringp and update *stringp to point past it.
1065 `fp' is the function whose return value is being parsed. The parsed
1066 item will be put at *sp. Return 0 on success, nonzero on error. */
1067 int parsedollar(struct function
*fp
, char **stringp
, struct string
*sp
) {
1075 while (isalnum(*p
) || *p
== '_')
1077 if (*start
== '[') {
1079 fprintf(stderr
, "%s: %s(%d): missing ] or bad character in $[\n",
1080 progname
, filename
, lineno
);
1084 return parsebitsplice(fp
, start
+ 1, p
- start
- 1, sp
);
1087 fprintf(stderr
, "%s: %s(%d): missing identifier after $\n", progname
,
1091 if (p
== start
+ 1) {
1092 if (findvariable(fp
, *start
, sp
) != 0)
1095 if (parsefunctioncall(fp
, start
, &p
, sp
) != 0)
1103 /* The representation of a $[...] bitsplice. It is parsed into a
1104 struct entry just as if it were a bitfield parameter, then analysed
1105 into a chain of struct bitsplicebits. These in conjunction with
1106 the constant portion of the struct entry will allow the bitsplice to
1107 be compiled. Each bitsplicebits element represents either a numeric
1108 argument to the current function, in which case it will be shifted
1109 into place; or a bitfield name from the bitfield description of the
1110 current function, in which case it will be shifted by the difference
1111 between the position of the bitfield in the argument and the position
1112 it occurs in the bitsplice. `shift' indicates how much to shift left
1113 the associated value; if it is negative the value is shifted right.
1114 For instance, in a function like this:
1115 %oh xx00(%y) $[yyxx]
1116 the bitsplicebits for y will have shift = 2 and value.arg pointing to y,
1117 and those for x will have shift = -2 and value.mask = binary 1100.
1118 As an optimisation, contiguous bitfields that are also contiguous in the
1119 bitsplice will be combined. For instance:
1120 %oh xxyy00 $[0xxyy0]
1121 will compile the same code as:
1122 %oh zzzz00 $[0zzzz0].
1123 As another optimisation, a bitfield that occupies the entire bitstring
1124 for a function will be treated like a parameter in that it will not be
1125 masked in the bitsplice. For instance:
1126 %oh xxxxxx $[0xxxxxx0]
1127 will compile the same code as:
1128 %oh (%x) $[0xxxxxx0]. */
1132 struct bitsplicebits
*splice
;
1134 struct bitsplicebits
{
1135 struct bitsplicebits
*next
;
1137 enum elementtype type
;
1145 int parsebitsplice(struct function
*fp
, char *bitstring
, int nbits
,
1146 struct string
*sp
) {
1147 struct bitsplice
*splicep
;
1148 struct bitsplicebits
*bsp
, *lastbsp
, **bspp
;
1150 int shift
, nfrombits
, ntobits
;
1153 splicep
= xmalloc(sizeof *splicep
);
1154 splicep
->nbits
= nbits
;
1155 if (parseentrybits(&splicep
->entry
, bitstring
, nbits
, 1) != 0)
1157 bspp
= &splicep
->splice
;
1159 for (bp
= splicep
->entry
.bits
; bp
!= NULL
; bp
= bp
->next
) {
1160 if (findvariable(fp
, bp
->name
, sp
) != 0)
1163 if (sp
->type
== S_BITSTRING
) {
1164 nfrombits
= bitcount(sp
->value
.bits
->mask
);
1165 ntobits
= bitcount(bp
->mask
);
1167 if (nfrombits
!= ntobits
) {
1168 fprintf(stderr
, "%s: %s(%d): warning: "
1169 "bitstring $%c %ser than its place "
1171 progname
, filename
, lineno
, bp
->name
,
1172 (nfrombits
> ntobits
) ? "bigg" : "small");
1175 shift
-= sp
->value
.bits
->shift
;
1177 /* See if this bitfield can be combined with a previous contiguous
1179 if (lastbsp
!= NULL
&& lastbsp
->type
== S_BITSTRING
1180 && lastbsp
->shift
== shift
) {
1181 lastbsp
->value
.mask
|= sp
->value
.bits
->mask
;
1185 assert(sp
->type
== S_PARAMETER
);
1186 if (sp
->value
.parameter
->type
!= T_INTEGER
) {
1188 "%s: %s(%d): variable %c in $[...] should be integer\n",
1189 progname
, filename
, lineno
, sp
->value
.parameter
->name
);
1193 *bspp
= bsp
= xmalloc(sizeof *bsp
);
1194 bsp
->type
= sp
->type
;
1196 if (sp
->type
== S_PARAMETER
)
1197 bsp
->value
.arg
= sp
->value
.parameter
;
1199 bsp
->value
.mask
= sp
->value
.bits
->mask
;
1205 /* Look for a spliced element that is the entire bitstring argument to
1206 this function and therefore doesn't need to be masked. */
1207 allbits
= allbitsset(fp
->nbits
);
1208 for (bsp
= splicep
->splice
; bsp
!= NULL
; bsp
= bsp
->next
) {
1209 if (bsp
->type
== S_BITSTRING
) {
1210 for (b
= bsp
->value
.mask
; b
!= 0 && !(b
& 1); b
>>= 1) ;
1212 bsp
->value
.mask
= 0;
1215 sp
->type
= S_BITSPLICE
;
1216 sp
->value
.bitsplice
= splicep
;
1221 int findvariable(struct function
*fp
, int name
, struct string
*sp
) {
1225 for (bp
= fp
->last
->bits
; bp
!= NULL
; bp
= bp
->next
) {
1226 if (bp
->name
== name
) {
1227 sp
->type
= S_BITSTRING
;
1228 sp
->value
.bits
= bp
;
1232 for (ap
= fp
->args
; ap
!= NULL
; ap
= ap
->next
) {
1233 if (ap
->name
== name
) {
1234 sp
->type
= S_PARAMETER
;
1235 sp
->value
.parameter
= ap
;
1239 fprintf(stderr
, "%s: %s(%d): undefined parameter %c\n", progname
, filename
,
1245 int parsefunctioncall(struct function
*fp
, char *start
, char **stringp
,
1246 struct string
*sp
) {
1248 struct functioncall
*fcp
;
1249 struct stringlist
**arglink
, *arg
;
1254 fprintf(stderr
, "%s: %s(%d): missing ( after function %.*s\n", progname
,
1255 filename
, lineno
, p
- start
, start
);
1258 sp
->type
= S_FUNCTIONCALL
;
1259 sp
->value
.functioncall
= fcp
= xmalloc(sizeof *fcp
);
1260 *p
= '\0'; /* Ugly. */
1261 fcp
->function
= findfunction(start
);
1263 arglink
= &fcp
->args
;
1266 arg
= xmalloc(sizeof *arg
);
1267 t
= makestring(fp
, &arg
->string
, &p
, MAKESTRING_MAGIC
",)",
1273 arglink
= &arg
->next
;
1287 int parsearray(struct function
*fp
, char **stringp
, struct string
*sp
,
1291 struct stringlist
**elementlink
, *element
;
1294 assert(*p
== '{'/*}*/);
1296 sp
->value
.array
= ap
= xmalloc(sizeof *ap
);
1298 elementlink
= &ap
->elements
;
1300 if (*++p
!= /*{*/'}') {
1302 element
= xmalloc(sizeof *element
);
1303 t
= makestring(fp
, &element
->string
, &p
,
1304 MAKESTRING_MAGIC
/*{*/"|}", t
);
1308 if (ap
->type
== T_UNKNOWN
)
1310 else if (t
!= T_UNKNOWN
&& ap
->type
!= t
) {
1311 fprintf(stderr
, "%s: %s(%d): mixed types in array:\n",
1312 progname
, filename
, lineno
);
1313 showstring(stderr
, ap
->elements
->string
);
1314 fprintf(stderr
, " -- %s\n", typename
[ap
->type
]);
1315 showstring(stderr
, element
->string
);
1316 fprintf(stderr
, " -- %s\n", typename
[t
]);
1319 *elementlink
= element
;
1320 elementlink
= &element
->next
;
1327 *elementlink
= NULL
;
1328 assert(*p
== /*{*/'}');
1330 fprintf(stderr
, "%s: %s(%d): missing [index] after array\n",
1331 progname
, filename
, lineno
);
1335 t
= makestring(fp
, &ap
->index
, &p
, MAKESTRING_MAGIC
"]", T_INTEGER
);
1338 if (t
== T_STRING
) {
1339 fprintf(stderr
, "%s: %s(%d): array index cannot be string:\n",
1340 progname
, filename
, lineno
);
1341 showstring(stderr
, ap
->index
);
1345 fprintf(stderr
, "%s: %s(%d): [ without ]\n", progname
, filename
,
1354 void dumpfunctions() {
1355 struct function
*fp
;
1357 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
)
1362 void dumpfunction(struct function
*fp
) {
1365 for (ep
= fp
->first
; ep
!= NULL
; ep
= ep
->next
)
1366 showentry(stderr
, fp
, ep
, 0);
1370 /* Entries are not shown exactly as they would be input, since \ would
1371 need to be provided before some characters such as $ or {. But the
1372 characters "|},]" pose a problem since a \ is only needed in certain
1373 contexts and is annoying otherwise. It's not worth doing this right,
1374 since it's only used for error messages. */
1375 void showentry(FILE *f
, struct function
*fp
, struct entry
*ep
, bits highlight
) {
1376 if (fp
->type
== T_INTEGER
)
1378 fprintf(f
, "%-*s ", maxfunctionname
+ 1, fp
->name
);
1379 if (fp
->nbits
== 0 && fp
->nargs
== 0)
1380 fprintf(f
, "%-*s", maxargwidth
, "()");
1382 showbits(f
, ep
, fp
->nbits
, 0);
1383 showargs(f
, fp
->args
, maxargwidth
- fp
->nbits
);
1386 showstring(f
, ep
->string
);
1388 if (highlight
!= 0) {
1389 fprintf(f
, "%-*s ", maxfunctionname
+ 1, "");
1390 showbits(f
, ep
, fp
->nbits
, highlight
);
1396 void showbits(FILE *f
, struct entry
*ep
, int nbits
, bits highlight
) {
1403 i
= 1 << (nbits
- 1);
1415 if (highlight
!= 0 || (ep
->mask
& i
)) {
1416 putc((value
& i
) ? one
: zero
, f
);
1419 assert(bp
!= NULL
&& (bp
->mask
& i
));
1423 } while (bp
->mask
& i
);
1430 void showargs(FILE *f
, struct arg
*ap
, int fieldwidth
) {
1441 isint
= (ap
->type
== T_INTEGER
);
1442 fprintf(f
, "%c%s%c", lastc
, isint
? "%" : "", ap
->name
);
1446 } while (ap
!= NULL
);
1449 fprintf(f
, "%-*s", fieldwidth
- width
, "");
1453 void showstring(FILE *f
, struct string
*sp
) {
1454 for ( ; sp
!= NULL
; sp
= sp
->next
)
1455 showstringelement(f
, sp
);
1459 void showstringelement(FILE *f
, struct string
*sp
) {
1460 struct bitsplice
*bsp
;
1464 fputs(sp
->value
.text
, f
);
1467 fprintf(f
, "$%c", sp
->value
.bits
->name
);
1471 bsp
= sp
->value
.bitsplice
;
1472 showbits(f
, &bsp
->entry
, bsp
->nbits
, 0);
1476 fprintf(f
, "$%c", sp
->value
.parameter
->name
);
1478 case S_FUNCTIONCALL
:
1479 showfunctioncall(f
, sp
->value
.functioncall
);
1482 showarray(f
, sp
->value
.array
);
1485 fprintf(stderr
, "showstring case %d\n", sp
->type
);
1491 void showfunctioncall(FILE *f
, struct functioncall
*fcp
) {
1492 struct stringlist
*sp
;
1495 fprintf(f
, "$%s(", fcp
->function
->name
);
1497 for (sp
= fcp
->args
; sp
!= NULL
; sp
= sp
->next
) {
1500 showstring(f
, sp
->string
);
1506 void showarray(FILE *f
, struct array
*ap
) {
1507 struct stringlist
*sp
;
1512 for (sp
= ap
->elements
; sp
!= NULL
; sp
= sp
->next
) {
1515 showstring(f
, sp
->string
);
1517 fputs(/*{*/"}[", f
);
1518 showstring(f
, ap
->index
);
1523 const char commonpreamble
[] = "\
1528 const char concatpreamble
[] = "\
1529 static char *dis_buf;\n\
1530 static int dis_bufindex, dis_buflen;\n\
1532 void *dis_alloc(size_t size)\n\
1535 int newindex = dis_bufindex + size;\n\
1536 if (newindex > dis_buflen) {\n\
1537 dis_buflen = newindex * 4;\n\
1538 dis_buf = malloc(dis_buflen);\n\
1539 /* We can't use realloc because there might be pointers extant into\n\
1540 the old buffer. So we waste the memory of the old buffer. We\n\
1541 should soon reach an adequate buffer size and stop leaking. */\n\
1542 if (dis_buf == 0) {\n\
1543 perror(\"malloc\");\n\
1546 dis_bufindex = 0;\n\
1548 p = dis_buf + dis_bufindex;\n\
1549 dis_bufindex = newindex;\n\
1555 dis_bufindex = 0;\n\
1560 const char concatdeclarations
[] = "\
1561 #include <string.h>\n\
1562 #include <stdlib.h>\n\
1563 #include <errno.h>\n\
1565 extern void *dis_realloc(void *p, size_t size); /* User-provided. */\n\
1566 void *dis_alloc(size_t size);\n\
1567 void dis_done(void);\n\
1570 const char nonconcatpreamble
[] = "\
1571 void dis_done() {}\n\
1575 int outputfunctions() {
1576 struct function
*fp
;
1578 outputidentity(stdout
);
1579 if (headerfilename
!= NULL
) {
1580 if ((headerfile
= fopen(headerfilename
, "w")) == NULL
) {
1581 fprintf(stderr
, "%s: create %s: %s\n", progname
, headerfilename
,
1585 outputidentity(headerfile
);
1586 fprintf(headerfile
, commonpreamble
, bitstype
);
1587 printf("\n#include \"%s\"\n", headerfilename
);
1589 printf(commonpreamble
, bitstype
);
1591 if (outputdeclarations() != 0)
1594 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
1598 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
1599 if (fp
->first
!= NULL
&& !fp
->isarray
) {
1600 if (outputfunction(fp
) != 0)
1608 void outputidentity(FILE *f
) {
1611 fprintf(f
, "/*\n * This file was generated by:\n *");
1612 for (p
= global_argv
; *p
!= NULL
; p
++)
1613 fprintf(f
, " %s", *p
);
1614 fprintf(f
, "\n */\n\n");
1618 int outputdeclarations() {
1619 FILE *f
= headerfile
? headerfile
: stdout
;
1620 struct function
*fp
;
1622 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
1623 if (fp
->type
!= T_UNKNOWN
) {
1625 fprintf(f
, "extern ");
1626 if (fp
->fixedlength
> 0)
1627 fprintf(f
, "char %s[][%d]", fp
->name
, fp
->fixedlength
);
1629 compiletype(f
, &fp
->type
);
1630 fprintf(f
, "%s[]", fp
->name
);
1633 functionheader(f
, fp
);
1641 void outputconcats() {
1644 if (componentbits
& ~3) {
1645 fputs(concatdeclarations
, headerfile
? headerfile
: stdout
);
1646 fputs(concatpreamble
, stdout
);
1648 fputs(nonconcatpreamble
, stdout
);
1649 for (i
= 2; i
< MAXBITS
; i
++) {
1650 if (componentbits
& (1 << i
))
1656 void outputconcat(int n
) {
1662 outputconcatheader(headerfile
, n
);
1663 fprintf(headerfile
, ";\n");
1665 outputconcatheader(stdout
, n
);
1666 printf("\n{\n void *p;\n int len = ");
1668 for (i
= 0; i
< n
; i
++) {
1669 printf("%sstrlen(p%d)", last
, i
);
1672 printf(";\n p = dis_alloc(len + 1);\n return ");
1673 for (i
= 1; i
< n
; i
++)
1675 printf("strcpy(p, p0)");
1676 for (i
= 1; i
< n
; i
++)
1677 printf(", p%d)", i
);
1682 void outputconcatheader(FILE *f
, int n
) {
1686 fprintf(f
, "char *dis_concat%d(", n
);
1687 for (i
= 0; i
< n
; i
++) {
1688 fprintf(f
, "%schar *p%d", last
, i
);
1696 struct function
*fp
;
1698 struct string
*estr
, *indexstr
;
1701 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
1702 if (fp
->nbits
> 0 && fp
->nargs
> 0)
1707 if (ep
== NULL
|| ep
->next
!= NULL
)
1710 if (estr
== NULL
|| estr
->next
!= NULL
|| estr
->type
!= S_ARRAY
)
1712 indexstr
= estr
->value
.array
->index
;
1713 if (indexstr
->next
!= NULL
)
1715 if (fp
->nbits
> 0) {
1717 if (bp
== NULL
|| bp
->next
!= NULL
|| bp
->shift
!= 0)
1719 if (bp
->mask
!= allbitsset(fp
->nbits
))
1721 if (indexstr
->type
!= S_BITSTRING
|| indexstr
->value
.bits
!= bp
)
1724 if (indexstr
->type
!= S_PARAMETER
1725 || indexstr
->value
.parameter
!= fp
->args
)
1728 if (!simplearray(estr
->value
.array
))
1732 (fp
->type
== T_INTEGER
) ? 0 : checkfixedlength(estr
->value
.array
);
1737 int checkfixedlength(struct array
*ap
) {
1738 int len
, maxlen
, wasted
, n
;
1739 struct stringlist
*lp
;
1742 for (lp
= ap
->elements
; lp
!= NULL
; lp
= lp
->next
) {
1743 if (lp
->string
== NULL
)
1745 assert(lp
->string
->type
== S_TEXT
);
1746 len
= strlen(lp
->string
->value
.text
);
1750 for (wasted
= n
= 0, lp
= ap
->elements
; lp
!= NULL
; n
++, lp
= lp
->next
) {
1751 if (lp
->string
== NULL
)
1753 wasted
+= maxlen
- strlen(lp
->string
->value
.text
);
1755 if (wasted
< n
* sizeof(char *)) /* Should be target's sizeof. */
1761 int outputfunction(struct function
*fp
) {
1763 functionheader(stdout
, fp
);
1764 printf("\n{\n"/*}*/);
1765 switch (functionswitch(fp
, 0, 0)) {
1770 fprintf(stderr
, "%s: warning: not all cases of %s covered\n",
1771 progname
, fp
->name
);
1779 void functionarray(struct function
*fp
) {
1782 ap
= fp
->first
->string
->value
.array
;
1784 compilesimplearray(&fp
->type
, fp
->name
, 0, ap
);
1788 void functionheader(FILE *f
, struct function
*fp
) {
1792 compiletype(f
, &fp
->type
);
1793 fprintf(f
, "%s(", fp
->name
);
1795 if (fp
->nbits
> 0) {
1796 fprintf(f
, "bits code");
1799 for (ap
= fp
->args
; ap
!= NULL
; ap
= ap
->next
) {
1801 compiletype(f
, &ap
->type
);
1811 int simplearray(struct array
*ap
) {
1812 struct stringlist
*lp
;
1814 for (lp
= ap
->elements
; lp
!= NULL
; lp
= lp
->next
) {
1815 if (lp
->string
!= NULL
1816 && (lp
->string
->next
!= NULL
|| lp
->string
->type
!= S_TEXT
))
1819 return (lp
== NULL
);
1823 void compiletype(FILE *f
, enum type
*tp
) {
1829 fprintf(f
, "char *");
1832 fprintf(f
, "bits ");
1835 fprintf(stderr
, "compiletype type %d\n", *tp
);
1841 /* Generate code for entries in function fp whose bitstring b satisfies
1842 the constraint (b & mask) == value. Return 1 if generated switch
1843 always does `return', 0 if not, -1 on error.
1844 The algorithm is as follows. Scan the eligible entries to find the
1845 largest set of bits not in the passed-in mask which always have a
1846 constant value (are not variable). One `default' entry is allowed
1847 all of whose bits are variable. For each value of the constant bits,
1848 generate a `switch' case and invoke the function recursively with
1849 that value included in the constraint parameters. The recursion
1850 stops when no set of constant bits is found, perhaps because the
1851 mask parameter has all bits set.
1852 This algorithm could be improved. Currently it will fail if there
1853 are input lines "xxyy", "00xx" and "yy00", each of which is default with
1854 respect to the others. The correct behaviour would then be to select
1855 a bit that is sometimes constant and deal with those cases first.
1856 But this problem has not yet arisen in real life. */
1857 int functionswitch(struct function
*fp
, bits mask
, bits value
) {
1858 struct entry
*ep
, *defaultcase
;
1859 bits allbits
, constbits
, missingcases
;
1860 int nhits
, ncases
, nconstbits
, alwaysreturns
;
1863 allbits
= allbitsset(fp
->nbits
);
1864 constbits
= allbits
& ~mask
;
1868 "functionswitch(%s): (x & 0x%lx) == 0x%lx; const == 0x%lx\n",
1869 fp
->name
, mask
, value
, constbits
);
1874 for (ep
= fp
->first
; ep
!= NULL
; ep
= ep
->next
) {
1875 /* If this is not one of the entries under consideration, skip. */
1877 || (ep
->mask
& mask
) != mask
|| (ep
->value
& mask
) != value
)
1881 showentry(stderr
, fp
, ep
, 0);
1883 /* If this entry has no constant bits in the still-variable portion,
1884 it's the default. */
1885 if ((constbits
& ep
->mask
) == 0) {
1886 if (defaultcase
!= NULL
) {
1888 "%s: function %s: unable to distinguish between:\n",
1889 progname
, fp
->name
);
1890 showentry(stderr
, fp
, defaultcase
, 0);
1891 showentry(stderr
, fp
, ep
, 0);
1897 fprintf(stderr
, "^^ default case\n");
1900 if (debug
&& (constbits
& ~ep
->mask
)) {
1902 fprintf(stderr
, "const now 0x%lx\n", constbits
& ep
->mask
);
1904 constbits
&= ep
->mask
;
1910 if (constbits
== allbits
)
1911 printf("switch (code) {\n"/*}*/);
1913 printf("switch (code & 0x%lx) {\n"/*}*/, constbits
);
1914 for (ep
= fp
->first
; ep
!= NULL
; ep
= ep
->next
) {
1915 /* If this is not one of the entries under consideration, skip. */
1916 if ((ep
->mask
& mask
) != mask
|| (ep
->value
& mask
) != value
)
1918 if (ep
->done
|| ep
== defaultcase
)
1922 printf("case 0x%lx:\n", ep
->value
& constbits
);
1923 switch (functionswitch(fp
, mask
| constbits
,
1924 value
| (ep
->value
& constbits
))) {
1929 indentation
++; indent(); indentation
--;
1936 nconstbits
= bitcount(constbits
);
1937 missingcases
= ((nconstbits
== MAXBITS
) ? 0 : 1 << nconstbits
) - ncases
;
1938 if (alwaysreturns
) {
1939 switch (missingcases
) {
1941 if (defaultcase
!= NULL
) {
1942 fprintf(stderr
, "%s: warning: redundant entry:\n", progname
);
1943 showentry(stderr
, fp
, defaultcase
, 0);
1948 if (defaultcase
!= NULL
&& nconstbits
!= 0) {
1950 "%s: warning: variable bit(s) could be constant:\n",
1952 showentry(stderr
, fp
, defaultcase
, constbits
);
1960 if (defaultcase
!= NULL
) {
1961 /* If defaultcase has some constant bits of its own, recursion will
1962 check that they have the required value. */
1963 if ((defaultcase
->mask
& ~mask
) == 0) {
1965 if (compilestring(-1, defaultcase
->string
, fp
->type
) != 0)
1967 defaultcase
->done
= 1;
1970 alwaysreturns
= functionswitch(fp
, mask
, value
);
1975 return alwaysreturns
;
1979 int compilestring(int assignto
, struct string
*sp
, enum type type
) {
1982 tempno
= walkstring(sp
, COUNTARRAYS
, assignto
);
1983 if (tempno
> assignto
) {
1987 (void) walkstring(sp
, DECLAREARRAYS
, assignto
);
1988 if (walkstring(sp
, COMPILEARRAYS
, assignto
) < 0)
1991 if (compilecheckedstring(assignto
, sp
, type
) != 0)
1993 if (tempno
> assignto
) {
2002 int compilecheckedstring(int assignto
, struct string
*sp
, enum type type
) {
2003 compileassign(assignto
);
2004 if (compileconcat(sp
, type
) != 0)
2011 void compileassign(int assignto
) {
2016 compiletemp(assignto
);
2022 void compiletemp(int tempno
) {
2023 printf("t__%d", tempno
);
2027 void compiletext(char *s
) {
2030 for ( ; *s
!= '\0'; s
++) {
2043 int compileconcat(struct string
*sp
, enum type type
) {
2049 return compilenull(type
);
2050 if (sp
->next
== NULL
)
2051 return compilesimple(sp
, type
);
2052 if (type
!= T_INTEGER
) {
2053 for (elements
= 0, sp1
= sp
; sp1
!= NULL
; elements
++, sp1
= sp1
->next
) ;
2054 printf("dis_concat%d(", elements
);
2057 for (sp1
= sp
; sp1
!= NULL
; sp1
= sp1
->next
) {
2059 if (type
!= T_INTEGER
)
2061 if (sp1
->type
== S_ARRAY
)
2062 compilearrayref(sp1
->value
.array
);
2064 if (compilesimple(sp1
, type
) != 0)
2067 if (type
!= T_INTEGER
)
2073 int compilenull(enum type type
) {
2074 if (type
== T_INTEGER
) {
2075 fprintf(stderr
, "%s: empty integer expression\n", progname
);
2083 int compilesimple(struct string
*sp
, enum type type
) {
2085 return compilenull(type
);
2088 if (type
== T_INTEGER
)
2089 printf("%s", sp
->value
.text
);
2091 compiletext(sp
->value
.text
);
2094 compilebitstring(sp
->value
.bits
);
2097 compilebitsplice(sp
->value
.bitsplice
);
2100 putchar(sp
->value
.parameter
->name
);
2102 case S_FUNCTIONCALL
:
2103 return compilefunctioncall(sp
);
2105 if (compilearrayref(sp
->value
.array
) != 0)
2109 fprintf(stderr
, "compilesimple case %d", sp
->type
);
2116 int compilearrayref(struct array
*ap
) {
2117 compiletemp(ap
->tempno
);
2118 if (simplearray(ap
)) {
2120 if (compileconcat(ap
->index
, T_INTEGER
) != 0)
2128 int compilefunctioncall(struct string
*sp
) {
2129 struct function
*fp
;
2130 struct stringlist
*actualp
;
2131 struct arg
*formalp
;
2134 enum type formaltype
;
2136 assert(sp
->type
== S_FUNCTIONCALL
);
2137 fp
= sp
->value
.functioncall
->function
;
2138 printf("%s%c", fp
->name
, fp
->isarray
? '[' : '(');
2142 actualp
= sp
->value
.functioncall
->args
;
2143 while (actualp
!= NULL
) {
2146 formaltype
= T_INTEGER
;
2148 if (formalp
== NULL
) {
2149 fprintf(stderr
, "%s: too many arguments to %s:\n", progname
,
2151 showstring(stderr
, sp
);
2155 formaltype
= formalp
->type
;
2156 formalp
= formalp
->next
;
2158 if (actualp
->type
!= T_UNKNOWN
&& actualp
->type
!= formaltype
) {
2159 fprintf(stderr
, "%s: argument to %s has the wrong type:\n",
2160 progname
, fp
->name
);
2161 showstring(stderr
, actualp
->string
);
2167 if (compileconcat(actualp
->string
, formaltype
) != 0)
2169 actualp
= actualp
->next
;
2171 putchar(fp
->isarray
? ']' : ')');
2176 int walkstring(struct string
*sp
, enum walkstringop op
, int tempno
) {
2177 struct stringlist
*lp
;
2180 for ( ; sp
!= NULL
; sp
= sp
->next
) {
2183 ap
= sp
->value
.array
;
2184 for (lp
= ap
->elements
; lp
!= NULL
; lp
= lp
->next
)
2185 tempno
= walkstring(lp
->string
, op
, tempno
);
2186 tempno
= walkstring(ap
->index
, op
, tempno
);
2187 ap
->tempno
= ++tempno
;
2190 if (simplearray(ap
)) {
2193 compilesimplearray(&ap
->type
, NULL
, tempno
, ap
);
2198 if (!simplearray(ap
))
2199 if (compilearray(ap
) != 0)
2206 case S_FUNCTIONCALL
:
2207 for (lp
= sp
->value
.functioncall
->args
; lp
!= NULL
; lp
= lp
->next
)
2208 tempno
= walkstring(lp
->string
, op
, tempno
);
2218 int compilearray(struct array
*ap
) {
2219 struct stringlist
*ep
;
2224 if (compileconcat(ap
->index
, T_INTEGER
) != 0)
2226 printf(") {\n"/*}*/);
2227 for (i
= 0, ep
= ap
->elements
; ep
!= NULL
; i
++, ep
= ep
->next
) {
2229 printf("case %d:\n", i
);
2231 if (compilecheckedstring(ap
->tempno
, ep
->string
, ap
->type
) != 0)
2243 void compilesimplearray(enum type
*tp
, char *name
, int num
, struct array
*ap
) {
2244 struct stringlist
*lp
;
2247 fixedlength
= (*tp
== T_INTEGER
) ? 0 : checkfixedlength(ap
);
2248 if (fixedlength
> 0)
2251 compiletype(stdout
, tp
);
2257 if (fixedlength
> 0)
2258 printf("[%d]", fixedlength
);
2259 printf(" = {\n"/*}*/);
2261 for (lp
= ap
->elements
; lp
!= NULL
; lp
= lp
->next
) {
2263 compilesimple(lp
->string
, lp
->type
);
2268 printf(/*{*/"};\n");
2272 void declarearray(struct array
*ap
) {
2274 compiletype(stdout
, &ap
->type
);
2275 compiletemp(ap
->tempno
);
2280 void compilebitstring(struct bits
*bp
) {
2284 printf("code & 0x%lx", bp
->mask
);
2286 printf(") >> %d", bp
->shift
);
2291 void compilebitsplice(struct bitsplice
*splicep
) {
2292 struct bitsplicebits
*bsp
;
2296 for (bsp
= splicep
->splice
; bsp
!= NULL
; bsp
= bsp
->next
) {
2299 if (bsp
->type
== S_PARAMETER
)
2300 putchar(bsp
->value
.arg
->name
);
2302 assert(bsp
->type
== S_BITSTRING
);
2303 if (bsp
->value
.mask
== 0)
2306 printf("(code & 0x%lx)", bsp
->value
.mask
);
2309 printf(" << %d", bsp
->shift
);
2310 else if (bsp
->shift
< 0)
2311 printf(" >> %d", -bsp
->shift
);
2313 if (splicep
->entry
.value
!= 0)
2314 printf("%s0x%lx", last
, splicep
->entry
.value
);
2319 int bitcount(bits x
) {
2322 for (nbits
= 0; x
!= 0; x
>>= 1) {
2330 bits
allbitsset(int nbits
) {
2331 return (nbits
== MAXBITS
) ? ~0 : (1 << nbits
) - 1;
2335 void findent(FILE *f
) {
2338 for (i
= 1; i
< indentation
; i
+= 2)
2340 if (i
== indentation
)
2350 void *xrealloc(char *oldp
, size_t size
) {
2356 p
= realloc(oldp
, size
);
2358 fprintf(stderr
, "%s: allocate of %d bytes failed: %s\n", progname
,
2359 (int) size
, strerror(errno
));
2366 void *xmalloc(size_t size
) {
2367 return xrealloc(NULL
, size
);
2371 void *xstrdup(char *s
) {
2374 p
= xmalloc(strlen(s
) + 1);
2380 int prematureeof() {
2381 fprintf(stderr
, "%s: %s(%d): premature end of file\n", progname
, filename
,