]>
git.saurik.com Git - apple/xnu.git/blob - osfmk/ddb/makedis.c
5ff0b624efc18ab4cf13bd0e9e377d3466644dcb
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
36 * Revision 1.1.1.1 1998/09/22 21:05:48 wsanchez
37 * Import of Mac OS X kernel (~semeria)
39 * Revision 1.1.1.1 1998/03/07 02:26:09 wsanchez
40 * Import of OSF Mach kernel (~mburg)
42 * Revision 1.1.2.1 1997/03/27 18:46:52 barbou
44 * [1997/03/27 13:58:42 barbou]
49 /* makedis.c - make a disassembler. */
52 By Eamonn McManus <emcmanus@gr.osf.org>, April 1995.
53 Copyright 1995 by Eamonn McManus. Non-commercial use is permitted. */
57 This program generates a disassembler in C from a file describing the
58 opcodes of the machine in question. Lines in the description file are
59 either comments beginning with #, or contain three fields, with the
60 first two being terminated by space and the third containing the rest
61 of the line. Long logical lines can be split onto several physical
62 lines by ending each one except the last with a \. A logical line
63 can also be split immediately after a |. Unlike \, | is considered
64 part of the logical line. Leading spaces on continuation lines
65 following either \ or | are ignored.
67 Here is a concise description of the meanings of the three fields.
68 Examples later will make it clearer what they are used for.
70 The first field of the three is a function name. This will produce
71 a function or array of the same name in the C output, so it should
72 not conflict with other identifiers or C keywords. By default the
73 function named returns a string (a (char *) in C), but if the first
74 field is preceded by %, the function returns an unsigned long
77 The second field describes the arguments of the function. It consists
78 of two parts, either but not both of which may be omitted. The first
79 part is a string which is a bitmask describing the first argument of
80 the function. Each character of the string represents one bit,
81 with the least significant bit being the last. A character can be
82 0 or 1, representing that constant value, or a letter, representing
83 part of a bitfield. A given bitfield consists of all of the
84 contiguous bits containing the same letter. Upper and lower case
85 letters are considered different.
87 The second part of the second field is a list of parameters
88 describing the parameters of the function, or the parameters after
89 the first if the bitfield part was present. The list is contained
90 in parentheses () and the individual parameters are separated by
91 commas. Spaces are not allowed. Each parameter name is a single
92 letter, optionally preceded by %. The parameter is an unsigned
93 long integer if % is present, otherwise a string. Again, upper and
94 lower case parameter names are different.
96 The third field describes the value of the function. If a bitmask
97 is present in the second field and it contains constant bits (0s or
98 1s), then the third field is the value of the function only in the
99 case where its first argument contains matching values in those bit
100 positions. There can be many different lines naming the same
101 function but with different bitpatterns. The generated C code will
102 arrange to return the value corresponding to the pattern that
103 matches the actual first argument of the function when it is
104 called. This argument should not have bits set in positions beyond
105 those present in the bitpattern.
107 It is only allowed for two different lines to name the same function
108 if there is a bitstring in the second field. It is not allowed for
109 two such lines to specify exactly the same constant bit values. But
110 it is allowed for a line to have all the same constant bit values as
111 another plus some extra constant values. In this case the more
112 specific line applies when all of its constant bits match, and
113 otherwise the less specific line applies.
115 Apart from the contents of the bitstring, the second field must be
116 identical on every line referring to a given function, and the
117 bitstring must always be of the same length.
119 For string-valued functions, the third field is the string value.
120 For integer-valued functions, it is a C integer expression
121 generating the value. In both cases there may be several special
124 - A $ followed by a single letter is replaced by the value of the
125 argument or bitfield with that name. The value of a bitfield is
126 shifted as if that bitfield were in the least-significant bit
127 position. Thus, a single-bit field always has value 0 or 1.
129 - A $ followed by the name of a function and an argument list in
130 parentheses () is replaced by the value returned by the function
131 with those arguments. An integer value cannot be inserted into a
132 string without being converted by a function, nor can a string
133 value be used in an integer expression.
135 - A $ followed by a bitstring enclosed in [] is replaced by the
136 value of that bitstring. The bitstring has the same syntax as in
137 the second field, described above. Each contiguous sequence of
138 the same repeated letter in the bitstring is replaced by the
139 value of the argument or bitfield-argument with that name,
140 shifted into the appropriate position.
142 - A list of strings, separated by |, enclosed in
143 {}, and followed by an integer expression enclosed in [], is
144 replaced by the string in the list whose number matches the value
145 of the expression. The first string in the list is numbered 0.
146 If there is no string corresponding to the value of the
147 expression, the behaviour is undefined. The strings in the list
148 may themselves contain $ or {} operations.
150 - A \ followed by any character is replaced by that
151 character, without regard to any meaning it may usually have.
152 This is used to obtain strings containing characters such as
153 {, $, or \. The use of backslash to split long logical
154 lines takes precedence over this use, so \\ should not appear
155 at the end of a line.
157 The third field may also be a lone colon ":", in which case the
158 function is assumed to be defined externally and only a function
159 declaration (prototype) is generated.
164 Here are some examples from the description file for the Z80
165 microprocessor. This processor has 8-bit opcodes which are
166 disassembled by a generated function "inst" which looks like this:
168 typedef unsigned long bits;
169 char *inst(bits code) {...}
171 The simplest sort of line in the description file is one that looks
176 The first field names the function, "inst". The second field
177 implies that that function has exactly one argument which is an
178 integer, and that this line specifies the value of the function
179 when this integer has the binary value 01110110 (hex 0x76). This
180 value will be the string "halt".
182 A more complex line is one looking like this:
184 inst 001aa111 {daa|cpl|scf|ccf}[$a]
186 This line is compatible with the previous one, because it has the
187 same number of bits and the constant bits are different. It
188 specifies the value of inst when its argument looks like
189 001aa111, i.e., for the binary values
193 00111111. The value of $a for these four values will be
194 respectively binary 00, 01, 10, 11, i.e., 0 to 3. The
195 corresponding values of the inst function will be "daa", "cpl",
198 The description defines a helper function "reg8" like this:
200 reg8 rrr {b|c|d|e|h|l|(hl)|a}[$r]
202 This simply selects one of the eight strings between {} depending
203 on the value of the argument, which is assumed to be a three-bit
204 value. This could just as easily have been written:
206 reg8 (%r) {b|c|d|e|h|l|(hl)|a}[$r]
208 The generated C code is the same -- in each case makedis realises
209 that the function can be represented by an array rather than
210 compiling a C function.
212 The reg8 function is used in lines like this one:
214 inst 01rrrsss ld $reg8($r),$reg8($s)
216 Thus if the argument to inst is
218 then $r is 010 (2) and $s is 011 (3). Since reg8(2) is "d" and
219 reg8(3) is "e", the value of inst with this argument will be the
222 Note that the opcode for "halt" given above matches this pattern,
223 but because the bitpattern for "halt" is more specific (has more
224 constant bits) it is the one chosen when the argument is 01110110.
226 The description also uses an external C function "hexprint" defined
229 char *hexprint(bits digits, bits n) {
230 char *p = dis_alloc(digits + 1);
231 sprintf(p, "%0*lx", (int) digits, n);
235 The value of this function is a string containing the number n
236 spelt out in hex with "digits" digits. In the description
237 file this function is declared like this:
241 The names of the parameters are not important in this case as long
242 as they are letters and are different from each other.
244 The hexprint function is used in lines like this one:
246 inst 11vvv111 rst $hexprint(2,$v << 3)
248 If the argument to inst is
250 then $v is 011 (3) and the arguments to hexprint are 2 and (3 << 3),
251 i.e., 0x18. So the value of inst with this argument will be the
254 Instead of writing $v << 3, it would be possible to write
255 $[00vvv000]. For instance when $v is binary 011, this becomes
256 00011000. The leading 0s could be omitted.
258 The $[...] operation is particularly useful for moving bits around.
259 For instance, the HP PA-RISC opcodes contain bits assigned to
260 apparently random parts of the instruction word. One of the helper
261 functions in its description file looks like this:
263 im21l aaaaabbccddddddddddde l'$hex($[edddddddddddbbaaaaacc00000000000])
265 So 111110011000000000001 produces 10000000000000111111100000000000.
267 The $[...] operation can also be used to spell out binary constants,
268 since C has no syntax for this.
271 ...More to come... */
274 - More error detection, e.g., bitstring or arg not used in entry.
275 - Better error recovery -- nearly all errors are currently fatal.
276 - Clean up type handling, which is somewhat haphazard. It works but there
277 is stuff that is surely redundant.
278 - Make generated functions void by default, with $ prefix to indicate
279 string-value. In a void function, instead of returning a string (or
280 integer) it would be output via a user-supplied function.
281 - Further optimise and tidy generated code, e.g.: arrays of one-character
282 strings could be replaced by arrays of characters; switches with just
283 one case could be replaced by ifs.
295 #define LONG_BIT (CHAR_BIT * sizeof (long))
296 #endif /* LONG_BIT */
298 #define MAXfunction 32 /* Max function name length. */
299 #define MAXBITS LONG_BIT /* Max bitstring length. */
300 typedef unsigned long bits
;
301 enum type
{T_ERROR
, T_UNKNOWN
, T_INTEGER
, T_STRING
};
302 const char *const typename
[] = {"error", "unknown", "integer", "string"};
303 enum walkstringop
{COUNTARRAYS
, DECLAREARRAYS
, COMPILEARRAYS
};
304 char *bitstype
= "unsigned long";
306 int maxfunctionname
, maxargwidth
;
307 char *progname
= "makedis";
310 char *headerfilename
;
314 int debug
, dump
, warnings
;
316 /* componentbits has a 1 bit for every possible number of strings we may want
317 to concatenate together at some stage. A separate C function is compiled
318 for each such case. */
331 int main(int argc
, char **argv
);
332 int makedis(FILE *f
, char *fname
);
333 struct function
*findfunction(char *function
);
334 int parseextern(struct function
*fp
, FILE *f
);
335 struct function
*makefunction(char *function
);
336 int parsebits(struct function
*fp
, char *bitstring
, int nbits
);
337 int parseentrybits(struct entry
*ep
, char *bitstring
, int nbits
, int issplice
);
338 int parsecontrol(char *name
, char *value
);
339 int parseargs(struct function
*fp
, FILE *f
, int *cp
);
340 int parsestring(struct function
*fp
, char *str
);
341 enum type
makestring(struct function
*fp
, struct string
**stringlink
,
342 char **stringp
, char *magic
, enum type targettype
);
343 int parsedollar(struct function
*fp
, char **stringp
, struct string
*sp
);
344 int parsebitsplice(struct function
*fp
, char *bitstring
, int nbits
,
346 int findvariable(struct function
*fp
, int name
, struct string
*sp
);
347 int parsefunctioncall(struct function
*fp
, char *start
, char **stringp
,
349 int parsearray(struct function
*fp
, char **stringp
, struct string
*sp
,
351 void dumpfunctions(void);
352 void dumpfunction(struct function
*fp
);
353 void showentry(FILE *f
, struct function
*fp
, struct entry
*ep
, bits highlight
);
354 void showbits(FILE *f
, struct entry
*ep
, int nbits
, bits highlight
);
355 void showargs(FILE *f
, struct arg
*ap
, int fieldwidth
);
356 void showstring(FILE *f
, struct string
*sp
);
357 void showstringelement(FILE *f
, struct string
*sp
);
358 void showfunctioncall(FILE *f
, struct functioncall
*fcp
);
359 void showarray(FILE *f
, struct array
*ap
);
360 int outputfunctions(void);
361 void outputidentity(FILE *f
);
362 int outputdeclarations(void);
363 void outputconcats(void);
364 void outputconcat(int n
);
365 void outputconcatheader(FILE *f
, int n
);
366 void findarrays(void);
367 int checkfixedlength(struct array
*ap
);
368 int outputfunction(struct function
*fp
);
369 void functionarray(struct function
*fp
);
370 void functionheader(FILE *f
, struct function
*fp
);
371 int simplearray(struct array
*ap
);
372 void compiletype(FILE *f
, enum type
*tp
);
373 int functionswitch(struct function
*fp
, bits mask
, bits value
);
374 int compilestring(int assignto
, struct string
*sp
, enum type type
);
375 int compilecheckedstring(int assignto
, struct string
*sp
, enum type type
);
376 void compileassign(int assignto
);
377 void compiletemp(int tempno
);
378 void compiletext(char *s
);
379 int compileconcat(struct string
*sp
, enum type type
);
380 int compilenull(enum type type
);
381 int compilesimple(struct string
*sp
, enum type type
);
382 int compilearrayref(struct array
*ap
);
383 int compilefunctioncall(struct string
*sp
);
384 int walkstring(struct string
*sp
, enum walkstringop op
, int tempno
);
385 int compilearray(struct array
*ap
);
386 void compilesimplearray(enum type
*tp
, char *name
, int num
, struct array
*ap
);
387 void declarearray(struct array
*ap
);
388 void compilebitstring(struct bits
*bp
);
389 void compilebitsplice(struct bitsplice
*splicep
);
390 int bitcount(bits x
);
391 bits
allbitsset(int nbits
);
392 void findent(FILE *f
);
394 void *xrealloc(char *oldp
, size_t size
);
395 void *xmalloc(size_t size
);
396 void *xstrdup(char *s
);
397 int prematureeof(void);
400 int main(int argc
, char **argv
) {
407 for (i
= 1; i
< argc
&& argv
[i
][0] == '-'; i
++) {
408 switch (argv
[i
][1]) {
412 headerfilename
= argv
[i
]; break;
421 fprintf(stderr
, "Usage: %s [file]\n", progname
);
426 return makedis(stdin
, "<stdin>");
429 if ((f
= fopen(argv
[i
], "r")) == NULL
) {
430 fprintf(stderr
, "%s: %s: %s\n", progname
, argv
[i
], strerror(errno
));
433 return makedis(f
, argv
[i
]);
437 int makedis(FILE *f
, char *fname
) {
439 char function
[MAXfunction
], bitstring
[MAXBITS
];
440 static char *string
= NULL
;
446 /* Loop for every line in the description. */
448 /* Ignore initial spaces and newlines. */
449 while (isspace(c
= getc(f
)))
455 /* Ignore comments. # only allowed at start of line. */
457 while ((c
= getc(f
)) != '\n')
459 return prematureeof();
464 /* Read function name, terminated by space. */
465 for (i
= 0; i
< sizeof function
&& !isspace(c
); i
++, c
= getc(f
)) {
467 return prematureeof();
470 if (i
>= sizeof function
) {
471 fprintf(stderr
, "%s: %s(%d): function name is too long: %.*s\n",
472 progname
, filename
, lineno
, i
, function
);
477 /* Skip to next field. */
478 while (isspace(c
) && c
!= '\n')
481 /* If not a control statement, read bitstring and/or arguments. */
482 if (function
[0] == ':')
483 fp
= 0; /* Silence gcc. */
485 fp
= makefunction(function
);
489 /* Read optional bitstring. */
490 for (i
= 0; i
< sizeof bitstring
&& isalnum(c
); i
++, c
= getc(f
)) {
492 return prematureeof();
496 fprintf(stderr
, "%s: %s(%d): bit string is too long: %.*s\n",
497 progname
, filename
, lineno
, i
, bitstring
);
500 if (parsebits(fp
, bitstring
, i
) != 0)
503 /* Read optional arguments. */
504 if (parseargs(fp
, f
, &c
) != 0)
507 /* Skip to next field. */
508 while (isspace(c
) && c
!= '\n')
511 /* : indicates an external (C) function. */
513 if (parseextern(fp
, f
) != 0)
519 /* Read associated text. */
522 for ( ; c
!= '\n'; i
++, c
= getc(f
)) {
524 return prematureeof();
525 if (i
>= stringlen
) {
526 stringlen
= stringlen
* 2 + 16;
527 string
= xrealloc(string
, stringlen
);
533 switch (string
[i
- 1]) {
538 while (isspace(c
= getc(f
)) && c
!= '\n') ;
544 if (i
>= stringlen
) {
545 stringlen
= stringlen
* 2 + 16;
546 string
= xrealloc(string
, stringlen
);
550 /* Parse the line just read. */
551 if (function
[0] == ':') {
552 if (parsecontrol(function
+ 1, string
) != 0)
555 if (parsestring(fp
, string
) != 0)
561 return outputfunctions();
565 /* A function in the description file. nbits and nargs are -1 until the
566 real values are known. */
568 struct function
*next
;
571 int nbits
; /* Number of bits in the bitpattern, 0 if none. */
572 int nargs
; /* Number of (x,y,...) parameters, 0 if none. */
573 char isarray
; /* Will be represented by a C array. */
574 int fixedlength
; /* If a C array, will be a char [][N] not a char *[]. */
575 struct entry
*first
, *last
;
576 /* Links to the value(s) supplied. */
577 struct arg
*args
; /* List of (x,y,...) names and types. */
579 struct function
*functions
;
582 /* Find the function with the given name. If not found, create a structure
583 for it, fill it out with a template, and return that. */
584 struct function
*findfunction(char *name
) {
587 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
588 if (strcmp(fp
->name
, name
) == 0)
591 if (strlen(name
) > maxfunctionname
)
592 maxfunctionname
= strlen(name
);
593 fp
= xmalloc(sizeof *fp
);
594 fp
->next
= functions
;
596 fp
->name
= xstrdup(name
);
597 fp
->type
= T_UNKNOWN
;
598 fp
->nbits
= fp
->nargs
= -1; /* nbits will be set correctly later. */
600 fp
->first
= fp
->last
= NULL
;
605 /* Parse an external (C) function declaration. This will look something like:
607 We're called just after seeing the ':'.
608 Return 0 if parsing is successful, 1 otherwise. */
609 int parseextern(struct function
*fp
, FILE *f
) {
612 if ((c
= getc(f
)) != '\n') {
614 "%s: %s(%d): extern declaration should be a lone `:'\n",
615 progname
, filename
, lineno
);
618 if (fp
->nbits
!= 0) {
620 "%s: %s(%d): extern functions should not have bitstrings\n",
621 progname
, filename
, lineno
);
625 fp
->first
= fp
->last
= NULL
;
630 /* A value supplied for a function (the third field in a description line).
631 In general there can be any number of such values, differing in the
632 bitpattern supplied. The mask and value fields describe the constant
633 bits in the bitpattern: mask indicates which bits they are and value
634 indicates the values of those bits. So this entry matches
635 ((x & mask) == value). */
639 struct bits
*bits
; /* List of named bitfields. */
640 struct string
*string
; /* Value of function when bitpattern matched. */
641 char done
; /* This entry has already been compiled. */
645 /* We've just seen a definition of function "name". Make a structure for it
646 if necessary, and a template entry that will describe the value given here.
648 struct function
*makefunction(char *name
) {
650 struct entry
*ep
= xmalloc(sizeof *ep
);
653 if (name
[0] == '%') {
658 fp
= findfunction(name
);
659 if (fp
->type
== T_UNKNOWN
)
661 else if (fp
->type
!= type
) {
662 fprintf(stderr
, "%s: %s(%d): function %s previously declared as %s, "
663 "here as %s\n", progname
, filename
, lineno
, name
,
664 typename
[fp
->type
], typename
[type
]);
670 if (fp
->first
!= NULL
)
679 /* A named bitfield within the bitpattern of a function entry, or within a
680 $[...] bitsplice. The mask covers the bitfield and the shift says how
681 many 0 bits there are after the last 1 in the mask. */
690 /* Parse the bitstring supplied for the given function. nbits says how many
691 bits there are; it can legitimately be 0. Return value is 0 on success. */
692 int parsebits(struct function
*fp
, char *bitstring
, int nbits
) {
695 else if (fp
->nbits
!= nbits
) {
696 fprintf(stderr
, "%s: %s(%d): bit string of length %d;\n",
697 progname
, filename
, lineno
, nbits
);
698 fprintf(stderr
, " function %s has bit strings of length %d\n",
699 fp
->name
, fp
->nbits
);
702 return parseentrybits(fp
->last
, bitstring
, nbits
, 0);
706 /* Parse a bitstring that is the pattern for a function entry or that is in a
707 $[...] bitsplice. Put the result in ep. Return value is 0 on success. */
708 int parseentrybits(struct entry
*ep
, char *bitstring
, int nbits
, int issplice
) {
711 bits mask
, value
, entrymask
;
715 for (i
= 0; i
< nbits
; i
++) {
716 bit
= bitstring
[nbits
- 1 - i
];
726 fprintf(stderr
, "%s: %s(%d): invalid character in bitstring: %c\n",
727 progname
, filename
, lineno
, bit
);
731 for (bp
= ep
->bits
; bp
!= NULL
; bp
= bp
->next
) {
732 if (bp
->name
== bit
) {
734 "%s: %s(%d): bitstring name %c used twice\n",
735 progname
, filename
, lineno
, bit
);
741 for (j
= i
+ 1; j
< nbits
&& bitstring
[nbits
- 1 - j
] == bit
; j
++)
743 bp
= xmalloc(sizeof *bp
);
745 bp
->mask
= entrymask
;
757 /* Parse a control line. This looks something like:
758 :bitstype unsigned int
759 in which case we will be called with name "bitstype" and
760 value "unsigned int". */
761 int parsecontrol(char *name
, char *value
) {
762 if (strcmp(name
, "bitstype") == 0)
763 bitstype
= xstrdup(value
);
765 fprintf(stderr
, "%s: %s(%d): unrecognised control keyword %s\n",
766 progname
, filename
, lineno
, name
);
773 /* A parameter to a function, e.g., x in:
774 %f aaa(%x) $a + $x */
782 /* Parse the parameters (x,y,...) to a function and put the result in fp.
783 The entry that is being built is fp->last. cp points to the opening
784 (; if it does not point to a ( then there are no parameters. If
785 this is the first entry for the function, fp->nargs will be -1 and
786 we will build up an argument list. Otherwise, fp->nargs will be
787 >= 0 and we will only check that the arguments here are consistent
788 with what went before. Return value is 0 on success. */
789 int parseargs(struct function
*fp
, FILE *f
, int *cp
) {
790 struct arg
**arglink
, *ap
;
805 if (fp
->nargs
>= 0 && nargs
> fp
->nargs
) {
807 "%s: %s(%d): %d arg(s) instead of %d for %s\n",
808 progname
, filename
, lineno
, nargs
, fp
->nargs
,
819 if (!isalpha(name
)) {
821 "%s: %s(%d): argument should be letter: %c\n",
822 progname
, filename
, lineno
, name
);
825 for (bp
= fp
->last
->bits
; bp
!= NULL
; bp
= bp
->next
) {
826 if (bp
->name
== name
) {
828 "%s: %s(%d): %c is a bitstring and an arg\n",
829 progname
, filename
, lineno
, name
);
833 if (fp
->nargs
>= 0) {
834 if ((*arglink
)->name
!= name
) {
836 "%s: %s(%d): arg %d of %s is %c not %c\n",
837 progname
, filename
, lineno
, nargs
, fp
->name
,
838 (*arglink
)->name
, name
);
841 if ((*arglink
)->type
!= t
) {
843 "%s: %s(%d): arg %c of %s: inconsistent type\n",
844 progname
, filename
, lineno
, name
, fp
->name
);
848 for (ap
= fp
->args
; ap
!= *arglink
; ap
= ap
->next
) {
849 if (ap
->name
== name
) {
851 "%s: %s(%d): argument name %c used twice\n",
852 progname
, filename
, lineno
, name
);
856 *arglink
= xmalloc(sizeof **arglink
);
857 (*arglink
)->name
= name
;
858 (*arglink
)->type
= t
;
860 arglink
= &(*arglink
)->next
;
866 "%s: %s(%d): bad character in argument list: %c\n"
867 " (arguments must be single letters)\n",
868 progname
, filename
, lineno
, *cp
);
879 if (width
> maxargwidth
)
881 } else if (fp
->nargs
!= nargs
) {
882 fprintf(stderr
, "%s: %s(%d): argument list of length %d;\n",
883 progname
, filename
, lineno
, nargs
);
884 fprintf(stderr
, " function %s has argument lists of length %d\n",
885 fp
->name
, fp
->nargs
);
893 /* Parse the string describing the value of this entry for our
894 function. Return 0 on success. */
895 int parsestring(struct function
*fp
, char *str
) {
898 t
= makestring(fp
, &fp
->last
->string
, &str
, NULL
, fp
->type
);
901 if (fp
->type
!= t
&& t
!= T_UNKNOWN
) {
902 fprintf(stderr
, "%s: %s(%d): function %s has inconsistent types\n",
903 progname
, filename
, lineno
, fp
->name
);
910 /* A parsed representation of the whole string describing a value of a
911 function, or certain strings within that (e.g., array indices). This is a
912 linked list of substrings whose type is given by the type field. */
916 S_TEXT
, S_BITSTRING
, S_BITSPLICE
, S_PARAMETER
, S_FUNCTIONCALL
, S_ARRAY
918 union value
{ /* The fields here correspond to the enum values. */
919 char *text
; /* plain text */
920 struct bits
*bits
; /* $x where x is a bitfield */
921 struct bitsplice
*bitsplice
; /* $[...] */
922 struct arg
*parameter
; /* $x where x is a parameter */
923 struct functioncall
*functioncall
; /* $func(...) */
924 struct array
*array
; /* {...}[...] */
928 /* The representation of a function call $func(...) in the description of a
930 struct functioncall
{
931 struct function
*function
;
932 struct stringlist
*args
;
935 /* The representation of an array selection {...|...}[...] in the description
936 of a function value. tempno is used when constructing a C variable name
937 that will contain the strings or numbers in an array. */
939 struct string
*index
; /* what's between [...] */
940 struct stringlist
*elements
; /* what's between {...} */
941 enum type type
; /* the type of each element */
945 /* A list of strings, being the list of arguments in a function call or the
946 list of elements of an array. This is a linked list of linked lists. */
948 struct stringlist
*next
;
950 struct string
*string
;
954 /* The following are the only characters with special meaning at the top level
955 of parsing of a function value. When parsing arrays or function calls,
956 other characters become special. */
957 #define MAKESTRING_MAGIC "${"/*}*/
960 /* Parse a function return-value string or substring and make a struct string
961 list for it. The string starts at *stringp and ends at a \0 or at any
962 character in the `magic' string other than { or $. *stringp is updated
963 to point to the terminating character. The parsed representation is put
964 at *stringlink. `fp' is the function whose return value is being parsed.
965 `targettype' is the expected type of the result, if known.
966 The return value is the actual type. */
967 enum type
makestring(struct function
*fp
, struct string
**stringlink
,
968 char **stringp
, char *magic
, enum type targettype
) {
970 struct string
*sp
, **firststringlink
;
973 enum type t
= targettype
, newt
;
976 magic
= MAKESTRING_MAGIC
;
978 firststringlink
= stringlink
;
981 sp
= xmalloc(sizeof *sp
);
985 if (strchr(magic
, *q
) != NULL
) {
986 if (*q
!= ')' || parenlevel
== 0)
1000 } while (*++q
!= '\0');
1003 sp
->value
.text
= q
= xmalloc(n
+ 1);
1011 } else if (*p
== '$') {
1012 if (parsedollar(fp
, &p
, sp
) != 0)
1020 newt
= sp
->value
.parameter
->type
;
1022 case S_FUNCTIONCALL
:
1023 newt
= sp
->value
.functioncall
->function
->type
;
1026 fprintf(stderr
, "makestring type %d\n", sp
->type
);
1029 } else if (*p
== '{'/*}*/) {
1030 if (parsearray(fp
, &p
, sp
, t
) != 0)
1032 newt
= sp
->value
.array
->type
;
1039 else if (newt
!= T_UNKNOWN
&& t
!= newt
) {
1040 if (stringlink
== firststringlink
) {
1041 fprintf(stderr
, "%s: %s(%d): expected %s type:\n", progname
,
1042 filename
, lineno
, typename
[t
]);
1043 showstringelement(stderr
, sp
);
1047 fprintf(stderr
, "%s: %s(%d): mixed types in string:\n",
1048 progname
, filename
, lineno
);
1049 showstring(stderr
, *firststringlink
);
1050 fprintf(stderr
, " -- %s\n", typename
[t
]);
1051 showstringelement(stderr
, sp
);
1052 fprintf(stderr
, " -- %s\n", typename
[newt
]);
1056 stringlink
= &sp
->next
;
1061 if (components
>= MAXBITS
) {
1062 fprintf(stderr
, "%s: %s(%d): excessively complicated string\n",
1063 progname
, filename
, lineno
);
1066 componentbits
|= 1 << components
;
1071 /* Parse a $ operation at **stringp and update *stringp to point past it.
1072 `fp' is the function whose return value is being parsed. The parsed
1073 item will be put at *sp. Return 0 on success, nonzero on error. */
1074 int parsedollar(struct function
*fp
, char **stringp
, struct string
*sp
) {
1082 while (isalnum(*p
) || *p
== '_')
1084 if (*start
== '[') {
1086 fprintf(stderr
, "%s: %s(%d): missing ] or bad character in $[\n",
1087 progname
, filename
, lineno
);
1091 return parsebitsplice(fp
, start
+ 1, p
- start
- 1, sp
);
1094 fprintf(stderr
, "%s: %s(%d): missing identifier after $\n", progname
,
1098 if (p
== start
+ 1) {
1099 if (findvariable(fp
, *start
, sp
) != 0)
1102 if (parsefunctioncall(fp
, start
, &p
, sp
) != 0)
1110 /* The representation of a $[...] bitsplice. It is parsed into a
1111 struct entry just as if it were a bitfield parameter, then analysed
1112 into a chain of struct bitsplicebits. These in conjunction with
1113 the constant portion of the struct entry will allow the bitsplice to
1114 be compiled. Each bitsplicebits element represents either a numeric
1115 argument to the current function, in which case it will be shifted
1116 into place; or a bitfield name from the bitfield description of the
1117 current function, in which case it will be shifted by the difference
1118 between the position of the bitfield in the argument and the position
1119 it occurs in the bitsplice. `shift' indicates how much to shift left
1120 the associated value; if it is negative the value is shifted right.
1121 For instance, in a function like this:
1122 %oh xx00(%y) $[yyxx]
1123 the bitsplicebits for y will have shift = 2 and value.arg pointing to y,
1124 and those for x will have shift = -2 and value.mask = binary 1100.
1125 As an optimisation, contiguous bitfields that are also contiguous in the
1126 bitsplice will be combined. For instance:
1127 %oh xxyy00 $[0xxyy0]
1128 will compile the same code as:
1129 %oh zzzz00 $[0zzzz0].
1130 As another optimisation, a bitfield that occupies the entire bitstring
1131 for a function will be treated like a parameter in that it will not be
1132 masked in the bitsplice. For instance:
1133 %oh xxxxxx $[0xxxxxx0]
1134 will compile the same code as:
1135 %oh (%x) $[0xxxxxx0]. */
1139 struct bitsplicebits
*splice
;
1141 struct bitsplicebits
{
1142 struct bitsplicebits
*next
;
1144 enum elementtype type
;
1152 int parsebitsplice(struct function
*fp
, char *bitstring
, int nbits
,
1153 struct string
*sp
) {
1154 struct bitsplice
*splicep
;
1155 struct bitsplicebits
*bsp
, *lastbsp
, **bspp
;
1157 int shift
, nfrombits
, ntobits
;
1160 splicep
= xmalloc(sizeof *splicep
);
1161 splicep
->nbits
= nbits
;
1162 if (parseentrybits(&splicep
->entry
, bitstring
, nbits
, 1) != 0)
1164 bspp
= &splicep
->splice
;
1166 for (bp
= splicep
->entry
.bits
; bp
!= NULL
; bp
= bp
->next
) {
1167 if (findvariable(fp
, bp
->name
, sp
) != 0)
1170 if (sp
->type
== S_BITSTRING
) {
1171 nfrombits
= bitcount(sp
->value
.bits
->mask
);
1172 ntobits
= bitcount(bp
->mask
);
1174 if (nfrombits
!= ntobits
) {
1175 fprintf(stderr
, "%s: %s(%d): warning: "
1176 "bitstring $%c %ser than its place "
1178 progname
, filename
, lineno
, bp
->name
,
1179 (nfrombits
> ntobits
) ? "bigg" : "small");
1182 shift
-= sp
->value
.bits
->shift
;
1184 /* See if this bitfield can be combined with a previous contiguous
1186 if (lastbsp
!= NULL
&& lastbsp
->type
== S_BITSTRING
1187 && lastbsp
->shift
== shift
) {
1188 lastbsp
->value
.mask
|= sp
->value
.bits
->mask
;
1192 assert(sp
->type
== S_PARAMETER
);
1193 if (sp
->value
.parameter
->type
!= T_INTEGER
) {
1195 "%s: %s(%d): variable %c in $[...] should be integer\n",
1196 progname
, filename
, lineno
, sp
->value
.parameter
->name
);
1200 *bspp
= bsp
= xmalloc(sizeof *bsp
);
1201 bsp
->type
= sp
->type
;
1203 if (sp
->type
== S_PARAMETER
)
1204 bsp
->value
.arg
= sp
->value
.parameter
;
1206 bsp
->value
.mask
= sp
->value
.bits
->mask
;
1212 /* Look for a spliced element that is the entire bitstring argument to
1213 this function and therefore doesn't need to be masked. */
1214 allbits
= allbitsset(fp
->nbits
);
1215 for (bsp
= splicep
->splice
; bsp
!= NULL
; bsp
= bsp
->next
) {
1216 if (bsp
->type
== S_BITSTRING
) {
1217 for (b
= bsp
->value
.mask
; b
!= 0 && !(b
& 1); b
>>= 1) ;
1219 bsp
->value
.mask
= 0;
1222 sp
->type
= S_BITSPLICE
;
1223 sp
->value
.bitsplice
= splicep
;
1228 int findvariable(struct function
*fp
, int name
, struct string
*sp
) {
1232 for (bp
= fp
->last
->bits
; bp
!= NULL
; bp
= bp
->next
) {
1233 if (bp
->name
== name
) {
1234 sp
->type
= S_BITSTRING
;
1235 sp
->value
.bits
= bp
;
1239 for (ap
= fp
->args
; ap
!= NULL
; ap
= ap
->next
) {
1240 if (ap
->name
== name
) {
1241 sp
->type
= S_PARAMETER
;
1242 sp
->value
.parameter
= ap
;
1246 fprintf(stderr
, "%s: %s(%d): undefined parameter %c\n", progname
, filename
,
1252 int parsefunctioncall(struct function
*fp
, char *start
, char **stringp
,
1253 struct string
*sp
) {
1255 struct functioncall
*fcp
;
1256 struct stringlist
**arglink
, *arg
;
1261 fprintf(stderr
, "%s: %s(%d): missing ( after function %.*s\n", progname
,
1262 filename
, lineno
, p
- start
, start
);
1265 sp
->type
= S_FUNCTIONCALL
;
1266 sp
->value
.functioncall
= fcp
= xmalloc(sizeof *fcp
);
1267 *p
= '\0'; /* Ugly. */
1268 fcp
->function
= findfunction(start
);
1270 arglink
= &fcp
->args
;
1273 arg
= xmalloc(sizeof *arg
);
1274 t
= makestring(fp
, &arg
->string
, &p
, MAKESTRING_MAGIC
",)",
1280 arglink
= &arg
->next
;
1294 int parsearray(struct function
*fp
, char **stringp
, struct string
*sp
,
1298 struct stringlist
**elementlink
, *element
;
1301 assert(*p
== '{'/*}*/);
1303 sp
->value
.array
= ap
= xmalloc(sizeof *ap
);
1305 elementlink
= &ap
->elements
;
1307 if (*++p
!= /*{*/'}') {
1309 element
= xmalloc(sizeof *element
);
1310 t
= makestring(fp
, &element
->string
, &p
,
1311 MAKESTRING_MAGIC
/*{*/"|}", t
);
1315 if (ap
->type
== T_UNKNOWN
)
1317 else if (t
!= T_UNKNOWN
&& ap
->type
!= t
) {
1318 fprintf(stderr
, "%s: %s(%d): mixed types in array:\n",
1319 progname
, filename
, lineno
);
1320 showstring(stderr
, ap
->elements
->string
);
1321 fprintf(stderr
, " -- %s\n", typename
[ap
->type
]);
1322 showstring(stderr
, element
->string
);
1323 fprintf(stderr
, " -- %s\n", typename
[t
]);
1326 *elementlink
= element
;
1327 elementlink
= &element
->next
;
1334 *elementlink
= NULL
;
1335 assert(*p
== /*{*/'}');
1337 fprintf(stderr
, "%s: %s(%d): missing [index] after array\n",
1338 progname
, filename
, lineno
);
1342 t
= makestring(fp
, &ap
->index
, &p
, MAKESTRING_MAGIC
"]", T_INTEGER
);
1345 if (t
== T_STRING
) {
1346 fprintf(stderr
, "%s: %s(%d): array index cannot be string:\n",
1347 progname
, filename
, lineno
);
1348 showstring(stderr
, ap
->index
);
1352 fprintf(stderr
, "%s: %s(%d): [ without ]\n", progname
, filename
,
1361 void dumpfunctions() {
1362 struct function
*fp
;
1364 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
)
1369 void dumpfunction(struct function
*fp
) {
1372 for (ep
= fp
->first
; ep
!= NULL
; ep
= ep
->next
)
1373 showentry(stderr
, fp
, ep
, 0);
1377 /* Entries are not shown exactly as they would be input, since \ would
1378 need to be provided before some characters such as $ or {. But the
1379 characters "|},]" pose a problem since a \ is only needed in certain
1380 contexts and is annoying otherwise. It's not worth doing this right,
1381 since it's only used for error messages. */
1382 void showentry(FILE *f
, struct function
*fp
, struct entry
*ep
, bits highlight
) {
1383 if (fp
->type
== T_INTEGER
)
1385 fprintf(f
, "%-*s ", maxfunctionname
+ 1, fp
->name
);
1386 if (fp
->nbits
== 0 && fp
->nargs
== 0)
1387 fprintf(f
, "%-*s", maxargwidth
, "()");
1389 showbits(f
, ep
, fp
->nbits
, 0);
1390 showargs(f
, fp
->args
, maxargwidth
- fp
->nbits
);
1393 showstring(f
, ep
->string
);
1395 if (highlight
!= 0) {
1396 fprintf(f
, "%-*s ", maxfunctionname
+ 1, "");
1397 showbits(f
, ep
, fp
->nbits
, highlight
);
1403 void showbits(FILE *f
, struct entry
*ep
, int nbits
, bits highlight
) {
1410 i
= 1 << (nbits
- 1);
1422 if (highlight
!= 0 || (ep
->mask
& i
)) {
1423 putc((value
& i
) ? one
: zero
, f
);
1426 assert(bp
!= NULL
&& (bp
->mask
& i
));
1430 } while (bp
->mask
& i
);
1437 void showargs(FILE *f
, struct arg
*ap
, int fieldwidth
) {
1448 isint
= (ap
->type
== T_INTEGER
);
1449 fprintf(f
, "%c%s%c", lastc
, isint
? "%" : "", ap
->name
);
1453 } while (ap
!= NULL
);
1456 fprintf(f
, "%-*s", fieldwidth
- width
, "");
1460 void showstring(FILE *f
, struct string
*sp
) {
1461 for ( ; sp
!= NULL
; sp
= sp
->next
)
1462 showstringelement(f
, sp
);
1466 void showstringelement(FILE *f
, struct string
*sp
) {
1467 struct bitsplice
*bsp
;
1471 fputs(sp
->value
.text
, f
);
1474 fprintf(f
, "$%c", sp
->value
.bits
->name
);
1478 bsp
= sp
->value
.bitsplice
;
1479 showbits(f
, &bsp
->entry
, bsp
->nbits
, 0);
1483 fprintf(f
, "$%c", sp
->value
.parameter
->name
);
1485 case S_FUNCTIONCALL
:
1486 showfunctioncall(f
, sp
->value
.functioncall
);
1489 showarray(f
, sp
->value
.array
);
1492 fprintf(stderr
, "showstring case %d\n", sp
->type
);
1498 void showfunctioncall(FILE *f
, struct functioncall
*fcp
) {
1499 struct stringlist
*sp
;
1502 fprintf(f
, "$%s(", fcp
->function
->name
);
1504 for (sp
= fcp
->args
; sp
!= NULL
; sp
= sp
->next
) {
1507 showstring(f
, sp
->string
);
1513 void showarray(FILE *f
, struct array
*ap
) {
1514 struct stringlist
*sp
;
1519 for (sp
= ap
->elements
; sp
!= NULL
; sp
= sp
->next
) {
1522 showstring(f
, sp
->string
);
1524 fputs(/*{*/"}[", f
);
1525 showstring(f
, ap
->index
);
1530 const char commonpreamble
[] = "\
1535 const char concatpreamble
[] = "\
1536 static char *dis_buf;\n\
1537 static int dis_bufindex, dis_buflen;\n\
1539 void *dis_alloc(size_t size)\n\
1542 int newindex = dis_bufindex + size;\n\
1543 if (newindex > dis_buflen) {\n\
1544 dis_buflen = newindex * 4;\n\
1545 dis_buf = malloc(dis_buflen);\n\
1546 /* We can't use realloc because there might be pointers extant into\n\
1547 the old buffer. So we waste the memory of the old buffer. We\n\
1548 should soon reach an adequate buffer size and stop leaking. */\n\
1549 if (dis_buf == 0) {\n\
1550 perror(\"malloc\");\n\
1553 dis_bufindex = 0;\n\
1555 p = dis_buf + dis_bufindex;\n\
1556 dis_bufindex = newindex;\n\
1562 dis_bufindex = 0;\n\
1567 const char concatdeclarations
[] = "\
1568 #include <string.h>\n\
1569 #include <stdlib.h>\n\
1570 #include <errno.h>\n\
1572 extern void *dis_realloc(void *p, size_t size); /* User-provided. */\n\
1573 void *dis_alloc(size_t size);\n\
1574 void dis_done(void);\n\
1577 const char nonconcatpreamble
[] = "\
1578 void dis_done() {}\n\
1582 int outputfunctions() {
1583 struct function
*fp
;
1585 outputidentity(stdout
);
1586 if (headerfilename
!= NULL
) {
1587 if ((headerfile
= fopen(headerfilename
, "w")) == NULL
) {
1588 fprintf(stderr
, "%s: create %s: %s\n", progname
, headerfilename
,
1592 outputidentity(headerfile
);
1593 fprintf(headerfile
, commonpreamble
, bitstype
);
1594 printf("\n#include \"%s\"\n", headerfilename
);
1596 printf(commonpreamble
, bitstype
);
1598 if (outputdeclarations() != 0)
1601 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
1605 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
1606 if (fp
->first
!= NULL
&& !fp
->isarray
) {
1607 if (outputfunction(fp
) != 0)
1615 void outputidentity(FILE *f
) {
1618 fprintf(f
, "/*\n * This file was generated by:\n *");
1619 for (p
= global_argv
; *p
!= NULL
; p
++)
1620 fprintf(f
, " %s", *p
);
1621 fprintf(f
, "\n */\n\n");
1625 int outputdeclarations() {
1626 FILE *f
= headerfile
? headerfile
: stdout
;
1627 struct function
*fp
;
1629 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
1630 if (fp
->type
!= T_UNKNOWN
) {
1632 fprintf(f
, "extern ");
1633 if (fp
->fixedlength
> 0)
1634 fprintf(f
, "char %s[][%d]", fp
->name
, fp
->fixedlength
);
1636 compiletype(f
, &fp
->type
);
1637 fprintf(f
, "%s[]", fp
->name
);
1640 functionheader(f
, fp
);
1648 void outputconcats() {
1651 if (componentbits
& ~3) {
1652 fputs(concatdeclarations
, headerfile
? headerfile
: stdout
);
1653 fputs(concatpreamble
, stdout
);
1655 fputs(nonconcatpreamble
, stdout
);
1656 for (i
= 2; i
< MAXBITS
; i
++) {
1657 if (componentbits
& (1 << i
))
1663 void outputconcat(int n
) {
1669 outputconcatheader(headerfile
, n
);
1670 fprintf(headerfile
, ";\n");
1672 outputconcatheader(stdout
, n
);
1673 printf("\n{\n void *p;\n int len = ");
1675 for (i
= 0; i
< n
; i
++) {
1676 printf("%sstrlen(p%d)", last
, i
);
1679 printf(";\n p = dis_alloc(len + 1);\n return ");
1680 for (i
= 1; i
< n
; i
++)
1682 printf("strcpy(p, p0)");
1683 for (i
= 1; i
< n
; i
++)
1684 printf(", p%d)", i
);
1689 void outputconcatheader(FILE *f
, int n
) {
1693 fprintf(f
, "char *dis_concat%d(", n
);
1694 for (i
= 0; i
< n
; i
++) {
1695 fprintf(f
, "%schar *p%d", last
, i
);
1703 struct function
*fp
;
1705 struct string
*estr
, *indexstr
;
1708 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
1709 if (fp
->nbits
> 0 && fp
->nargs
> 0)
1714 if (ep
== NULL
|| ep
->next
!= NULL
)
1717 if (estr
== NULL
|| estr
->next
!= NULL
|| estr
->type
!= S_ARRAY
)
1719 indexstr
= estr
->value
.array
->index
;
1720 if (indexstr
->next
!= NULL
)
1722 if (fp
->nbits
> 0) {
1724 if (bp
== NULL
|| bp
->next
!= NULL
|| bp
->shift
!= 0)
1726 if (bp
->mask
!= allbitsset(fp
->nbits
))
1728 if (indexstr
->type
!= S_BITSTRING
|| indexstr
->value
.bits
!= bp
)
1731 if (indexstr
->type
!= S_PARAMETER
1732 || indexstr
->value
.parameter
!= fp
->args
)
1735 if (!simplearray(estr
->value
.array
))
1739 (fp
->type
== T_INTEGER
) ? 0 : checkfixedlength(estr
->value
.array
);
1744 int checkfixedlength(struct array
*ap
) {
1745 int len
, maxlen
, wasted
, n
;
1746 struct stringlist
*lp
;
1749 for (lp
= ap
->elements
; lp
!= NULL
; lp
= lp
->next
) {
1750 if (lp
->string
== NULL
)
1752 assert(lp
->string
->type
== S_TEXT
);
1753 len
= strlen(lp
->string
->value
.text
);
1757 for (wasted
= n
= 0, lp
= ap
->elements
; lp
!= NULL
; n
++, lp
= lp
->next
) {
1758 if (lp
->string
== NULL
)
1760 wasted
+= maxlen
- strlen(lp
->string
->value
.text
);
1762 if (wasted
< n
* sizeof(char *)) /* Should be target's sizeof. */
1768 int outputfunction(struct function
*fp
) {
1770 functionheader(stdout
, fp
);
1771 printf("\n{\n"/*}*/);
1772 switch (functionswitch(fp
, 0, 0)) {
1777 fprintf(stderr
, "%s: warning: not all cases of %s covered\n",
1778 progname
, fp
->name
);
1786 void functionarray(struct function
*fp
) {
1789 ap
= fp
->first
->string
->value
.array
;
1791 compilesimplearray(&fp
->type
, fp
->name
, 0, ap
);
1795 void functionheader(FILE *f
, struct function
*fp
) {
1799 compiletype(f
, &fp
->type
);
1800 fprintf(f
, "%s(", fp
->name
);
1802 if (fp
->nbits
> 0) {
1803 fprintf(f
, "bits code");
1806 for (ap
= fp
->args
; ap
!= NULL
; ap
= ap
->next
) {
1808 compiletype(f
, &ap
->type
);
1818 int simplearray(struct array
*ap
) {
1819 struct stringlist
*lp
;
1821 for (lp
= ap
->elements
; lp
!= NULL
; lp
= lp
->next
) {
1822 if (lp
->string
!= NULL
1823 && (lp
->string
->next
!= NULL
|| lp
->string
->type
!= S_TEXT
))
1826 return (lp
== NULL
);
1830 void compiletype(FILE *f
, enum type
*tp
) {
1836 fprintf(f
, "char *");
1839 fprintf(f
, "bits ");
1842 fprintf(stderr
, "compiletype type %d\n", *tp
);
1848 /* Generate code for entries in function fp whose bitstring b satisfies
1849 the constraint (b & mask) == value. Return 1 if generated switch
1850 always does `return', 0 if not, -1 on error.
1851 The algorithm is as follows. Scan the eligible entries to find the
1852 largest set of bits not in the passed-in mask which always have a
1853 constant value (are not variable). One `default' entry is allowed
1854 all of whose bits are variable. For each value of the constant bits,
1855 generate a `switch' case and invoke the function recursively with
1856 that value included in the constraint parameters. The recursion
1857 stops when no set of constant bits is found, perhaps because the
1858 mask parameter has all bits set.
1859 This algorithm could be improved. Currently it will fail if there
1860 are input lines "xxyy", "00xx" and "yy00", each of which is default with
1861 respect to the others. The correct behaviour would then be to select
1862 a bit that is sometimes constant and deal with those cases first.
1863 But this problem has not yet arisen in real life. */
1864 int functionswitch(struct function
*fp
, bits mask
, bits value
) {
1865 struct entry
*ep
, *defaultcase
;
1866 bits allbits
, constbits
, missingcases
;
1867 int nhits
, ncases
, nconstbits
, alwaysreturns
;
1870 allbits
= allbitsset(fp
->nbits
);
1871 constbits
= allbits
& ~mask
;
1875 "functionswitch(%s): (x & 0x%lx) == 0x%lx; const == 0x%lx\n",
1876 fp
->name
, mask
, value
, constbits
);
1881 for (ep
= fp
->first
; ep
!= NULL
; ep
= ep
->next
) {
1882 /* If this is not one of the entries under consideration, skip. */
1884 || (ep
->mask
& mask
) != mask
|| (ep
->value
& mask
) != value
)
1888 showentry(stderr
, fp
, ep
, 0);
1890 /* If this entry has no constant bits in the still-variable portion,
1891 it's the default. */
1892 if ((constbits
& ep
->mask
) == 0) {
1893 if (defaultcase
!= NULL
) {
1895 "%s: function %s: unable to distinguish between:\n",
1896 progname
, fp
->name
);
1897 showentry(stderr
, fp
, defaultcase
, 0);
1898 showentry(stderr
, fp
, ep
, 0);
1904 fprintf(stderr
, "^^ default case\n");
1907 if (debug
&& (constbits
& ~ep
->mask
)) {
1909 fprintf(stderr
, "const now 0x%lx\n", constbits
& ep
->mask
);
1911 constbits
&= ep
->mask
;
1917 if (constbits
== allbits
)
1918 printf("switch (code) {\n"/*}*/);
1920 printf("switch (code & 0x%lx) {\n"/*}*/, constbits
);
1921 for (ep
= fp
->first
; ep
!= NULL
; ep
= ep
->next
) {
1922 /* If this is not one of the entries under consideration, skip. */
1923 if ((ep
->mask
& mask
) != mask
|| (ep
->value
& mask
) != value
)
1925 if (ep
->done
|| ep
== defaultcase
)
1929 printf("case 0x%lx:\n", ep
->value
& constbits
);
1930 switch (functionswitch(fp
, mask
| constbits
,
1931 value
| (ep
->value
& constbits
))) {
1936 indentation
++; indent(); indentation
--;
1943 nconstbits
= bitcount(constbits
);
1944 missingcases
= ((nconstbits
== MAXBITS
) ? 0 : 1 << nconstbits
) - ncases
;
1945 if (alwaysreturns
) {
1946 switch (missingcases
) {
1948 if (defaultcase
!= NULL
) {
1949 fprintf(stderr
, "%s: warning: redundant entry:\n", progname
);
1950 showentry(stderr
, fp
, defaultcase
, 0);
1955 if (defaultcase
!= NULL
&& nconstbits
!= 0) {
1957 "%s: warning: variable bit(s) could be constant:\n",
1959 showentry(stderr
, fp
, defaultcase
, constbits
);
1967 if (defaultcase
!= NULL
) {
1968 /* If defaultcase has some constant bits of its own, recursion will
1969 check that they have the required value. */
1970 if ((defaultcase
->mask
& ~mask
) == 0) {
1972 if (compilestring(-1, defaultcase
->string
, fp
->type
) != 0)
1974 defaultcase
->done
= 1;
1977 alwaysreturns
= functionswitch(fp
, mask
, value
);
1982 return alwaysreturns
;
1986 int compilestring(int assignto
, struct string
*sp
, enum type type
) {
1989 tempno
= walkstring(sp
, COUNTARRAYS
, assignto
);
1990 if (tempno
> assignto
) {
1994 (void) walkstring(sp
, DECLAREARRAYS
, assignto
);
1995 if (walkstring(sp
, COMPILEARRAYS
, assignto
) < 0)
1998 if (compilecheckedstring(assignto
, sp
, type
) != 0)
2000 if (tempno
> assignto
) {
2009 int compilecheckedstring(int assignto
, struct string
*sp
, enum type type
) {
2010 compileassign(assignto
);
2011 if (compileconcat(sp
, type
) != 0)
2018 void compileassign(int assignto
) {
2023 compiletemp(assignto
);
2029 void compiletemp(int tempno
) {
2030 printf("t__%d", tempno
);
2034 void compiletext(char *s
) {
2037 for ( ; *s
!= '\0'; s
++) {
2050 int compileconcat(struct string
*sp
, enum type type
) {
2056 return compilenull(type
);
2057 if (sp
->next
== NULL
)
2058 return compilesimple(sp
, type
);
2059 if (type
!= T_INTEGER
) {
2060 for (elements
= 0, sp1
= sp
; sp1
!= NULL
; elements
++, sp1
= sp1
->next
) ;
2061 printf("dis_concat%d(", elements
);
2064 for (sp1
= sp
; sp1
!= NULL
; sp1
= sp1
->next
) {
2066 if (type
!= T_INTEGER
)
2068 if (sp1
->type
== S_ARRAY
)
2069 compilearrayref(sp1
->value
.array
);
2071 if (compilesimple(sp1
, type
) != 0)
2074 if (type
!= T_INTEGER
)
2080 int compilenull(enum type type
) {
2081 if (type
== T_INTEGER
) {
2082 fprintf(stderr
, "%s: empty integer expression\n", progname
);
2090 int compilesimple(struct string
*sp
, enum type type
) {
2092 return compilenull(type
);
2095 if (type
== T_INTEGER
)
2096 printf("%s", sp
->value
.text
);
2098 compiletext(sp
->value
.text
);
2101 compilebitstring(sp
->value
.bits
);
2104 compilebitsplice(sp
->value
.bitsplice
);
2107 putchar(sp
->value
.parameter
->name
);
2109 case S_FUNCTIONCALL
:
2110 return compilefunctioncall(sp
);
2112 if (compilearrayref(sp
->value
.array
) != 0)
2116 fprintf(stderr
, "compilesimple case %d", sp
->type
);
2123 int compilearrayref(struct array
*ap
) {
2124 compiletemp(ap
->tempno
);
2125 if (simplearray(ap
)) {
2127 if (compileconcat(ap
->index
, T_INTEGER
) != 0)
2135 int compilefunctioncall(struct string
*sp
) {
2136 struct function
*fp
;
2137 struct stringlist
*actualp
;
2138 struct arg
*formalp
;
2141 enum type formaltype
;
2143 assert(sp
->type
== S_FUNCTIONCALL
);
2144 fp
= sp
->value
.functioncall
->function
;
2145 printf("%s%c", fp
->name
, fp
->isarray
? '[' : '(');
2149 actualp
= sp
->value
.functioncall
->args
;
2150 while (actualp
!= NULL
) {
2153 formaltype
= T_INTEGER
;
2155 if (formalp
== NULL
) {
2156 fprintf(stderr
, "%s: too many arguments to %s:\n", progname
,
2158 showstring(stderr
, sp
);
2162 formaltype
= formalp
->type
;
2163 formalp
= formalp
->next
;
2165 if (actualp
->type
!= T_UNKNOWN
&& actualp
->type
!= formaltype
) {
2166 fprintf(stderr
, "%s: argument to %s has the wrong type:\n",
2167 progname
, fp
->name
);
2168 showstring(stderr
, actualp
->string
);
2174 if (compileconcat(actualp
->string
, formaltype
) != 0)
2176 actualp
= actualp
->next
;
2178 putchar(fp
->isarray
? ']' : ')');
2183 int walkstring(struct string
*sp
, enum walkstringop op
, int tempno
) {
2184 struct stringlist
*lp
;
2187 for ( ; sp
!= NULL
; sp
= sp
->next
) {
2190 ap
= sp
->value
.array
;
2191 for (lp
= ap
->elements
; lp
!= NULL
; lp
= lp
->next
)
2192 tempno
= walkstring(lp
->string
, op
, tempno
);
2193 tempno
= walkstring(ap
->index
, op
, tempno
);
2194 ap
->tempno
= ++tempno
;
2197 if (simplearray(ap
)) {
2200 compilesimplearray(&ap
->type
, NULL
, tempno
, ap
);
2205 if (!simplearray(ap
))
2206 if (compilearray(ap
) != 0)
2213 case S_FUNCTIONCALL
:
2214 for (lp
= sp
->value
.functioncall
->args
; lp
!= NULL
; lp
= lp
->next
)
2215 tempno
= walkstring(lp
->string
, op
, tempno
);
2225 int compilearray(struct array
*ap
) {
2226 struct stringlist
*ep
;
2231 if (compileconcat(ap
->index
, T_INTEGER
) != 0)
2233 printf(") {\n"/*}*/);
2234 for (i
= 0, ep
= ap
->elements
; ep
!= NULL
; i
++, ep
= ep
->next
) {
2236 printf("case %d:\n", i
);
2238 if (compilecheckedstring(ap
->tempno
, ep
->string
, ap
->type
) != 0)
2250 void compilesimplearray(enum type
*tp
, char *name
, int num
, struct array
*ap
) {
2251 struct stringlist
*lp
;
2254 fixedlength
= (*tp
== T_INTEGER
) ? 0 : checkfixedlength(ap
);
2255 if (fixedlength
> 0)
2258 compiletype(stdout
, tp
);
2264 if (fixedlength
> 0)
2265 printf("[%d]", fixedlength
);
2266 printf(" = {\n"/*}*/);
2268 for (lp
= ap
->elements
; lp
!= NULL
; lp
= lp
->next
) {
2270 compilesimple(lp
->string
, lp
->type
);
2275 printf(/*{*/"};\n");
2279 void declarearray(struct array
*ap
) {
2281 compiletype(stdout
, &ap
->type
);
2282 compiletemp(ap
->tempno
);
2287 void compilebitstring(struct bits
*bp
) {
2291 printf("code & 0x%lx", bp
->mask
);
2293 printf(") >> %d", bp
->shift
);
2298 void compilebitsplice(struct bitsplice
*splicep
) {
2299 struct bitsplicebits
*bsp
;
2303 for (bsp
= splicep
->splice
; bsp
!= NULL
; bsp
= bsp
->next
) {
2306 if (bsp
->type
== S_PARAMETER
)
2307 putchar(bsp
->value
.arg
->name
);
2309 assert(bsp
->type
== S_BITSTRING
);
2310 if (bsp
->value
.mask
== 0)
2313 printf("(code & 0x%lx)", bsp
->value
.mask
);
2316 printf(" << %d", bsp
->shift
);
2317 else if (bsp
->shift
< 0)
2318 printf(" >> %d", -bsp
->shift
);
2320 if (splicep
->entry
.value
!= 0)
2321 printf("%s0x%lx", last
, splicep
->entry
.value
);
2326 int bitcount(bits x
) {
2329 for (nbits
= 0; x
!= 0; x
>>= 1) {
2337 bits
allbitsset(int nbits
) {
2338 return (nbits
== MAXBITS
) ? ~0 : (1 << nbits
) - 1;
2342 void findent(FILE *f
) {
2345 for (i
= 1; i
< indentation
; i
+= 2)
2347 if (i
== indentation
)
2357 void *xrealloc(char *oldp
, size_t size
) {
2363 p
= realloc(oldp
, size
);
2365 fprintf(stderr
, "%s: allocate of %d bytes failed: %s\n", progname
,
2366 (int) size
, strerror(errno
));
2373 void *xmalloc(size_t size
) {
2374 return xrealloc(NULL
, size
);
2378 void *xstrdup(char *s
) {
2381 p
= xmalloc(strlen(s
) + 1);
2387 int prematureeof() {
2388 fprintf(stderr
, "%s: %s(%d): premature end of file\n", progname
, filename
,