]>
git.saurik.com Git - apple/xnu.git/blob - osfmk/ddb/makedis.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_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. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
34 * Revision 1.1.1.1 1998/09/22 21:05:48 wsanchez
35 * Import of Mac OS X kernel (~semeria)
37 * Revision 1.1.1.1 1998/03/07 02:26:09 wsanchez
38 * Import of OSF Mach kernel (~mburg)
40 * Revision 1.1.2.1 1997/03/27 18:46:52 barbou
42 * [1997/03/27 13:58:42 barbou]
47 /* makedis.c - make a disassembler. */
50 By Eamonn McManus <emcmanus@gr.osf.org>, April 1995.
51 Copyright 1995 by Eamonn McManus. Non-commercial use is permitted. */
55 This program generates a disassembler in C from a file describing the
56 opcodes of the machine in question. Lines in the description file are
57 either comments beginning with #, or contain three fields, with the
58 first two being terminated by space and the third containing the rest
59 of the line. Long logical lines can be split onto several physical
60 lines by ending each one except the last with a \. A logical line
61 can also be split immediately after a |. Unlike \, | is considered
62 part of the logical line. Leading spaces on continuation lines
63 following either \ or | are ignored.
65 Here is a concise description of the meanings of the three fields.
66 Examples later will make it clearer what they are used for.
68 The first field of the three is a function name. This will produce
69 a function or array of the same name in the C output, so it should
70 not conflict with other identifiers or C keywords. By default the
71 function named returns a string (a (char *) in C), but if the first
72 field is preceded by %, the function returns an unsigned long
75 The second field describes the arguments of the function. It consists
76 of two parts, either but not both of which may be omitted. The first
77 part is a string which is a bitmask describing the first argument of
78 the function. Each character of the string represents one bit,
79 with the least significant bit being the last. A character can be
80 0 or 1, representing that constant value, or a letter, representing
81 part of a bitfield. A given bitfield consists of all of the
82 contiguous bits containing the same letter. Upper and lower case
83 letters are considered different.
85 The second part of the second field is a list of parameters
86 describing the parameters of the function, or the parameters after
87 the first if the bitfield part was present. The list is contained
88 in parentheses () and the individual parameters are separated by
89 commas. Spaces are not allowed. Each parameter name is a single
90 letter, optionally preceded by %. The parameter is an unsigned
91 long integer if % is present, otherwise a string. Again, upper and
92 lower case parameter names are different.
94 The third field describes the value of the function. If a bitmask
95 is present in the second field and it contains constant bits (0s or
96 1s), then the third field is the value of the function only in the
97 case where its first argument contains matching values in those bit
98 positions. There can be many different lines naming the same
99 function but with different bitpatterns. The generated C code will
100 arrange to return the value corresponding to the pattern that
101 matches the actual first argument of the function when it is
102 called. This argument should not have bits set in positions beyond
103 those present in the bitpattern.
105 It is only allowed for two different lines to name the same function
106 if there is a bitstring in the second field. It is not allowed for
107 two such lines to specify exactly the same constant bit values. But
108 it is allowed for a line to have all the same constant bit values as
109 another plus some extra constant values. In this case the more
110 specific line applies when all of its constant bits match, and
111 otherwise the less specific line applies.
113 Apart from the contents of the bitstring, the second field must be
114 identical on every line referring to a given function, and the
115 bitstring must always be of the same length.
117 For string-valued functions, the third field is the string value.
118 For integer-valued functions, it is a C integer expression
119 generating the value. In both cases there may be several special
122 - A $ followed by a single letter is replaced by the value of the
123 argument or bitfield with that name. The value of a bitfield is
124 shifted as if that bitfield were in the least-significant bit
125 position. Thus, a single-bit field always has value 0 or 1.
127 - A $ followed by the name of a function and an argument list in
128 parentheses () is replaced by the value returned by the function
129 with those arguments. An integer value cannot be inserted into a
130 string without being converted by a function, nor can a string
131 value be used in an integer expression.
133 - A $ followed by a bitstring enclosed in [] is replaced by the
134 value of that bitstring. The bitstring has the same syntax as in
135 the second field, described above. Each contiguous sequence of
136 the same repeated letter in the bitstring is replaced by the
137 value of the argument or bitfield-argument with that name,
138 shifted into the appropriate position.
140 - A list of strings, separated by |, enclosed in
141 {}, and followed by an integer expression enclosed in [], is
142 replaced by the string in the list whose number matches the value
143 of the expression. The first string in the list is numbered 0.
144 If there is no string corresponding to the value of the
145 expression, the behaviour is undefined. The strings in the list
146 may themselves contain $ or {} operations.
148 - A \ followed by any character is replaced by that
149 character, without regard to any meaning it may usually have.
150 This is used to obtain strings containing characters such as
151 {, $, or \. The use of backslash to split long logical
152 lines takes precedence over this use, so \\ should not appear
153 at the end of a line.
155 The third field may also be a lone colon ":", in which case the
156 function is assumed to be defined externally and only a function
157 declaration (prototype) is generated.
162 Here are some examples from the description file for the Z80
163 microprocessor. This processor has 8-bit opcodes which are
164 disassembled by a generated function "inst" which looks like this:
166 typedef unsigned long bits;
167 char *inst(bits code) {...}
169 The simplest sort of line in the description file is one that looks
174 The first field names the function, "inst". The second field
175 implies that that function has exactly one argument which is an
176 integer, and that this line specifies the value of the function
177 when this integer has the binary value 01110110 (hex 0x76). This
178 value will be the string "halt".
180 A more complex line is one looking like this:
182 inst 001aa111 {daa|cpl|scf|ccf}[$a]
184 This line is compatible with the previous one, because it has the
185 same number of bits and the constant bits are different. It
186 specifies the value of inst when its argument looks like
187 001aa111, i.e., for the binary values
191 00111111. The value of $a for these four values will be
192 respectively binary 00, 01, 10, 11, i.e., 0 to 3. The
193 corresponding values of the inst function will be "daa", "cpl",
196 The description defines a helper function "reg8" like this:
198 reg8 rrr {b|c|d|e|h|l|(hl)|a}[$r]
200 This simply selects one of the eight strings between {} depending
201 on the value of the argument, which is assumed to be a three-bit
202 value. This could just as easily have been written:
204 reg8 (%r) {b|c|d|e|h|l|(hl)|a}[$r]
206 The generated C code is the same -- in each case makedis realises
207 that the function can be represented by an array rather than
208 compiling a C function.
210 The reg8 function is used in lines like this one:
212 inst 01rrrsss ld $reg8($r),$reg8($s)
214 Thus if the argument to inst is
216 then $r is 010 (2) and $s is 011 (3). Since reg8(2) is "d" and
217 reg8(3) is "e", the value of inst with this argument will be the
220 Note that the opcode for "halt" given above matches this pattern,
221 but because the bitpattern for "halt" is more specific (has more
222 constant bits) it is the one chosen when the argument is 01110110.
224 The description also uses an external C function "hexprint" defined
227 char *hexprint(bits digits, bits n) {
228 char *p = dis_alloc(digits + 1);
229 sprintf(p, "%0*lx", (int) digits, n);
233 The value of this function is a string containing the number n
234 spelt out in hex with "digits" digits. In the description
235 file this function is declared like this:
239 The names of the parameters are not important in this case as long
240 as they are letters and are different from each other.
242 The hexprint function is used in lines like this one:
244 inst 11vvv111 rst $hexprint(2,$v << 3)
246 If the argument to inst is
248 then $v is 011 (3) and the arguments to hexprint are 2 and (3 << 3),
249 i.e., 0x18. So the value of inst with this argument will be the
252 Instead of writing $v << 3, it would be possible to write
253 $[00vvv000]. For instance when $v is binary 011, this becomes
254 00011000. The leading 0s could be omitted.
256 The $[...] operation is particularly useful for moving bits around.
257 For instance, the HP PA-RISC opcodes contain bits assigned to
258 apparently random parts of the instruction word. One of the helper
259 functions in its description file looks like this:
261 im21l aaaaabbccddddddddddde l'$hex($[edddddddddddbbaaaaacc00000000000])
263 So 111110011000000000001 produces 10000000000000111111100000000000.
265 The $[...] operation can also be used to spell out binary constants,
266 since C has no syntax for this.
269 ...More to come... */
272 - More error detection, e.g., bitstring or arg not used in entry.
273 - Better error recovery -- nearly all errors are currently fatal.
274 - Clean up type handling, which is somewhat haphazard. It works but there
275 is stuff that is surely redundant.
276 - Make generated functions void by default, with $ prefix to indicate
277 string-value. In a void function, instead of returning a string (or
278 integer) it would be output via a user-supplied function.
279 - Further optimise and tidy generated code, e.g.: arrays of one-character
280 strings could be replaced by arrays of characters; switches with just
281 one case could be replaced by ifs.
293 #define LONG_BIT (CHAR_BIT * sizeof (long))
294 #endif /* LONG_BIT */
296 #define MAXfunction 32 /* Max function name length. */
297 #define MAXBITS LONG_BIT /* Max bitstring length. */
298 typedef unsigned long bits
;
299 enum type
{T_ERROR
, T_UNKNOWN
, T_INTEGER
, T_STRING
};
300 const char *const typename
[] = {"error", "unknown", "integer", "string"};
301 enum walkstringop
{COUNTARRAYS
, DECLAREARRAYS
, COMPILEARRAYS
};
302 char *bitstype
= "unsigned long";
304 int maxfunctionname
, maxargwidth
;
305 char *progname
= "makedis";
308 char *headerfilename
;
312 int debug
, dump
, warnings
;
314 /* componentbits has a 1 bit for every possible number of strings we may want
315 to concatenate together at some stage. A separate C function is compiled
316 for each such case. */
329 int main(int argc
, char **argv
);
330 int makedis(FILE *f
, char *fname
);
331 struct function
*findfunction(char *function
);
332 int parseextern(struct function
*fp
, FILE *f
);
333 struct function
*makefunction(char *function
);
334 int parsebits(struct function
*fp
, char *bitstring
, int nbits
);
335 int parseentrybits(struct entry
*ep
, char *bitstring
, int nbits
, int issplice
);
336 int parsecontrol(char *name
, char *value
);
337 int parseargs(struct function
*fp
, FILE *f
, int *cp
);
338 int parsestring(struct function
*fp
, char *str
);
339 enum type
makestring(struct function
*fp
, struct string
**stringlink
,
340 char **stringp
, char *magic
, enum type targettype
);
341 int parsedollar(struct function
*fp
, char **stringp
, struct string
*sp
);
342 int parsebitsplice(struct function
*fp
, char *bitstring
, int nbits
,
344 int findvariable(struct function
*fp
, int name
, struct string
*sp
);
345 int parsefunctioncall(struct function
*fp
, char *start
, char **stringp
,
347 int parsearray(struct function
*fp
, char **stringp
, struct string
*sp
,
349 void dumpfunctions(void);
350 void dumpfunction(struct function
*fp
);
351 void showentry(FILE *f
, struct function
*fp
, struct entry
*ep
, bits highlight
);
352 void showbits(FILE *f
, struct entry
*ep
, int nbits
, bits highlight
);
353 void showargs(FILE *f
, struct arg
*ap
, int fieldwidth
);
354 void showstring(FILE *f
, struct string
*sp
);
355 void showstringelement(FILE *f
, struct string
*sp
);
356 void showfunctioncall(FILE *f
, struct functioncall
*fcp
);
357 void showarray(FILE *f
, struct array
*ap
);
358 int outputfunctions(void);
359 void outputidentity(FILE *f
);
360 int outputdeclarations(void);
361 void outputconcats(void);
362 void outputconcat(int n
);
363 void outputconcatheader(FILE *f
, int n
);
364 void findarrays(void);
365 int checkfixedlength(struct array
*ap
);
366 int outputfunction(struct function
*fp
);
367 void functionarray(struct function
*fp
);
368 void functionheader(FILE *f
, struct function
*fp
);
369 int simplearray(struct array
*ap
);
370 void compiletype(FILE *f
, enum type
*tp
);
371 int functionswitch(struct function
*fp
, bits mask
, bits value
);
372 int compilestring(int assignto
, struct string
*sp
, enum type type
);
373 int compilecheckedstring(int assignto
, struct string
*sp
, enum type type
);
374 void compileassign(int assignto
);
375 void compiletemp(int tempno
);
376 void compiletext(char *s
);
377 int compileconcat(struct string
*sp
, enum type type
);
378 int compilenull(enum type type
);
379 int compilesimple(struct string
*sp
, enum type type
);
380 int compilearrayref(struct array
*ap
);
381 int compilefunctioncall(struct string
*sp
);
382 int walkstring(struct string
*sp
, enum walkstringop op
, int tempno
);
383 int compilearray(struct array
*ap
);
384 void compilesimplearray(enum type
*tp
, char *name
, int num
, struct array
*ap
);
385 void declarearray(struct array
*ap
);
386 void compilebitstring(struct bits
*bp
);
387 void compilebitsplice(struct bitsplice
*splicep
);
388 int bitcount(bits x
);
389 bits
allbitsset(int nbits
);
390 void findent(FILE *f
);
392 void *xrealloc(char *oldp
, size_t size
);
393 void *xmalloc(size_t size
);
394 void *xstrdup(char *s
);
395 int prematureeof(void);
398 int main(int argc
, char **argv
) {
405 for (i
= 1; i
< argc
&& argv
[i
][0] == '-'; i
++) {
406 switch (argv
[i
][1]) {
410 headerfilename
= argv
[i
]; break;
419 fprintf(stderr
, "Usage: %s [file]\n", progname
);
424 return makedis(stdin
, "<stdin>");
427 if ((f
= fopen(argv
[i
], "r")) == NULL
) {
428 fprintf(stderr
, "%s: %s: %s\n", progname
, argv
[i
], strerror(errno
));
431 return makedis(f
, argv
[i
]);
435 int makedis(FILE *f
, char *fname
) {
437 char function
[MAXfunction
], bitstring
[MAXBITS
];
438 static char *string
= NULL
;
444 /* Loop for every line in the description. */
446 /* Ignore initial spaces and newlines. */
447 while (isspace(c
= getc(f
)))
453 /* Ignore comments. # only allowed at start of line. */
455 while ((c
= getc(f
)) != '\n')
457 return prematureeof();
462 /* Read function name, terminated by space. */
463 for (i
= 0; i
< sizeof function
&& !isspace(c
); i
++, c
= getc(f
)) {
465 return prematureeof();
468 if (i
>= sizeof function
) {
469 fprintf(stderr
, "%s: %s(%d): function name is too long: %.*s\n",
470 progname
, filename
, lineno
, i
, function
);
475 /* Skip to next field. */
476 while (isspace(c
) && c
!= '\n')
479 /* If not a control statement, read bitstring and/or arguments. */
480 if (function
[0] == ':')
481 fp
= 0; /* Silence gcc. */
483 fp
= makefunction(function
);
487 /* Read optional bitstring. */
488 for (i
= 0; i
< sizeof bitstring
&& isalnum(c
); i
++, c
= getc(f
)) {
490 return prematureeof();
494 fprintf(stderr
, "%s: %s(%d): bit string is too long: %.*s\n",
495 progname
, filename
, lineno
, i
, bitstring
);
498 if (parsebits(fp
, bitstring
, i
) != 0)
501 /* Read optional arguments. */
502 if (parseargs(fp
, f
, &c
) != 0)
505 /* Skip to next field. */
506 while (isspace(c
) && c
!= '\n')
509 /* : indicates an external (C) function. */
511 if (parseextern(fp
, f
) != 0)
517 /* Read associated text. */
520 for ( ; c
!= '\n'; i
++, c
= getc(f
)) {
522 return prematureeof();
523 if (i
>= stringlen
) {
524 stringlen
= stringlen
* 2 + 16;
525 string
= xrealloc(string
, stringlen
);
531 switch (string
[i
- 1]) {
536 while (isspace(c
= getc(f
)) && c
!= '\n') ;
542 if (i
>= stringlen
) {
543 stringlen
= stringlen
* 2 + 16;
544 string
= xrealloc(string
, stringlen
);
548 /* Parse the line just read. */
549 if (function
[0] == ':') {
550 if (parsecontrol(function
+ 1, string
) != 0)
553 if (parsestring(fp
, string
) != 0)
559 return outputfunctions();
563 /* A function in the description file. nbits and nargs are -1 until the
564 real values are known. */
566 struct function
*next
;
569 int nbits
; /* Number of bits in the bitpattern, 0 if none. */
570 int nargs
; /* Number of (x,y,...) parameters, 0 if none. */
571 char isarray
; /* Will be represented by a C array. */
572 int fixedlength
; /* If a C array, will be a char [][N] not a char *[]. */
573 struct entry
*first
, *last
;
574 /* Links to the value(s) supplied. */
575 struct arg
*args
; /* List of (x,y,...) names and types. */
577 struct function
*functions
;
580 /* Find the function with the given name. If not found, create a structure
581 for it, fill it out with a template, and return that. */
582 struct function
*findfunction(char *name
) {
585 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
586 if (strcmp(fp
->name
, name
) == 0)
589 if (strlen(name
) > maxfunctionname
)
590 maxfunctionname
= strlen(name
);
591 fp
= xmalloc(sizeof *fp
);
592 fp
->next
= functions
;
594 fp
->name
= xstrdup(name
);
595 fp
->type
= T_UNKNOWN
;
596 fp
->nbits
= fp
->nargs
= -1; /* nbits will be set correctly later. */
598 fp
->first
= fp
->last
= NULL
;
603 /* Parse an external (C) function declaration. This will look something like:
605 We're called just after seeing the ':'.
606 Return 0 if parsing is successful, 1 otherwise. */
607 int parseextern(struct function
*fp
, FILE *f
) {
610 if ((c
= getc(f
)) != '\n') {
612 "%s: %s(%d): extern declaration should be a lone `:'\n",
613 progname
, filename
, lineno
);
616 if (fp
->nbits
!= 0) {
618 "%s: %s(%d): extern functions should not have bitstrings\n",
619 progname
, filename
, lineno
);
623 fp
->first
= fp
->last
= NULL
;
628 /* A value supplied for a function (the third field in a description line).
629 In general there can be any number of such values, differing in the
630 bitpattern supplied. The mask and value fields describe the constant
631 bits in the bitpattern: mask indicates which bits they are and value
632 indicates the values of those bits. So this entry matches
633 ((x & mask) == value). */
637 struct bits
*bits
; /* List of named bitfields. */
638 struct string
*string
; /* Value of function when bitpattern matched. */
639 char done
; /* This entry has already been compiled. */
643 /* We've just seen a definition of function "name". Make a structure for it
644 if necessary, and a template entry that will describe the value given here.
646 struct function
*makefunction(char *name
) {
648 struct entry
*ep
= xmalloc(sizeof *ep
);
651 if (name
[0] == '%') {
656 fp
= findfunction(name
);
657 if (fp
->type
== T_UNKNOWN
)
659 else if (fp
->type
!= type
) {
660 fprintf(stderr
, "%s: %s(%d): function %s previously declared as %s, "
661 "here as %s\n", progname
, filename
, lineno
, name
,
662 typename
[fp
->type
], typename
[type
]);
668 if (fp
->first
!= NULL
)
677 /* A named bitfield within the bitpattern of a function entry, or within a
678 $[...] bitsplice. The mask covers the bitfield and the shift says how
679 many 0 bits there are after the last 1 in the mask. */
688 /* Parse the bitstring supplied for the given function. nbits says how many
689 bits there are; it can legitimately be 0. Return value is 0 on success. */
690 int parsebits(struct function
*fp
, char *bitstring
, int nbits
) {
693 else if (fp
->nbits
!= nbits
) {
694 fprintf(stderr
, "%s: %s(%d): bit string of length %d;\n",
695 progname
, filename
, lineno
, nbits
);
696 fprintf(stderr
, " function %s has bit strings of length %d\n",
697 fp
->name
, fp
->nbits
);
700 return parseentrybits(fp
->last
, bitstring
, nbits
, 0);
704 /* Parse a bitstring that is the pattern for a function entry or that is in a
705 $[...] bitsplice. Put the result in ep. Return value is 0 on success. */
706 int parseentrybits(struct entry
*ep
, char *bitstring
, int nbits
, int issplice
) {
709 bits mask
, value
, entrymask
;
713 for (i
= 0; i
< nbits
; i
++) {
714 bit
= bitstring
[nbits
- 1 - i
];
724 fprintf(stderr
, "%s: %s(%d): invalid character in bitstring: %c\n",
725 progname
, filename
, lineno
, bit
);
729 for (bp
= ep
->bits
; bp
!= NULL
; bp
= bp
->next
) {
730 if (bp
->name
== bit
) {
732 "%s: %s(%d): bitstring name %c used twice\n",
733 progname
, filename
, lineno
, bit
);
739 for (j
= i
+ 1; j
< nbits
&& bitstring
[nbits
- 1 - j
] == bit
; j
++)
741 bp
= xmalloc(sizeof *bp
);
743 bp
->mask
= entrymask
;
755 /* Parse a control line. This looks something like:
756 :bitstype unsigned int
757 in which case we will be called with name "bitstype" and
758 value "unsigned int". */
759 int parsecontrol(char *name
, char *value
) {
760 if (strcmp(name
, "bitstype") == 0)
761 bitstype
= xstrdup(value
);
763 fprintf(stderr
, "%s: %s(%d): unrecognised control keyword %s\n",
764 progname
, filename
, lineno
, name
);
771 /* A parameter to a function, e.g., x in:
772 %f aaa(%x) $a + $x */
780 /* Parse the parameters (x,y,...) to a function and put the result in fp.
781 The entry that is being built is fp->last. cp points to the opening
782 (; if it does not point to a ( then there are no parameters. If
783 this is the first entry for the function, fp->nargs will be -1 and
784 we will build up an argument list. Otherwise, fp->nargs will be
785 >= 0 and we will only check that the arguments here are consistent
786 with what went before. Return value is 0 on success. */
787 int parseargs(struct function
*fp
, FILE *f
, int *cp
) {
788 struct arg
**arglink
, *ap
;
803 if (fp
->nargs
>= 0 && nargs
> fp
->nargs
) {
805 "%s: %s(%d): %d arg(s) instead of %d for %s\n",
806 progname
, filename
, lineno
, nargs
, fp
->nargs
,
817 if (!isalpha(name
)) {
819 "%s: %s(%d): argument should be letter: %c\n",
820 progname
, filename
, lineno
, name
);
823 for (bp
= fp
->last
->bits
; bp
!= NULL
; bp
= bp
->next
) {
824 if (bp
->name
== name
) {
826 "%s: %s(%d): %c is a bitstring and an arg\n",
827 progname
, filename
, lineno
, name
);
831 if (fp
->nargs
>= 0) {
832 if ((*arglink
)->name
!= name
) {
834 "%s: %s(%d): arg %d of %s is %c not %c\n",
835 progname
, filename
, lineno
, nargs
, fp
->name
,
836 (*arglink
)->name
, name
);
839 if ((*arglink
)->type
!= t
) {
841 "%s: %s(%d): arg %c of %s: inconsistent type\n",
842 progname
, filename
, lineno
, name
, fp
->name
);
846 for (ap
= fp
->args
; ap
!= *arglink
; ap
= ap
->next
) {
847 if (ap
->name
== name
) {
849 "%s: %s(%d): argument name %c used twice\n",
850 progname
, filename
, lineno
, name
);
854 *arglink
= xmalloc(sizeof **arglink
);
855 (*arglink
)->name
= name
;
856 (*arglink
)->type
= t
;
858 arglink
= &(*arglink
)->next
;
864 "%s: %s(%d): bad character in argument list: %c\n"
865 " (arguments must be single letters)\n",
866 progname
, filename
, lineno
, *cp
);
877 if (width
> maxargwidth
)
879 } else if (fp
->nargs
!= nargs
) {
880 fprintf(stderr
, "%s: %s(%d): argument list of length %d;\n",
881 progname
, filename
, lineno
, nargs
);
882 fprintf(stderr
, " function %s has argument lists of length %d\n",
883 fp
->name
, fp
->nargs
);
891 /* Parse the string describing the value of this entry for our
892 function. Return 0 on success. */
893 int parsestring(struct function
*fp
, char *str
) {
896 t
= makestring(fp
, &fp
->last
->string
, &str
, NULL
, fp
->type
);
899 if (fp
->type
!= t
&& t
!= T_UNKNOWN
) {
900 fprintf(stderr
, "%s: %s(%d): function %s has inconsistent types\n",
901 progname
, filename
, lineno
, fp
->name
);
908 /* A parsed representation of the whole string describing a value of a
909 function, or certain strings within that (e.g., array indices). This is a
910 linked list of substrings whose type is given by the type field. */
914 S_TEXT
, S_BITSTRING
, S_BITSPLICE
, S_PARAMETER
, S_FUNCTIONCALL
, S_ARRAY
916 union value
{ /* The fields here correspond to the enum values. */
917 char *text
; /* plain text */
918 struct bits
*bits
; /* $x where x is a bitfield */
919 struct bitsplice
*bitsplice
; /* $[...] */
920 struct arg
*parameter
; /* $x where x is a parameter */
921 struct functioncall
*functioncall
; /* $func(...) */
922 struct array
*array
; /* {...}[...] */
926 /* The representation of a function call $func(...) in the description of a
928 struct functioncall
{
929 struct function
*function
;
930 struct stringlist
*args
;
933 /* The representation of an array selection {...|...}[...] in the description
934 of a function value. tempno is used when constructing a C variable name
935 that will contain the strings or numbers in an array. */
937 struct string
*index
; /* what's between [...] */
938 struct stringlist
*elements
; /* what's between {...} */
939 enum type type
; /* the type of each element */
943 /* A list of strings, being the list of arguments in a function call or the
944 list of elements of an array. This is a linked list of linked lists. */
946 struct stringlist
*next
;
948 struct string
*string
;
952 /* The following are the only characters with special meaning at the top level
953 of parsing of a function value. When parsing arrays or function calls,
954 other characters become special. */
955 #define MAKESTRING_MAGIC "${"/*}*/
958 /* Parse a function return-value string or substring and make a struct string
959 list for it. The string starts at *stringp and ends at a \0 or at any
960 character in the `magic' string other than { or $. *stringp is updated
961 to point to the terminating character. The parsed representation is put
962 at *stringlink. `fp' is the function whose return value is being parsed.
963 `targettype' is the expected type of the result, if known.
964 The return value is the actual type. */
965 enum type
makestring(struct function
*fp
, struct string
**stringlink
,
966 char **stringp
, char *magic
, enum type targettype
) {
968 struct string
*sp
, **firststringlink
;
971 enum type t
= targettype
, newt
;
974 magic
= MAKESTRING_MAGIC
;
976 firststringlink
= stringlink
;
979 sp
= xmalloc(sizeof *sp
);
983 if (strchr(magic
, *q
) != NULL
) {
984 if (*q
!= ')' || parenlevel
== 0)
998 } while (*++q
!= '\0');
1001 sp
->value
.text
= q
= xmalloc(n
+ 1);
1009 } else if (*p
== '$') {
1010 if (parsedollar(fp
, &p
, sp
) != 0)
1018 newt
= sp
->value
.parameter
->type
;
1020 case S_FUNCTIONCALL
:
1021 newt
= sp
->value
.functioncall
->function
->type
;
1024 fprintf(stderr
, "makestring type %d\n", sp
->type
);
1027 } else if (*p
== '{'/*}*/) {
1028 if (parsearray(fp
, &p
, sp
, t
) != 0)
1030 newt
= sp
->value
.array
->type
;
1037 else if (newt
!= T_UNKNOWN
&& t
!= newt
) {
1038 if (stringlink
== firststringlink
) {
1039 fprintf(stderr
, "%s: %s(%d): expected %s type:\n", progname
,
1040 filename
, lineno
, typename
[t
]);
1041 showstringelement(stderr
, sp
);
1045 fprintf(stderr
, "%s: %s(%d): mixed types in string:\n",
1046 progname
, filename
, lineno
);
1047 showstring(stderr
, *firststringlink
);
1048 fprintf(stderr
, " -- %s\n", typename
[t
]);
1049 showstringelement(stderr
, sp
);
1050 fprintf(stderr
, " -- %s\n", typename
[newt
]);
1054 stringlink
= &sp
->next
;
1059 if (components
>= MAXBITS
) {
1060 fprintf(stderr
, "%s: %s(%d): excessively complicated string\n",
1061 progname
, filename
, lineno
);
1064 componentbits
|= 1 << components
;
1069 /* Parse a $ operation at **stringp and update *stringp to point past it.
1070 `fp' is the function whose return value is being parsed. The parsed
1071 item will be put at *sp. Return 0 on success, nonzero on error. */
1072 int parsedollar(struct function
*fp
, char **stringp
, struct string
*sp
) {
1080 while (isalnum(*p
) || *p
== '_')
1082 if (*start
== '[') {
1084 fprintf(stderr
, "%s: %s(%d): missing ] or bad character in $[\n",
1085 progname
, filename
, lineno
);
1089 return parsebitsplice(fp
, start
+ 1, p
- start
- 1, sp
);
1092 fprintf(stderr
, "%s: %s(%d): missing identifier after $\n", progname
,
1096 if (p
== start
+ 1) {
1097 if (findvariable(fp
, *start
, sp
) != 0)
1100 if (parsefunctioncall(fp
, start
, &p
, sp
) != 0)
1108 /* The representation of a $[...] bitsplice. It is parsed into a
1109 struct entry just as if it were a bitfield parameter, then analysed
1110 into a chain of struct bitsplicebits. These in conjunction with
1111 the constant portion of the struct entry will allow the bitsplice to
1112 be compiled. Each bitsplicebits element represents either a numeric
1113 argument to the current function, in which case it will be shifted
1114 into place; or a bitfield name from the bitfield description of the
1115 current function, in which case it will be shifted by the difference
1116 between the position of the bitfield in the argument and the position
1117 it occurs in the bitsplice. `shift' indicates how much to shift left
1118 the associated value; if it is negative the value is shifted right.
1119 For instance, in a function like this:
1120 %oh xx00(%y) $[yyxx]
1121 the bitsplicebits for y will have shift = 2 and value.arg pointing to y,
1122 and those for x will have shift = -2 and value.mask = binary 1100.
1123 As an optimisation, contiguous bitfields that are also contiguous in the
1124 bitsplice will be combined. For instance:
1125 %oh xxyy00 $[0xxyy0]
1126 will compile the same code as:
1127 %oh zzzz00 $[0zzzz0].
1128 As another optimisation, a bitfield that occupies the entire bitstring
1129 for a function will be treated like a parameter in that it will not be
1130 masked in the bitsplice. For instance:
1131 %oh xxxxxx $[0xxxxxx0]
1132 will compile the same code as:
1133 %oh (%x) $[0xxxxxx0]. */
1137 struct bitsplicebits
*splice
;
1139 struct bitsplicebits
{
1140 struct bitsplicebits
*next
;
1142 enum elementtype type
;
1150 int parsebitsplice(struct function
*fp
, char *bitstring
, int nbits
,
1151 struct string
*sp
) {
1152 struct bitsplice
*splicep
;
1153 struct bitsplicebits
*bsp
, *lastbsp
, **bspp
;
1155 int shift
, nfrombits
, ntobits
;
1158 splicep
= xmalloc(sizeof *splicep
);
1159 splicep
->nbits
= nbits
;
1160 if (parseentrybits(&splicep
->entry
, bitstring
, nbits
, 1) != 0)
1162 bspp
= &splicep
->splice
;
1164 for (bp
= splicep
->entry
.bits
; bp
!= NULL
; bp
= bp
->next
) {
1165 if (findvariable(fp
, bp
->name
, sp
) != 0)
1168 if (sp
->type
== S_BITSTRING
) {
1169 nfrombits
= bitcount(sp
->value
.bits
->mask
);
1170 ntobits
= bitcount(bp
->mask
);
1172 if (nfrombits
!= ntobits
) {
1173 fprintf(stderr
, "%s: %s(%d): warning: "
1174 "bitstring $%c %ser than its place "
1176 progname
, filename
, lineno
, bp
->name
,
1177 (nfrombits
> ntobits
) ? "bigg" : "small");
1180 shift
-= sp
->value
.bits
->shift
;
1182 /* See if this bitfield can be combined with a previous contiguous
1184 if (lastbsp
!= NULL
&& lastbsp
->type
== S_BITSTRING
1185 && lastbsp
->shift
== shift
) {
1186 lastbsp
->value
.mask
|= sp
->value
.bits
->mask
;
1190 assert(sp
->type
== S_PARAMETER
);
1191 if (sp
->value
.parameter
->type
!= T_INTEGER
) {
1193 "%s: %s(%d): variable %c in $[...] should be integer\n",
1194 progname
, filename
, lineno
, sp
->value
.parameter
->name
);
1198 *bspp
= bsp
= xmalloc(sizeof *bsp
);
1199 bsp
->type
= sp
->type
;
1201 if (sp
->type
== S_PARAMETER
)
1202 bsp
->value
.arg
= sp
->value
.parameter
;
1204 bsp
->value
.mask
= sp
->value
.bits
->mask
;
1210 /* Look for a spliced element that is the entire bitstring argument to
1211 this function and therefore doesn't need to be masked. */
1212 allbits
= allbitsset(fp
->nbits
);
1213 for (bsp
= splicep
->splice
; bsp
!= NULL
; bsp
= bsp
->next
) {
1214 if (bsp
->type
== S_BITSTRING
) {
1215 for (b
= bsp
->value
.mask
; b
!= 0 && !(b
& 1); b
>>= 1) ;
1217 bsp
->value
.mask
= 0;
1220 sp
->type
= S_BITSPLICE
;
1221 sp
->value
.bitsplice
= splicep
;
1226 int findvariable(struct function
*fp
, int name
, struct string
*sp
) {
1230 for (bp
= fp
->last
->bits
; bp
!= NULL
; bp
= bp
->next
) {
1231 if (bp
->name
== name
) {
1232 sp
->type
= S_BITSTRING
;
1233 sp
->value
.bits
= bp
;
1237 for (ap
= fp
->args
; ap
!= NULL
; ap
= ap
->next
) {
1238 if (ap
->name
== name
) {
1239 sp
->type
= S_PARAMETER
;
1240 sp
->value
.parameter
= ap
;
1244 fprintf(stderr
, "%s: %s(%d): undefined parameter %c\n", progname
, filename
,
1250 int parsefunctioncall(struct function
*fp
, char *start
, char **stringp
,
1251 struct string
*sp
) {
1253 struct functioncall
*fcp
;
1254 struct stringlist
**arglink
, *arg
;
1259 fprintf(stderr
, "%s: %s(%d): missing ( after function %.*s\n", progname
,
1260 filename
, lineno
, p
- start
, start
);
1263 sp
->type
= S_FUNCTIONCALL
;
1264 sp
->value
.functioncall
= fcp
= xmalloc(sizeof *fcp
);
1265 *p
= '\0'; /* Ugly. */
1266 fcp
->function
= findfunction(start
);
1268 arglink
= &fcp
->args
;
1271 arg
= xmalloc(sizeof *arg
);
1272 t
= makestring(fp
, &arg
->string
, &p
, MAKESTRING_MAGIC
",)",
1278 arglink
= &arg
->next
;
1292 int parsearray(struct function
*fp
, char **stringp
, struct string
*sp
,
1296 struct stringlist
**elementlink
, *element
;
1299 assert(*p
== '{'/*}*/);
1301 sp
->value
.array
= ap
= xmalloc(sizeof *ap
);
1303 elementlink
= &ap
->elements
;
1305 if (*++p
!= /*{*/'}') {
1307 element
= xmalloc(sizeof *element
);
1308 t
= makestring(fp
, &element
->string
, &p
,
1309 MAKESTRING_MAGIC
/*{*/"|}", t
);
1313 if (ap
->type
== T_UNKNOWN
)
1315 else if (t
!= T_UNKNOWN
&& ap
->type
!= t
) {
1316 fprintf(stderr
, "%s: %s(%d): mixed types in array:\n",
1317 progname
, filename
, lineno
);
1318 showstring(stderr
, ap
->elements
->string
);
1319 fprintf(stderr
, " -- %s\n", typename
[ap
->type
]);
1320 showstring(stderr
, element
->string
);
1321 fprintf(stderr
, " -- %s\n", typename
[t
]);
1324 *elementlink
= element
;
1325 elementlink
= &element
->next
;
1332 *elementlink
= NULL
;
1333 assert(*p
== /*{*/'}');
1335 fprintf(stderr
, "%s: %s(%d): missing [index] after array\n",
1336 progname
, filename
, lineno
);
1340 t
= makestring(fp
, &ap
->index
, &p
, MAKESTRING_MAGIC
"]", T_INTEGER
);
1343 if (t
== T_STRING
) {
1344 fprintf(stderr
, "%s: %s(%d): array index cannot be string:\n",
1345 progname
, filename
, lineno
);
1346 showstring(stderr
, ap
->index
);
1350 fprintf(stderr
, "%s: %s(%d): [ without ]\n", progname
, filename
,
1359 void dumpfunctions() {
1360 struct function
*fp
;
1362 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
)
1367 void dumpfunction(struct function
*fp
) {
1370 for (ep
= fp
->first
; ep
!= NULL
; ep
= ep
->next
)
1371 showentry(stderr
, fp
, ep
, 0);
1375 /* Entries are not shown exactly as they would be input, since \ would
1376 need to be provided before some characters such as $ or {. But the
1377 characters "|},]" pose a problem since a \ is only needed in certain
1378 contexts and is annoying otherwise. It's not worth doing this right,
1379 since it's only used for error messages. */
1380 void showentry(FILE *f
, struct function
*fp
, struct entry
*ep
, bits highlight
) {
1381 if (fp
->type
== T_INTEGER
)
1383 fprintf(f
, "%-*s ", maxfunctionname
+ 1, fp
->name
);
1384 if (fp
->nbits
== 0 && fp
->nargs
== 0)
1385 fprintf(f
, "%-*s", maxargwidth
, "()");
1387 showbits(f
, ep
, fp
->nbits
, 0);
1388 showargs(f
, fp
->args
, maxargwidth
- fp
->nbits
);
1391 showstring(f
, ep
->string
);
1393 if (highlight
!= 0) {
1394 fprintf(f
, "%-*s ", maxfunctionname
+ 1, "");
1395 showbits(f
, ep
, fp
->nbits
, highlight
);
1401 void showbits(FILE *f
, struct entry
*ep
, int nbits
, bits highlight
) {
1408 i
= 1 << (nbits
- 1);
1420 if (highlight
!= 0 || (ep
->mask
& i
)) {
1421 putc((value
& i
) ? one
: zero
, f
);
1424 assert(bp
!= NULL
&& (bp
->mask
& i
));
1428 } while (bp
->mask
& i
);
1435 void showargs(FILE *f
, struct arg
*ap
, int fieldwidth
) {
1446 isint
= (ap
->type
== T_INTEGER
);
1447 fprintf(f
, "%c%s%c", lastc
, isint
? "%" : "", ap
->name
);
1451 } while (ap
!= NULL
);
1454 fprintf(f
, "%-*s", fieldwidth
- width
, "");
1458 void showstring(FILE *f
, struct string
*sp
) {
1459 for ( ; sp
!= NULL
; sp
= sp
->next
)
1460 showstringelement(f
, sp
);
1464 void showstringelement(FILE *f
, struct string
*sp
) {
1465 struct bitsplice
*bsp
;
1469 fputs(sp
->value
.text
, f
);
1472 fprintf(f
, "$%c", sp
->value
.bits
->name
);
1476 bsp
= sp
->value
.bitsplice
;
1477 showbits(f
, &bsp
->entry
, bsp
->nbits
, 0);
1481 fprintf(f
, "$%c", sp
->value
.parameter
->name
);
1483 case S_FUNCTIONCALL
:
1484 showfunctioncall(f
, sp
->value
.functioncall
);
1487 showarray(f
, sp
->value
.array
);
1490 fprintf(stderr
, "showstring case %d\n", sp
->type
);
1496 void showfunctioncall(FILE *f
, struct functioncall
*fcp
) {
1497 struct stringlist
*sp
;
1500 fprintf(f
, "$%s(", fcp
->function
->name
);
1502 for (sp
= fcp
->args
; sp
!= NULL
; sp
= sp
->next
) {
1505 showstring(f
, sp
->string
);
1511 void showarray(FILE *f
, struct array
*ap
) {
1512 struct stringlist
*sp
;
1517 for (sp
= ap
->elements
; sp
!= NULL
; sp
= sp
->next
) {
1520 showstring(f
, sp
->string
);
1522 fputs(/*{*/"}[", f
);
1523 showstring(f
, ap
->index
);
1528 const char commonpreamble
[] = "\
1533 const char concatpreamble
[] = "\
1534 static char *dis_buf;\n\
1535 static int dis_bufindex, dis_buflen;\n\
1537 void *dis_alloc(size_t size)\n\
1540 int newindex = dis_bufindex + size;\n\
1541 if (newindex > dis_buflen) {\n\
1542 dis_buflen = newindex * 4;\n\
1543 dis_buf = malloc(dis_buflen);\n\
1544 /* We can't use realloc because there might be pointers extant into\n\
1545 the old buffer. So we waste the memory of the old buffer. We\n\
1546 should soon reach an adequate buffer size and stop leaking. */\n\
1547 if (dis_buf == 0) {\n\
1548 perror(\"malloc\");\n\
1551 dis_bufindex = 0;\n\
1553 p = dis_buf + dis_bufindex;\n\
1554 dis_bufindex = newindex;\n\
1560 dis_bufindex = 0;\n\
1565 const char concatdeclarations
[] = "\
1566 #include <string.h>\n\
1567 #include <stdlib.h>\n\
1568 #include <errno.h>\n\
1570 extern void *dis_realloc(void *p, size_t size); /* User-provided. */\n\
1571 void *dis_alloc(size_t size);\n\
1572 void dis_done(void);\n\
1575 const char nonconcatpreamble
[] = "\
1576 void dis_done() {}\n\
1580 int outputfunctions() {
1581 struct function
*fp
;
1583 outputidentity(stdout
);
1584 if (headerfilename
!= NULL
) {
1585 if ((headerfile
= fopen(headerfilename
, "w")) == NULL
) {
1586 fprintf(stderr
, "%s: create %s: %s\n", progname
, headerfilename
,
1590 outputidentity(headerfile
);
1591 fprintf(headerfile
, commonpreamble
, bitstype
);
1592 printf("\n#include \"%s\"\n", headerfilename
);
1594 printf(commonpreamble
, bitstype
);
1596 if (outputdeclarations() != 0)
1599 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
1603 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
1604 if (fp
->first
!= NULL
&& !fp
->isarray
) {
1605 if (outputfunction(fp
) != 0)
1613 void outputidentity(FILE *f
) {
1616 fprintf(f
, "/*\n * This file was generated by:\n *");
1617 for (p
= global_argv
; *p
!= NULL
; p
++)
1618 fprintf(f
, " %s", *p
);
1619 fprintf(f
, "\n */\n\n");
1623 int outputdeclarations() {
1624 FILE *f
= headerfile
? headerfile
: stdout
;
1625 struct function
*fp
;
1627 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
1628 if (fp
->type
!= T_UNKNOWN
) {
1630 fprintf(f
, "extern ");
1631 if (fp
->fixedlength
> 0)
1632 fprintf(f
, "char %s[][%d]", fp
->name
, fp
->fixedlength
);
1634 compiletype(f
, &fp
->type
);
1635 fprintf(f
, "%s[]", fp
->name
);
1638 functionheader(f
, fp
);
1646 void outputconcats() {
1649 if (componentbits
& ~3) {
1650 fputs(concatdeclarations
, headerfile
? headerfile
: stdout
);
1651 fputs(concatpreamble
, stdout
);
1653 fputs(nonconcatpreamble
, stdout
);
1654 for (i
= 2; i
< MAXBITS
; i
++) {
1655 if (componentbits
& (1 << i
))
1661 void outputconcat(int n
) {
1667 outputconcatheader(headerfile
, n
);
1668 fprintf(headerfile
, ";\n");
1670 outputconcatheader(stdout
, n
);
1671 printf("\n{\n void *p;\n int len = ");
1673 for (i
= 0; i
< n
; i
++) {
1674 printf("%sstrlen(p%d)", last
, i
);
1677 printf(";\n p = dis_alloc(len + 1);\n return ");
1678 for (i
= 1; i
< n
; i
++)
1680 printf("strcpy(p, p0)");
1681 for (i
= 1; i
< n
; i
++)
1682 printf(", p%d)", i
);
1687 void outputconcatheader(FILE *f
, int n
) {
1691 fprintf(f
, "char *dis_concat%d(", n
);
1692 for (i
= 0; i
< n
; i
++) {
1693 fprintf(f
, "%schar *p%d", last
, i
);
1701 struct function
*fp
;
1703 struct string
*estr
, *indexstr
;
1706 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
1707 if (fp
->nbits
> 0 && fp
->nargs
> 0)
1712 if (ep
== NULL
|| ep
->next
!= NULL
)
1715 if (estr
== NULL
|| estr
->next
!= NULL
|| estr
->type
!= S_ARRAY
)
1717 indexstr
= estr
->value
.array
->index
;
1718 if (indexstr
->next
!= NULL
)
1720 if (fp
->nbits
> 0) {
1722 if (bp
== NULL
|| bp
->next
!= NULL
|| bp
->shift
!= 0)
1724 if (bp
->mask
!= allbitsset(fp
->nbits
))
1726 if (indexstr
->type
!= S_BITSTRING
|| indexstr
->value
.bits
!= bp
)
1729 if (indexstr
->type
!= S_PARAMETER
1730 || indexstr
->value
.parameter
!= fp
->args
)
1733 if (!simplearray(estr
->value
.array
))
1737 (fp
->type
== T_INTEGER
) ? 0 : checkfixedlength(estr
->value
.array
);
1742 int checkfixedlength(struct array
*ap
) {
1743 int len
, maxlen
, wasted
, n
;
1744 struct stringlist
*lp
;
1747 for (lp
= ap
->elements
; lp
!= NULL
; lp
= lp
->next
) {
1748 if (lp
->string
== NULL
)
1750 assert(lp
->string
->type
== S_TEXT
);
1751 len
= strlen(lp
->string
->value
.text
);
1755 for (wasted
= n
= 0, lp
= ap
->elements
; lp
!= NULL
; n
++, lp
= lp
->next
) {
1756 if (lp
->string
== NULL
)
1758 wasted
+= maxlen
- strlen(lp
->string
->value
.text
);
1760 if (wasted
< n
* sizeof(char *)) /* Should be target's sizeof. */
1766 int outputfunction(struct function
*fp
) {
1768 functionheader(stdout
, fp
);
1769 printf("\n{\n"/*}*/);
1770 switch (functionswitch(fp
, 0, 0)) {
1775 fprintf(stderr
, "%s: warning: not all cases of %s covered\n",
1776 progname
, fp
->name
);
1784 void functionarray(struct function
*fp
) {
1787 ap
= fp
->first
->string
->value
.array
;
1789 compilesimplearray(&fp
->type
, fp
->name
, 0, ap
);
1793 void functionheader(FILE *f
, struct function
*fp
) {
1797 compiletype(f
, &fp
->type
);
1798 fprintf(f
, "%s(", fp
->name
);
1800 if (fp
->nbits
> 0) {
1801 fprintf(f
, "bits code");
1804 for (ap
= fp
->args
; ap
!= NULL
; ap
= ap
->next
) {
1806 compiletype(f
, &ap
->type
);
1816 int simplearray(struct array
*ap
) {
1817 struct stringlist
*lp
;
1819 for (lp
= ap
->elements
; lp
!= NULL
; lp
= lp
->next
) {
1820 if (lp
->string
!= NULL
1821 && (lp
->string
->next
!= NULL
|| lp
->string
->type
!= S_TEXT
))
1824 return (lp
== NULL
);
1828 void compiletype(FILE *f
, enum type
*tp
) {
1834 fprintf(f
, "char *");
1837 fprintf(f
, "bits ");
1840 fprintf(stderr
, "compiletype type %d\n", *tp
);
1846 /* Generate code for entries in function fp whose bitstring b satisfies
1847 the constraint (b & mask) == value. Return 1 if generated switch
1848 always does `return', 0 if not, -1 on error.
1849 The algorithm is as follows. Scan the eligible entries to find the
1850 largest set of bits not in the passed-in mask which always have a
1851 constant value (are not variable). One `default' entry is allowed
1852 all of whose bits are variable. For each value of the constant bits,
1853 generate a `switch' case and invoke the function recursively with
1854 that value included in the constraint parameters. The recursion
1855 stops when no set of constant bits is found, perhaps because the
1856 mask parameter has all bits set.
1857 This algorithm could be improved. Currently it will fail if there
1858 are input lines "xxyy", "00xx" and "yy00", each of which is default with
1859 respect to the others. The correct behaviour would then be to select
1860 a bit that is sometimes constant and deal with those cases first.
1861 But this problem has not yet arisen in real life. */
1862 int functionswitch(struct function
*fp
, bits mask
, bits value
) {
1863 struct entry
*ep
, *defaultcase
;
1864 bits allbits
, constbits
, missingcases
;
1865 int nhits
, ncases
, nconstbits
, alwaysreturns
;
1868 allbits
= allbitsset(fp
->nbits
);
1869 constbits
= allbits
& ~mask
;
1873 "functionswitch(%s): (x & 0x%lx) == 0x%lx; const == 0x%lx\n",
1874 fp
->name
, mask
, value
, constbits
);
1879 for (ep
= fp
->first
; ep
!= NULL
; ep
= ep
->next
) {
1880 /* If this is not one of the entries under consideration, skip. */
1882 || (ep
->mask
& mask
) != mask
|| (ep
->value
& mask
) != value
)
1886 showentry(stderr
, fp
, ep
, 0);
1888 /* If this entry has no constant bits in the still-variable portion,
1889 it's the default. */
1890 if ((constbits
& ep
->mask
) == 0) {
1891 if (defaultcase
!= NULL
) {
1893 "%s: function %s: unable to distinguish between:\n",
1894 progname
, fp
->name
);
1895 showentry(stderr
, fp
, defaultcase
, 0);
1896 showentry(stderr
, fp
, ep
, 0);
1902 fprintf(stderr
, "^^ default case\n");
1905 if (debug
&& (constbits
& ~ep
->mask
)) {
1907 fprintf(stderr
, "const now 0x%lx\n", constbits
& ep
->mask
);
1909 constbits
&= ep
->mask
;
1915 if (constbits
== allbits
)
1916 printf("switch (code) {\n"/*}*/);
1918 printf("switch (code & 0x%lx) {\n"/*}*/, constbits
);
1919 for (ep
= fp
->first
; ep
!= NULL
; ep
= ep
->next
) {
1920 /* If this is not one of the entries under consideration, skip. */
1921 if ((ep
->mask
& mask
) != mask
|| (ep
->value
& mask
) != value
)
1923 if (ep
->done
|| ep
== defaultcase
)
1927 printf("case 0x%lx:\n", ep
->value
& constbits
);
1928 switch (functionswitch(fp
, mask
| constbits
,
1929 value
| (ep
->value
& constbits
))) {
1934 indentation
++; indent(); indentation
--;
1941 nconstbits
= bitcount(constbits
);
1942 missingcases
= ((nconstbits
== MAXBITS
) ? 0 : 1 << nconstbits
) - ncases
;
1943 if (alwaysreturns
) {
1944 switch (missingcases
) {
1946 if (defaultcase
!= NULL
) {
1947 fprintf(stderr
, "%s: warning: redundant entry:\n", progname
);
1948 showentry(stderr
, fp
, defaultcase
, 0);
1953 if (defaultcase
!= NULL
&& nconstbits
!= 0) {
1955 "%s: warning: variable bit(s) could be constant:\n",
1957 showentry(stderr
, fp
, defaultcase
, constbits
);
1965 if (defaultcase
!= NULL
) {
1966 /* If defaultcase has some constant bits of its own, recursion will
1967 check that they have the required value. */
1968 if ((defaultcase
->mask
& ~mask
) == 0) {
1970 if (compilestring(-1, defaultcase
->string
, fp
->type
) != 0)
1972 defaultcase
->done
= 1;
1975 alwaysreturns
= functionswitch(fp
, mask
, value
);
1980 return alwaysreturns
;
1984 int compilestring(int assignto
, struct string
*sp
, enum type type
) {
1987 tempno
= walkstring(sp
, COUNTARRAYS
, assignto
);
1988 if (tempno
> assignto
) {
1992 (void) walkstring(sp
, DECLAREARRAYS
, assignto
);
1993 if (walkstring(sp
, COMPILEARRAYS
, assignto
) < 0)
1996 if (compilecheckedstring(assignto
, sp
, type
) != 0)
1998 if (tempno
> assignto
) {
2007 int compilecheckedstring(int assignto
, struct string
*sp
, enum type type
) {
2008 compileassign(assignto
);
2009 if (compileconcat(sp
, type
) != 0)
2016 void compileassign(int assignto
) {
2021 compiletemp(assignto
);
2027 void compiletemp(int tempno
) {
2028 printf("t__%d", tempno
);
2032 void compiletext(char *s
) {
2035 for ( ; *s
!= '\0'; s
++) {
2048 int compileconcat(struct string
*sp
, enum type type
) {
2054 return compilenull(type
);
2055 if (sp
->next
== NULL
)
2056 return compilesimple(sp
, type
);
2057 if (type
!= T_INTEGER
) {
2058 for (elements
= 0, sp1
= sp
; sp1
!= NULL
; elements
++, sp1
= sp1
->next
) ;
2059 printf("dis_concat%d(", elements
);
2062 for (sp1
= sp
; sp1
!= NULL
; sp1
= sp1
->next
) {
2064 if (type
!= T_INTEGER
)
2066 if (sp1
->type
== S_ARRAY
)
2067 compilearrayref(sp1
->value
.array
);
2069 if (compilesimple(sp1
, type
) != 0)
2072 if (type
!= T_INTEGER
)
2078 int compilenull(enum type type
) {
2079 if (type
== T_INTEGER
) {
2080 fprintf(stderr
, "%s: empty integer expression\n", progname
);
2088 int compilesimple(struct string
*sp
, enum type type
) {
2090 return compilenull(type
);
2093 if (type
== T_INTEGER
)
2094 printf("%s", sp
->value
.text
);
2096 compiletext(sp
->value
.text
);
2099 compilebitstring(sp
->value
.bits
);
2102 compilebitsplice(sp
->value
.bitsplice
);
2105 putchar(sp
->value
.parameter
->name
);
2107 case S_FUNCTIONCALL
:
2108 return compilefunctioncall(sp
);
2110 if (compilearrayref(sp
->value
.array
) != 0)
2114 fprintf(stderr
, "compilesimple case %d", sp
->type
);
2121 int compilearrayref(struct array
*ap
) {
2122 compiletemp(ap
->tempno
);
2123 if (simplearray(ap
)) {
2125 if (compileconcat(ap
->index
, T_INTEGER
) != 0)
2133 int compilefunctioncall(struct string
*sp
) {
2134 struct function
*fp
;
2135 struct stringlist
*actualp
;
2136 struct arg
*formalp
;
2139 enum type formaltype
;
2141 assert(sp
->type
== S_FUNCTIONCALL
);
2142 fp
= sp
->value
.functioncall
->function
;
2143 printf("%s%c", fp
->name
, fp
->isarray
? '[' : '(');
2147 actualp
= sp
->value
.functioncall
->args
;
2148 while (actualp
!= NULL
) {
2151 formaltype
= T_INTEGER
;
2153 if (formalp
== NULL
) {
2154 fprintf(stderr
, "%s: too many arguments to %s:\n", progname
,
2156 showstring(stderr
, sp
);
2160 formaltype
= formalp
->type
;
2161 formalp
= formalp
->next
;
2163 if (actualp
->type
!= T_UNKNOWN
&& actualp
->type
!= formaltype
) {
2164 fprintf(stderr
, "%s: argument to %s has the wrong type:\n",
2165 progname
, fp
->name
);
2166 showstring(stderr
, actualp
->string
);
2172 if (compileconcat(actualp
->string
, formaltype
) != 0)
2174 actualp
= actualp
->next
;
2176 putchar(fp
->isarray
? ']' : ')');
2181 int walkstring(struct string
*sp
, enum walkstringop op
, int tempno
) {
2182 struct stringlist
*lp
;
2185 for ( ; sp
!= NULL
; sp
= sp
->next
) {
2188 ap
= sp
->value
.array
;
2189 for (lp
= ap
->elements
; lp
!= NULL
; lp
= lp
->next
)
2190 tempno
= walkstring(lp
->string
, op
, tempno
);
2191 tempno
= walkstring(ap
->index
, op
, tempno
);
2192 ap
->tempno
= ++tempno
;
2195 if (simplearray(ap
)) {
2198 compilesimplearray(&ap
->type
, NULL
, tempno
, ap
);
2203 if (!simplearray(ap
))
2204 if (compilearray(ap
) != 0)
2211 case S_FUNCTIONCALL
:
2212 for (lp
= sp
->value
.functioncall
->args
; lp
!= NULL
; lp
= lp
->next
)
2213 tempno
= walkstring(lp
->string
, op
, tempno
);
2223 int compilearray(struct array
*ap
) {
2224 struct stringlist
*ep
;
2229 if (compileconcat(ap
->index
, T_INTEGER
) != 0)
2231 printf(") {\n"/*}*/);
2232 for (i
= 0, ep
= ap
->elements
; ep
!= NULL
; i
++, ep
= ep
->next
) {
2234 printf("case %d:\n", i
);
2236 if (compilecheckedstring(ap
->tempno
, ep
->string
, ap
->type
) != 0)
2248 void compilesimplearray(enum type
*tp
, char *name
, int num
, struct array
*ap
) {
2249 struct stringlist
*lp
;
2252 fixedlength
= (*tp
== T_INTEGER
) ? 0 : checkfixedlength(ap
);
2253 if (fixedlength
> 0)
2256 compiletype(stdout
, tp
);
2262 if (fixedlength
> 0)
2263 printf("[%d]", fixedlength
);
2264 printf(" = {\n"/*}*/);
2266 for (lp
= ap
->elements
; lp
!= NULL
; lp
= lp
->next
) {
2268 compilesimple(lp
->string
, lp
->type
);
2273 printf(/*{*/"};\n");
2277 void declarearray(struct array
*ap
) {
2279 compiletype(stdout
, &ap
->type
);
2280 compiletemp(ap
->tempno
);
2285 void compilebitstring(struct bits
*bp
) {
2289 printf("code & 0x%lx", bp
->mask
);
2291 printf(") >> %d", bp
->shift
);
2296 void compilebitsplice(struct bitsplice
*splicep
) {
2297 struct bitsplicebits
*bsp
;
2301 for (bsp
= splicep
->splice
; bsp
!= NULL
; bsp
= bsp
->next
) {
2304 if (bsp
->type
== S_PARAMETER
)
2305 putchar(bsp
->value
.arg
->name
);
2307 assert(bsp
->type
== S_BITSTRING
);
2308 if (bsp
->value
.mask
== 0)
2311 printf("(code & 0x%lx)", bsp
->value
.mask
);
2314 printf(" << %d", bsp
->shift
);
2315 else if (bsp
->shift
< 0)
2316 printf(" >> %d", -bsp
->shift
);
2318 if (splicep
->entry
.value
!= 0)
2319 printf("%s0x%lx", last
, splicep
->entry
.value
);
2324 int bitcount(bits x
) {
2327 for (nbits
= 0; x
!= 0; x
>>= 1) {
2335 bits
allbitsset(int nbits
) {
2336 return (nbits
== MAXBITS
) ? ~0 : (1 << nbits
) - 1;
2340 void findent(FILE *f
) {
2343 for (i
= 1; i
< indentation
; i
+= 2)
2345 if (i
== indentation
)
2355 void *xrealloc(char *oldp
, size_t size
) {
2361 p
= realloc(oldp
, size
);
2363 fprintf(stderr
, "%s: allocate of %d bytes failed: %s\n", progname
,
2364 (int) size
, strerror(errno
));
2371 void *xmalloc(size_t size
) {
2372 return xrealloc(NULL
, size
);
2376 void *xstrdup(char *s
) {
2379 p
= xmalloc(strlen(s
) + 1);
2385 int prematureeof() {
2386 fprintf(stderr
, "%s: %s(%d): premature end of file\n", progname
, filename
,