]>
git.saurik.com Git - apple/xnu.git/blob - osfmk/ddb/makedis.c
a33bf216e2f9a146a388f1a933fa9bcb1c476b43
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.
286 #include <sys/errno.h>
292 #define MAXfunction 32 /* Max function name length. */
293 #define MAXBITS 32 /* Max bitstring length. */
294 typedef unsigned long bits
;
295 enum type
{T_ERROR
, T_UNKNOWN
, T_INTEGER
, T_STRING
};
296 const char *const typename
[] = {"error", "unknown", "integer", "string"};
297 enum walkstringop
{COUNTARRAYS
, DECLAREARRAYS
, COMPILEARRAYS
};
298 char *bitstype
= "unsigned long";
300 int maxfunctionname
, maxargwidth
;
301 char *progname
= "makedis";
304 char *headerfilename
;
308 int debug
, dump
, warnings
;
310 /* componentbits has a 1 bit for every possible number of strings we may want
311 to concatenate together at some stage. A separate C function is compiled
312 for each such case. */
325 int main(int argc
, char **argv
);
326 int makedis(FILE *f
, char *fname
);
327 struct function
*findfunction(char *function
);
328 int parseextern(struct function
*fp
, FILE *f
);
329 struct function
*makefunction(char *function
);
330 int parsebits(struct function
*fp
, char *bitstring
, int nbits
);
331 int parseentrybits(struct entry
*ep
, char *bitstring
, int nbits
, int issplice
);
332 int parsecontrol(char *name
, char *value
);
333 int parseargs(struct function
*fp
, FILE *f
, int *cp
);
334 int parsestring(struct function
*fp
, char *str
);
335 enum type
makestring(struct function
*fp
, struct string
**stringlink
,
336 char **stringp
, char *magic
, enum type targettype
);
337 int parsedollar(struct function
*fp
, char **stringp
, struct string
*sp
);
338 int parsebitsplice(struct function
*fp
, char *bitstring
, int nbits
,
340 int findvariable(struct function
*fp
, int name
, struct string
*sp
);
341 int parsefunctioncall(struct function
*fp
, char *start
, char **stringp
,
343 int parsearray(struct function
*fp
, char **stringp
, struct string
*sp
,
345 void dumpfunctions(void);
346 void dumpfunction(struct function
*fp
);
347 void showentry(FILE *f
, struct function
*fp
, struct entry
*ep
, bits highlight
);
348 void showbits(FILE *f
, struct entry
*ep
, int nbits
, bits highlight
);
349 void showargs(FILE *f
, struct arg
*ap
, int fieldwidth
);
350 void showstring(FILE *f
, struct string
*sp
);
351 void showstringelement(FILE *f
, struct string
*sp
);
352 void showfunctioncall(FILE *f
, struct functioncall
*fcp
);
353 void showarray(FILE *f
, struct array
*ap
);
354 int outputfunctions(void);
355 void outputidentity(FILE *f
);
356 int outputdeclarations(void);
357 void outputconcats(void);
358 void outputconcat(int n
);
359 void outputconcatheader(FILE *f
, int n
);
360 void findarrays(void);
361 int checkfixedlength(struct array
*ap
);
362 int outputfunction(struct function
*fp
);
363 void functionarray(struct function
*fp
);
364 void functionheader(FILE *f
, struct function
*fp
);
365 int simplearray(struct array
*ap
);
366 void compiletype(FILE *f
, enum type
*tp
);
367 int functionswitch(struct function
*fp
, bits mask
, bits value
);
368 int compilestring(int assignto
, struct string
*sp
, enum type type
);
369 int compilecheckedstring(int assignto
, struct string
*sp
, enum type type
);
370 void compileassign(int assignto
);
371 void compiletemp(int tempno
);
372 void compiletext(char *s
);
373 int compileconcat(struct string
*sp
, enum type type
);
374 int compilenull(enum type type
);
375 int compilesimple(struct string
*sp
, enum type type
);
376 int compilearrayref(struct array
*ap
);
377 int compilefunctioncall(struct string
*sp
);
378 int walkstring(struct string
*sp
, enum walkstringop op
, int tempno
);
379 int compilearray(struct array
*ap
);
380 void compilesimplearray(enum type
*tp
, char *name
, int num
, struct array
*ap
);
381 void declarearray(struct array
*ap
);
382 void compilebitstring(struct bits
*bp
);
383 void compilebitsplice(struct bitsplice
*splicep
);
384 int bitcount(bits x
);
385 bits
allbitsset(int nbits
);
386 void findent(FILE *f
);
388 void *xrealloc(char *oldp
, size_t size
);
389 void *xmalloc(size_t size
);
390 void *xstrdup(char *s
);
391 int prematureeof(void);
394 int main(int argc
, char **argv
) {
401 for (i
= 1; i
< argc
&& argv
[i
][0] == '-'; i
++) {
402 switch (argv
[i
][1]) {
406 headerfilename
= argv
[i
]; break;
415 fprintf(stderr
, "Usage: %s [file]\n", progname
);
420 return makedis(stdin
, "<stdin>");
423 if ((f
= fopen(argv
[i
], "r")) == NULL
) {
424 fprintf(stderr
, "%s: %s: %s\n", progname
, argv
[i
], strerror(errno
));
427 return makedis(f
, argv
[i
]);
431 int makedis(FILE *f
, char *fname
) {
433 char function
[MAXfunction
], bitstring
[MAXBITS
];
434 static char *string
= NULL
;
440 /* Loop for every line in the description. */
442 /* Ignore initial spaces and newlines. */
443 while (isspace(c
= getc(f
)))
449 /* Ignore comments. # only allowed at start of line. */
451 while ((c
= getc(f
)) != '\n')
453 return prematureeof();
458 /* Read function name, terminated by space. */
459 for (i
= 0; i
< sizeof function
&& !isspace(c
); i
++, c
= getc(f
)) {
461 return prematureeof();
464 if (i
>= sizeof function
) {
465 fprintf(stderr
, "%s: %s(%d): function name is too long: %.*s\n",
466 progname
, filename
, lineno
, i
, function
);
471 /* Skip to next field. */
472 while (isspace(c
) && c
!= '\n')
475 /* If not a control statement, read bitstring and/or arguments. */
476 if (function
[0] == ':')
477 fp
= 0; /* Silence gcc. */
479 fp
= makefunction(function
);
483 /* Read optional bitstring. */
484 for (i
= 0; i
< sizeof bitstring
&& isalnum(c
); i
++, c
= getc(f
)) {
486 return prematureeof();
490 fprintf(stderr
, "%s: %s(%d): bit string is too long: %.*s\n",
491 progname
, filename
, lineno
, i
, bitstring
);
494 if (parsebits(fp
, bitstring
, i
) != 0)
497 /* Read optional arguments. */
498 if (parseargs(fp
, f
, &c
) != 0)
501 /* Skip to next field. */
502 while (isspace(c
) && c
!= '\n')
505 /* : indicates an external (C) function. */
507 if (parseextern(fp
, f
) != 0)
513 /* Read associated text. */
516 for ( ; c
!= '\n'; i
++, c
= getc(f
)) {
518 return prematureeof();
519 if (i
>= stringlen
) {
520 stringlen
= stringlen
* 2 + 16;
521 string
= xrealloc(string
, stringlen
);
527 switch (string
[i
- 1]) {
532 while (isspace(c
= getc(f
)) && c
!= '\n') ;
538 if (i
>= stringlen
) {
539 stringlen
= stringlen
* 2 + 16;
540 string
= xrealloc(string
, stringlen
);
544 /* Parse the line just read. */
545 if (function
[0] == ':') {
546 if (parsecontrol(function
+ 1, string
) != 0)
549 if (parsestring(fp
, string
) != 0)
555 return outputfunctions();
559 /* A function in the description file. nbits and nargs are -1 until the
560 real values are known. */
562 struct function
*next
;
565 int nbits
; /* Number of bits in the bitpattern, 0 if none. */
566 int nargs
; /* Number of (x,y,...) parameters, 0 if none. */
567 char isarray
; /* Will be represented by a C array. */
568 int fixedlength
; /* If a C array, will be a char [][N] not a char *[]. */
569 struct entry
*first
, *last
;
570 /* Links to the value(s) supplied. */
571 struct arg
*args
; /* List of (x,y,...) names and types. */
573 struct function
*functions
;
576 /* Find the function with the given name. If not found, create a structure
577 for it, fill it out with a template, and return that. */
578 struct function
*findfunction(char *name
) {
581 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
582 if (strcmp(fp
->name
, name
) == 0)
585 if (strlen(name
) > maxfunctionname
)
586 maxfunctionname
= strlen(name
);
587 fp
= xmalloc(sizeof *fp
);
588 fp
->next
= functions
;
590 fp
->name
= xstrdup(name
);
591 fp
->type
= T_UNKNOWN
;
592 fp
->nbits
= fp
->nargs
= -1; /* nbits will be set correctly later. */
594 fp
->first
= fp
->last
= NULL
;
599 /* Parse an external (C) function declaration. This will look something like:
601 We're called just after seeing the ':'.
602 Return 0 if parsing is successful, 1 otherwise. */
603 int parseextern(struct function
*fp
, FILE *f
) {
606 if ((c
= getc(f
)) != '\n') {
608 "%s: %s(%d): extern declaration should be a lone `:'\n",
609 progname
, filename
, lineno
);
612 if (fp
->nbits
!= 0) {
614 "%s: %s(%d): extern functions should not have bitstrings\n",
615 progname
, filename
, lineno
);
619 fp
->first
= fp
->last
= NULL
;
624 /* A value supplied for a function (the third field in a description line).
625 In general there can be any number of such values, differing in the
626 bitpattern supplied. The mask and value fields describe the constant
627 bits in the bitpattern: mask indicates which bits they are and value
628 indicates the values of those bits. So this entry matches
629 ((x & mask) == value). */
633 struct bits
*bits
; /* List of named bitfields. */
634 struct string
*string
; /* Value of function when bitpattern matched. */
635 char done
; /* This entry has already been compiled. */
639 /* We've just seen a definition of function "name". Make a structure for it
640 if necessary, and a template entry that will describe the value given here.
642 struct function
*makefunction(char *name
) {
644 struct entry
*ep
= xmalloc(sizeof *ep
);
647 if (name
[0] == '%') {
652 fp
= findfunction(name
);
653 if (fp
->type
== T_UNKNOWN
)
655 else if (fp
->type
!= type
) {
656 fprintf(stderr
, "%s: %s(%d): function %s previously declared as %s, "
657 "here as %s\n", progname
, filename
, lineno
, name
,
658 typename
[fp
->type
], typename
[type
]);
664 if (fp
->first
!= NULL
)
673 /* A named bitfield within the bitpattern of a function entry, or within a
674 $[...] bitsplice. The mask covers the bitfield and the shift says how
675 many 0 bits there are after the last 1 in the mask. */
684 /* Parse the bitstring supplied for the given function. nbits says how many
685 bits there are; it can legitimately be 0. Return value is 0 on success. */
686 int parsebits(struct function
*fp
, char *bitstring
, int nbits
) {
689 else if (fp
->nbits
!= nbits
) {
690 fprintf(stderr
, "%s: %s(%d): bit string of length %d;\n",
691 progname
, filename
, lineno
, nbits
);
692 fprintf(stderr
, " function %s has bit strings of length %d\n",
693 fp
->name
, fp
->nbits
);
696 return parseentrybits(fp
->last
, bitstring
, nbits
, 0);
700 /* Parse a bitstring that is the pattern for a function entry or that is in a
701 $[...] bitsplice. Put the result in ep. Return value is 0 on success. */
702 int parseentrybits(struct entry
*ep
, char *bitstring
, int nbits
, int issplice
) {
705 bits mask
, value
, entrymask
;
709 for (i
= 0; i
< nbits
; i
++) {
710 bit
= bitstring
[nbits
- 1 - i
];
720 fprintf(stderr
, "%s: %s(%d): invalid character in bitstring: %c\n",
721 progname
, filename
, lineno
, bit
);
725 for (bp
= ep
->bits
; bp
!= NULL
; bp
= bp
->next
) {
726 if (bp
->name
== bit
) {
728 "%s: %s(%d): bitstring name %c used twice\n",
729 progname
, filename
, lineno
, bit
);
735 for (j
= i
+ 1; j
< nbits
&& bitstring
[nbits
- 1 - j
] == bit
; j
++)
737 bp
= xmalloc(sizeof *bp
);
739 bp
->mask
= entrymask
;
751 /* Parse a control line. This looks something like:
752 :bitstype unsigned int
753 in which case we will be called with name "bitstype" and
754 value "unsigned int". */
755 int parsecontrol(char *name
, char *value
) {
756 if (strcmp(name
, "bitstype") == 0)
757 bitstype
= xstrdup(value
);
759 fprintf(stderr
, "%s: %s(%d): unrecognised control keyword %s\n",
760 progname
, filename
, lineno
, name
);
767 /* A parameter to a function, e.g., x in:
768 %f aaa(%x) $a + $x */
776 /* Parse the parameters (x,y,...) to a function and put the result in fp.
777 The entry that is being built is fp->last. cp points to the opening
778 (; if it does not point to a ( then there are no parameters. If
779 this is the first entry for the function, fp->nargs will be -1 and
780 we will build up an argument list. Otherwise, fp->nargs will be
781 >= 0 and we will only check that the arguments here are consistent
782 with what went before. Return value is 0 on success. */
783 int parseargs(struct function
*fp
, FILE *f
, int *cp
) {
784 struct arg
**arglink
, *ap
;
799 if (fp
->nargs
>= 0 && nargs
> fp
->nargs
) {
801 "%s: %s(%d): %d arg(s) instead of %d for %s\n",
802 progname
, filename
, lineno
, nargs
, fp
->nargs
,
813 if (!isalpha(name
)) {
815 "%s: %s(%d): argument should be letter: %c\n",
816 progname
, filename
, lineno
, name
);
819 for (bp
= fp
->last
->bits
; bp
!= NULL
; bp
= bp
->next
) {
820 if (bp
->name
== name
) {
822 "%s: %s(%d): %c is a bitstring and an arg\n",
823 progname
, filename
, lineno
, name
);
827 if (fp
->nargs
>= 0) {
828 if ((*arglink
)->name
!= name
) {
830 "%s: %s(%d): arg %d of %s is %c not %c\n",
831 progname
, filename
, lineno
, nargs
, fp
->name
,
832 (*arglink
)->name
, name
);
835 if ((*arglink
)->type
!= t
) {
837 "%s: %s(%d): arg %c of %s: inconsistent type\n",
838 progname
, filename
, lineno
, name
, fp
->name
);
842 for (ap
= fp
->args
; ap
!= *arglink
; ap
= ap
->next
) {
843 if (ap
->name
== name
) {
845 "%s: %s(%d): argument name %c used twice\n",
846 progname
, filename
, lineno
, name
);
850 *arglink
= xmalloc(sizeof **arglink
);
851 (*arglink
)->name
= name
;
852 (*arglink
)->type
= t
;
854 arglink
= &(*arglink
)->next
;
860 "%s: %s(%d): bad character in argument list: %c\n"
861 " (arguments must be single letters)\n",
862 progname
, filename
, lineno
, *cp
);
873 if (width
> maxargwidth
)
875 } else if (fp
->nargs
!= nargs
) {
876 fprintf(stderr
, "%s: %s(%d): argument list of length %d;\n",
877 progname
, filename
, lineno
, nargs
);
878 fprintf(stderr
, " function %s has argument lists of length %d\n",
879 fp
->name
, fp
->nargs
);
887 /* Parse the string describing the value of this entry for our
888 function. Return 0 on success. */
889 int parsestring(struct function
*fp
, char *str
) {
892 t
= makestring(fp
, &fp
->last
->string
, &str
, NULL
, fp
->type
);
895 if (fp
->type
!= t
&& t
!= T_UNKNOWN
) {
896 fprintf(stderr
, "%s: %s(%d): function %s has inconsistent types\n",
897 progname
, filename
, lineno
, fp
->name
);
904 /* A parsed representation of the whole string describing a value of a
905 function, or certain strings within that (e.g., array indices). This is a
906 linked list of substrings whose type is given by the type field. */
910 S_TEXT
, S_BITSTRING
, S_BITSPLICE
, S_PARAMETER
, S_FUNCTIONCALL
, S_ARRAY
912 union value
{ /* The fields here correspond to the enum values. */
913 char *text
; /* plain text */
914 struct bits
*bits
; /* $x where x is a bitfield */
915 struct bitsplice
*bitsplice
; /* $[...] */
916 struct arg
*parameter
; /* $x where x is a parameter */
917 struct functioncall
*functioncall
; /* $func(...) */
918 struct array
*array
; /* {...}[...] */
922 /* The representation of a function call $func(...) in the description of a
924 struct functioncall
{
925 struct function
*function
;
926 struct stringlist
*args
;
929 /* The representation of an array selection {...|...}[...] in the description
930 of a function value. tempno is used when constructing a C variable name
931 that will contain the strings or numbers in an array. */
933 struct string
*index
; /* what's between [...] */
934 struct stringlist
*elements
; /* what's between {...} */
935 enum type type
; /* the type of each element */
939 /* A list of strings, being the list of arguments in a function call or the
940 list of elements of an array. This is a linked list of linked lists. */
942 struct stringlist
*next
;
944 struct string
*string
;
948 /* The following are the only characters with special meaning at the top level
949 of parsing of a function value. When parsing arrays or function calls,
950 other characters become special. */
951 #define MAKESTRING_MAGIC "${"/*}*/
954 /* Parse a function return-value string or substring and make a struct string
955 list for it. The string starts at *stringp and ends at a \0 or at any
956 character in the `magic' string other than { or $. *stringp is updated
957 to point to the terminating character. The parsed representation is put
958 at *stringlink. `fp' is the function whose return value is being parsed.
959 `targettype' is the expected type of the result, if known.
960 The return value is the actual type. */
961 enum type
makestring(struct function
*fp
, struct string
**stringlink
,
962 char **stringp
, char *magic
, enum type targettype
) {
964 struct string
*sp
, **firststringlink
;
967 enum type t
= targettype
, newt
;
970 magic
= MAKESTRING_MAGIC
;
972 firststringlink
= stringlink
;
975 sp
= xmalloc(sizeof *sp
);
979 if (strchr(magic
, *q
) != NULL
) {
980 if (*q
!= ')' || parenlevel
== 0)
994 } while (*++q
!= '\0');
997 sp
->value
.text
= q
= xmalloc(n
+ 1);
1005 } else if (*p
== '$') {
1006 if (parsedollar(fp
, &p
, sp
) != 0)
1014 newt
= sp
->value
.parameter
->type
;
1016 case S_FUNCTIONCALL
:
1017 newt
= sp
->value
.functioncall
->function
->type
;
1020 fprintf(stderr
, "makestring type %d\n", sp
->type
);
1023 } else if (*p
== '{'/*}*/) {
1024 if (parsearray(fp
, &p
, sp
, t
) != 0)
1026 newt
= sp
->value
.array
->type
;
1033 else if (newt
!= T_UNKNOWN
&& t
!= newt
) {
1034 if (stringlink
== firststringlink
) {
1035 fprintf(stderr
, "%s: %s(%d): expected %s type:\n", progname
,
1036 filename
, lineno
, typename
[t
]);
1037 showstringelement(stderr
, sp
);
1041 fprintf(stderr
, "%s: %s(%d): mixed types in string:\n",
1042 progname
, filename
, lineno
);
1043 showstring(stderr
, *firststringlink
);
1044 fprintf(stderr
, " -- %s\n", typename
[t
]);
1045 showstringelement(stderr
, sp
);
1046 fprintf(stderr
, " -- %s\n", typename
[newt
]);
1050 stringlink
= &sp
->next
;
1055 if (components
>= MAXBITS
) {
1056 fprintf(stderr
, "%s: %s(%d): excessively complicated string\n",
1057 progname
, filename
, lineno
);
1060 componentbits
|= 1 << components
;
1065 /* Parse a $ operation at **stringp and update *stringp to point past it.
1066 `fp' is the function whose return value is being parsed. The parsed
1067 item will be put at *sp. Return 0 on success, nonzero on error. */
1068 int parsedollar(struct function
*fp
, char **stringp
, struct string
*sp
) {
1076 while (isalnum(*p
) || *p
== '_')
1078 if (*start
== '[') {
1080 fprintf(stderr
, "%s: %s(%d): missing ] or bad character in $[\n",
1081 progname
, filename
, lineno
);
1085 return parsebitsplice(fp
, start
+ 1, p
- start
- 1, sp
);
1088 fprintf(stderr
, "%s: %s(%d): missing identifier after $\n", progname
,
1092 if (p
== start
+ 1) {
1093 if (findvariable(fp
, *start
, sp
) != 0)
1096 if (parsefunctioncall(fp
, start
, &p
, sp
) != 0)
1104 /* The representation of a $[...] bitsplice. It is parsed into a
1105 struct entry just as if it were a bitfield parameter, then analysed
1106 into a chain of struct bitsplicebits. These in conjunction with
1107 the constant portion of the struct entry will allow the bitsplice to
1108 be compiled. Each bitsplicebits element represents either a numeric
1109 argument to the current function, in which case it will be shifted
1110 into place; or a bitfield name from the bitfield description of the
1111 current function, in which case it will be shifted by the difference
1112 between the position of the bitfield in the argument and the position
1113 it occurs in the bitsplice. `shift' indicates how much to shift left
1114 the associated value; if it is negative the value is shifted right.
1115 For instance, in a function like this:
1116 %oh xx00(%y) $[yyxx]
1117 the bitsplicebits for y will have shift = 2 and value.arg pointing to y,
1118 and those for x will have shift = -2 and value.mask = binary 1100.
1119 As an optimisation, contiguous bitfields that are also contiguous in the
1120 bitsplice will be combined. For instance:
1121 %oh xxyy00 $[0xxyy0]
1122 will compile the same code as:
1123 %oh zzzz00 $[0zzzz0].
1124 As another optimisation, a bitfield that occupies the entire bitstring
1125 for a function will be treated like a parameter in that it will not be
1126 masked in the bitsplice. For instance:
1127 %oh xxxxxx $[0xxxxxx0]
1128 will compile the same code as:
1129 %oh (%x) $[0xxxxxx0]. */
1133 struct bitsplicebits
*splice
;
1135 struct bitsplicebits
{
1136 struct bitsplicebits
*next
;
1138 enum elementtype type
;
1146 int parsebitsplice(struct function
*fp
, char *bitstring
, int nbits
,
1147 struct string
*sp
) {
1148 struct bitsplice
*splicep
;
1149 struct bitsplicebits
*bsp
, *lastbsp
, **bspp
;
1151 int shift
, nfrombits
, ntobits
;
1154 splicep
= xmalloc(sizeof *splicep
);
1155 splicep
->nbits
= nbits
;
1156 if (parseentrybits(&splicep
->entry
, bitstring
, nbits
, 1) != 0)
1158 bspp
= &splicep
->splice
;
1160 for (bp
= splicep
->entry
.bits
; bp
!= NULL
; bp
= bp
->next
) {
1161 if (findvariable(fp
, bp
->name
, sp
) != 0)
1164 if (sp
->type
== S_BITSTRING
) {
1165 nfrombits
= bitcount(sp
->value
.bits
->mask
);
1166 ntobits
= bitcount(bp
->mask
);
1168 if (nfrombits
!= ntobits
) {
1169 fprintf(stderr
, "%s: %s(%d): warning: "
1170 "bitstring $%c %ser than its place "
1172 progname
, filename
, lineno
, bp
->name
,
1173 (nfrombits
> ntobits
) ? "bigg" : "small");
1176 shift
-= sp
->value
.bits
->shift
;
1178 /* See if this bitfield can be combined with a previous contiguous
1180 if (lastbsp
!= NULL
&& lastbsp
->type
== S_BITSTRING
1181 && lastbsp
->shift
== shift
) {
1182 lastbsp
->value
.mask
|= sp
->value
.bits
->mask
;
1186 assert(sp
->type
== S_PARAMETER
);
1187 if (sp
->value
.parameter
->type
!= T_INTEGER
) {
1189 "%s: %s(%d): variable %c in $[...] should be integer\n",
1190 progname
, filename
, lineno
, sp
->value
.parameter
->name
);
1194 *bspp
= bsp
= xmalloc(sizeof *bsp
);
1195 bsp
->type
= sp
->type
;
1197 if (sp
->type
== S_PARAMETER
)
1198 bsp
->value
.arg
= sp
->value
.parameter
;
1200 bsp
->value
.mask
= sp
->value
.bits
->mask
;
1206 /* Look for a spliced element that is the entire bitstring argument to
1207 this function and therefore doesn't need to be masked. */
1208 allbits
= allbitsset(fp
->nbits
);
1209 for (bsp
= splicep
->splice
; bsp
!= NULL
; bsp
= bsp
->next
) {
1210 if (bsp
->type
== S_BITSTRING
) {
1211 for (b
= bsp
->value
.mask
; b
!= 0 && !(b
& 1); b
>>= 1) ;
1213 bsp
->value
.mask
= 0;
1216 sp
->type
= S_BITSPLICE
;
1217 sp
->value
.bitsplice
= splicep
;
1222 int findvariable(struct function
*fp
, int name
, struct string
*sp
) {
1226 for (bp
= fp
->last
->bits
; bp
!= NULL
; bp
= bp
->next
) {
1227 if (bp
->name
== name
) {
1228 sp
->type
= S_BITSTRING
;
1229 sp
->value
.bits
= bp
;
1233 for (ap
= fp
->args
; ap
!= NULL
; ap
= ap
->next
) {
1234 if (ap
->name
== name
) {
1235 sp
->type
= S_PARAMETER
;
1236 sp
->value
.parameter
= ap
;
1240 fprintf(stderr
, "%s: %s(%d): undefined parameter %c\n", progname
, filename
,
1246 int parsefunctioncall(struct function
*fp
, char *start
, char **stringp
,
1247 struct string
*sp
) {
1249 struct functioncall
*fcp
;
1250 struct stringlist
**arglink
, *arg
;
1255 fprintf(stderr
, "%s: %s(%d): missing ( after function %.*s\n", progname
,
1256 filename
, lineno
, (int)(p
- start
), start
);
1259 sp
->type
= S_FUNCTIONCALL
;
1260 sp
->value
.functioncall
= fcp
= xmalloc(sizeof *fcp
);
1261 *p
= '\0'; /* Ugly. */
1262 fcp
->function
= findfunction(start
);
1264 arglink
= &fcp
->args
;
1267 arg
= xmalloc(sizeof *arg
);
1268 t
= makestring(fp
, &arg
->string
, &p
, MAKESTRING_MAGIC
",)",
1274 arglink
= &arg
->next
;
1288 int parsearray(struct function
*fp
, char **stringp
, struct string
*sp
,
1292 struct stringlist
**elementlink
, *element
;
1295 assert(*p
== '{'/*}*/);
1297 sp
->value
.array
= ap
= xmalloc(sizeof *ap
);
1299 elementlink
= &ap
->elements
;
1301 if (*++p
!= /*{*/'}') {
1303 element
= xmalloc(sizeof *element
);
1304 t
= makestring(fp
, &element
->string
, &p
,
1305 MAKESTRING_MAGIC
/*{*/"|}", t
);
1309 if (ap
->type
== T_UNKNOWN
)
1311 else if (t
!= T_UNKNOWN
&& ap
->type
!= t
) {
1312 fprintf(stderr
, "%s: %s(%d): mixed types in array:\n",
1313 progname
, filename
, lineno
);
1314 showstring(stderr
, ap
->elements
->string
);
1315 fprintf(stderr
, " -- %s\n", typename
[ap
->type
]);
1316 showstring(stderr
, element
->string
);
1317 fprintf(stderr
, " -- %s\n", typename
[t
]);
1320 *elementlink
= element
;
1321 elementlink
= &element
->next
;
1328 *elementlink
= NULL
;
1329 assert(*p
== /*{*/'}');
1331 fprintf(stderr
, "%s: %s(%d): missing [index] after array\n",
1332 progname
, filename
, lineno
);
1336 t
= makestring(fp
, &ap
->index
, &p
, MAKESTRING_MAGIC
"]", T_INTEGER
);
1339 if (t
== T_STRING
) {
1340 fprintf(stderr
, "%s: %s(%d): array index cannot be string:\n",
1341 progname
, filename
, lineno
);
1342 showstring(stderr
, ap
->index
);
1346 fprintf(stderr
, "%s: %s(%d): [ without ]\n", progname
, filename
,
1355 void dumpfunctions() {
1356 struct function
*fp
;
1358 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
)
1363 void dumpfunction(struct function
*fp
) {
1366 for (ep
= fp
->first
; ep
!= NULL
; ep
= ep
->next
)
1367 showentry(stderr
, fp
, ep
, 0);
1371 /* Entries are not shown exactly as they would be input, since \ would
1372 need to be provided before some characters such as $ or {. But the
1373 characters "|},]" pose a problem since a \ is only needed in certain
1374 contexts and is annoying otherwise. It's not worth doing this right,
1375 since it's only used for error messages. */
1376 void showentry(FILE *f
, struct function
*fp
, struct entry
*ep
, bits highlight
) {
1377 if (fp
->type
== T_INTEGER
)
1379 fprintf(f
, "%-*s ", maxfunctionname
+ 1, fp
->name
);
1380 if (fp
->nbits
== 0 && fp
->nargs
== 0)
1381 fprintf(f
, "%-*s", maxargwidth
, "()");
1383 showbits(f
, ep
, fp
->nbits
, 0);
1384 showargs(f
, fp
->args
, maxargwidth
- fp
->nbits
);
1387 showstring(f
, ep
->string
);
1389 if (highlight
!= 0) {
1390 fprintf(f
, "%-*s ", maxfunctionname
+ 1, "");
1391 showbits(f
, ep
, fp
->nbits
, highlight
);
1397 void showbits(FILE *f
, struct entry
*ep
, int nbits
, bits highlight
) {
1404 i
= 1 << (nbits
- 1);
1416 if (highlight
!= 0 || (ep
->mask
& i
)) {
1417 putc((value
& i
) ? one
: zero
, f
);
1420 assert(bp
!= NULL
&& (bp
->mask
& i
));
1424 } while (bp
->mask
& i
);
1431 void showargs(FILE *f
, struct arg
*ap
, int fieldwidth
) {
1442 isint
= (ap
->type
== T_INTEGER
);
1443 fprintf(f
, "%c%s%c", lastc
, isint
? "%" : "", ap
->name
);
1447 } while (ap
!= NULL
);
1450 fprintf(f
, "%-*s", fieldwidth
- width
, "");
1454 void showstring(FILE *f
, struct string
*sp
) {
1455 for ( ; sp
!= NULL
; sp
= sp
->next
)
1456 showstringelement(f
, sp
);
1460 void showstringelement(FILE *f
, struct string
*sp
) {
1461 struct bitsplice
*bsp
;
1465 fputs(sp
->value
.text
, f
);
1468 fprintf(f
, "$%c", sp
->value
.bits
->name
);
1472 bsp
= sp
->value
.bitsplice
;
1473 showbits(f
, &bsp
->entry
, bsp
->nbits
, 0);
1477 fprintf(f
, "$%c", sp
->value
.parameter
->name
);
1479 case S_FUNCTIONCALL
:
1480 showfunctioncall(f
, sp
->value
.functioncall
);
1483 showarray(f
, sp
->value
.array
);
1486 fprintf(stderr
, "showstring case %d\n", sp
->type
);
1492 void showfunctioncall(FILE *f
, struct functioncall
*fcp
) {
1493 struct stringlist
*sp
;
1496 fprintf(f
, "$%s(", fcp
->function
->name
);
1498 for (sp
= fcp
->args
; sp
!= NULL
; sp
= sp
->next
) {
1501 showstring(f
, sp
->string
);
1507 void showarray(FILE *f
, struct array
*ap
) {
1508 struct stringlist
*sp
;
1513 for (sp
= ap
->elements
; sp
!= NULL
; sp
= sp
->next
) {
1516 showstring(f
, sp
->string
);
1518 fputs(/*{*/"}[", f
);
1519 showstring(f
, ap
->index
);
1524 const char commonpreamble
[] = "\
1529 const char concatpreamble
[] = "\
1530 static char *dis_buf;\n\
1531 static int dis_bufindex, dis_buflen;\n\
1533 void *dis_alloc(size_t size)\n\
1536 int newindex = dis_bufindex + size;\n\
1537 if (newindex > dis_buflen) {\n\
1538 dis_buflen = newindex * 4;\n\
1539 dis_buf = malloc(dis_buflen);\n\
1540 /* We can't use realloc because there might be pointers extant into\n\
1541 the old buffer. So we waste the memory of the old buffer. We\n\
1542 should soon reach an adequate buffer size and stop leaking. */\n\
1543 if (dis_buf == 0) {\n\
1544 perror(\"malloc\");\n\
1547 dis_bufindex = 0;\n\
1549 p = dis_buf + dis_bufindex;\n\
1550 dis_bufindex = newindex;\n\
1556 dis_bufindex = 0;\n\
1561 const char concatdeclarations
[] = "\
1562 #include <string.h>\n\
1563 #include <stdlib.h>\n\
1564 #include <sys/errno.h>\n\
1566 extern void *dis_realloc(void *p, size_t size); /* User-provided. */\n\
1567 void *dis_alloc(size_t size);\n\
1568 void dis_done(void);\n\
1571 const char nonconcatpreamble
[] = "\
1572 void dis_done() {}\n\
1576 int outputfunctions() {
1577 struct function
*fp
;
1579 outputidentity(stdout
);
1580 if (headerfilename
!= NULL
) {
1581 if ((headerfile
= fopen(headerfilename
, "w")) == NULL
) {
1582 fprintf(stderr
, "%s: create %s: %s\n", progname
, headerfilename
,
1586 outputidentity(headerfile
);
1587 fprintf(headerfile
, commonpreamble
, bitstype
);
1588 printf("\n#include \"%s\"\n", headerfilename
);
1590 printf(commonpreamble
, bitstype
);
1592 if (outputdeclarations() != 0)
1595 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
1599 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
1600 if (fp
->first
!= NULL
&& !fp
->isarray
) {
1601 if (outputfunction(fp
) != 0)
1609 void outputidentity(FILE *f
) {
1612 fprintf(f
, "/*\n * This file was generated by:\n *");
1613 for (p
= global_argv
; *p
!= NULL
; p
++)
1614 fprintf(f
, " %s", *p
);
1615 fprintf(f
, "\n */\n\n");
1619 int outputdeclarations() {
1620 FILE *f
= headerfile
? headerfile
: stdout
;
1621 struct function
*fp
;
1623 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
1624 if (fp
->type
!= T_UNKNOWN
) {
1626 fprintf(f
, "extern ");
1627 if (fp
->fixedlength
> 0)
1628 fprintf(f
, "char %s[][%d]", fp
->name
, fp
->fixedlength
);
1630 compiletype(f
, &fp
->type
);
1631 fprintf(f
, "%s[]", fp
->name
);
1634 functionheader(f
, fp
);
1642 void outputconcats() {
1645 if (componentbits
& ~3) {
1646 fputs(concatdeclarations
, headerfile
? headerfile
: stdout
);
1647 fputs(concatpreamble
, stdout
);
1649 fputs(nonconcatpreamble
, stdout
);
1650 for (i
= 2; i
< MAXBITS
; i
++) {
1651 if (componentbits
& (1 << i
))
1657 void outputconcat(int n
) {
1663 outputconcatheader(headerfile
, n
);
1664 fprintf(headerfile
, ";\n");
1666 outputconcatheader(stdout
, n
);
1667 printf("\n{\n void *p;\n int len = ");
1669 for (i
= 0; i
< n
; i
++) {
1670 printf("%sstrlen(p%d)", last
, i
);
1673 printf(";\n p = dis_alloc(len + 1);\n return ");
1674 for (i
= 1; i
< n
; i
++)
1676 printf("strcpy(p, p0)");
1677 for (i
= 1; i
< n
; i
++)
1678 printf(", p%d)", i
);
1683 void outputconcatheader(FILE *f
, int n
) {
1687 fprintf(f
, "char *dis_concat%d(", n
);
1688 for (i
= 0; i
< n
; i
++) {
1689 fprintf(f
, "%schar *p%d", last
, i
);
1697 struct function
*fp
;
1699 struct string
*estr
, *indexstr
;
1702 for (fp
= functions
; fp
!= NULL
; fp
= fp
->next
) {
1703 if (fp
->nbits
> 0 && fp
->nargs
> 0)
1708 if (ep
== NULL
|| ep
->next
!= NULL
)
1711 if (estr
== NULL
|| estr
->next
!= NULL
|| estr
->type
!= S_ARRAY
)
1713 indexstr
= estr
->value
.array
->index
;
1714 if (indexstr
->next
!= NULL
)
1716 if (fp
->nbits
> 0) {
1718 if (bp
== NULL
|| bp
->next
!= NULL
|| bp
->shift
!= 0)
1720 if (bp
->mask
!= allbitsset(fp
->nbits
))
1722 if (indexstr
->type
!= S_BITSTRING
|| indexstr
->value
.bits
!= bp
)
1725 if (indexstr
->type
!= S_PARAMETER
1726 || indexstr
->value
.parameter
!= fp
->args
)
1729 if (!simplearray(estr
->value
.array
))
1733 (fp
->type
== T_INTEGER
) ? 0 : checkfixedlength(estr
->value
.array
);
1738 int checkfixedlength(struct array
*ap
) {
1739 int len
, maxlen
, wasted
, n
;
1740 struct stringlist
*lp
;
1743 for (lp
= ap
->elements
; lp
!= NULL
; lp
= lp
->next
) {
1744 if (lp
->string
== NULL
)
1746 assert(lp
->string
->type
== S_TEXT
);
1747 len
= strlen(lp
->string
->value
.text
);
1751 for (wasted
= n
= 0, lp
= ap
->elements
; lp
!= NULL
; n
++, lp
= lp
->next
) {
1752 if (lp
->string
== NULL
)
1754 wasted
+= maxlen
- strlen(lp
->string
->value
.text
);
1756 if (wasted
< n
* sizeof(char *)) /* Should be target's sizeof. */
1762 int outputfunction(struct function
*fp
) {
1764 functionheader(stdout
, fp
);
1765 printf("\n{\n"/*}*/);
1766 switch (functionswitch(fp
, 0, 0)) {
1771 fprintf(stderr
, "%s: warning: not all cases of %s covered\n",
1772 progname
, fp
->name
);
1780 void functionarray(struct function
*fp
) {
1783 ap
= fp
->first
->string
->value
.array
;
1785 compilesimplearray(&fp
->type
, fp
->name
, 0, ap
);
1789 void functionheader(FILE *f
, struct function
*fp
) {
1793 compiletype(f
, &fp
->type
);
1794 fprintf(f
, "%s(", fp
->name
);
1796 if (fp
->nbits
> 0) {
1797 fprintf(f
, "bits code");
1800 for (ap
= fp
->args
; ap
!= NULL
; ap
= ap
->next
) {
1801 fprintf(f
, "%s", last
);
1802 compiletype(f
, &ap
->type
);
1812 int simplearray(struct array
*ap
) {
1813 struct stringlist
*lp
;
1815 for (lp
= ap
->elements
; lp
!= NULL
; lp
= lp
->next
) {
1816 if (lp
->string
!= NULL
1817 && (lp
->string
->next
!= NULL
|| lp
->string
->type
!= S_TEXT
))
1820 return (lp
== NULL
);
1824 void compiletype(FILE *f
, enum type
*tp
) {
1830 fprintf(f
, "char *");
1833 fprintf(f
, "bits ");
1836 fprintf(stderr
, "compiletype type %d\n", *tp
);
1842 /* Generate code for entries in function fp whose bitstring b satisfies
1843 the constraint (b & mask) == value. Return 1 if generated switch
1844 always does `return', 0 if not, -1 on error.
1845 The algorithm is as follows. Scan the eligible entries to find the
1846 largest set of bits not in the passed-in mask which always have a
1847 constant value (are not variable). One `default' entry is allowed
1848 all of whose bits are variable. For each value of the constant bits,
1849 generate a `switch' case and invoke the function recursively with
1850 that value included in the constraint parameters. The recursion
1851 stops when no set of constant bits is found, perhaps because the
1852 mask parameter has all bits set.
1853 This algorithm could be improved. Currently it will fail if there
1854 are input lines "xxyy", "00xx" and "yy00", each of which is default with
1855 respect to the others. The correct behaviour would then be to select
1856 a bit that is sometimes constant and deal with those cases first.
1857 But this problem has not yet arisen in real life. */
1858 int functionswitch(struct function
*fp
, bits mask
, bits value
) {
1859 struct entry
*ep
, *defaultcase
;
1860 bits allbits
, constbits
, missingcases
;
1861 int nhits
, ncases
, nconstbits
, alwaysreturns
;
1864 allbits
= allbitsset(fp
->nbits
);
1865 constbits
= allbits
& ~mask
;
1869 "functionswitch(%s): (x & 0x%lx) == 0x%lx; const == 0x%lx\n",
1870 fp
->name
, mask
, value
, constbits
);
1875 for (ep
= fp
->first
; ep
!= NULL
; ep
= ep
->next
) {
1876 /* If this is not one of the entries under consideration, skip. */
1878 || (ep
->mask
& mask
) != mask
|| (ep
->value
& mask
) != value
)
1882 showentry(stderr
, fp
, ep
, 0);
1884 /* If this entry has no constant bits in the still-variable portion,
1885 it's the default. */
1886 if ((constbits
& ep
->mask
) == 0) {
1887 if (defaultcase
!= NULL
) {
1889 "%s: function %s: unable to distinguish between:\n",
1890 progname
, fp
->name
);
1891 showentry(stderr
, fp
, defaultcase
, 0);
1892 showentry(stderr
, fp
, ep
, 0);
1898 fprintf(stderr
, "^^ default case\n");
1901 if (debug
&& (constbits
& ~ep
->mask
)) {
1903 fprintf(stderr
, "const now 0x%lx\n", constbits
& ep
->mask
);
1905 constbits
&= ep
->mask
;
1911 if (constbits
== allbits
)
1912 printf("switch (code) {\n"/*}*/);
1914 printf("switch (code & 0x%lx) {\n"/*}*/, constbits
);
1915 for (ep
= fp
->first
; ep
!= NULL
; ep
= ep
->next
) {
1916 /* If this is not one of the entries under consideration, skip. */
1917 if ((ep
->mask
& mask
) != mask
|| (ep
->value
& mask
) != value
)
1919 if (ep
->done
|| ep
== defaultcase
)
1923 printf("case 0x%lx:\n", ep
->value
& constbits
);
1924 switch (functionswitch(fp
, mask
| constbits
,
1925 value
| (ep
->value
& constbits
))) {
1930 indentation
++; indent(); indentation
--;
1937 nconstbits
= bitcount(constbits
);
1938 missingcases
= ((nconstbits
== MAXBITS
) ? 0 : 1 << nconstbits
) - ncases
;
1939 if (alwaysreturns
) {
1940 switch (missingcases
) {
1942 if (defaultcase
!= NULL
) {
1943 fprintf(stderr
, "%s: warning: redundant entry:\n", progname
);
1944 showentry(stderr
, fp
, defaultcase
, 0);
1949 if (defaultcase
!= NULL
&& nconstbits
!= 0) {
1951 "%s: warning: variable bit(s) could be constant:\n",
1953 showentry(stderr
, fp
, defaultcase
, constbits
);
1961 if (defaultcase
!= NULL
) {
1962 /* If defaultcase has some constant bits of its own, recursion will
1963 check that they have the required value. */
1964 if ((defaultcase
->mask
& ~mask
) == 0) {
1966 if (compilestring(-1, defaultcase
->string
, fp
->type
) != 0)
1968 defaultcase
->done
= 1;
1971 alwaysreturns
= functionswitch(fp
, mask
, value
);
1976 return alwaysreturns
;
1980 int compilestring(int assignto
, struct string
*sp
, enum type type
) {
1983 tempno
= walkstring(sp
, COUNTARRAYS
, assignto
);
1984 if (tempno
> assignto
) {
1988 (void) walkstring(sp
, DECLAREARRAYS
, assignto
);
1989 if (walkstring(sp
, COMPILEARRAYS
, assignto
) < 0)
1992 if (compilecheckedstring(assignto
, sp
, type
) != 0)
1994 if (tempno
> assignto
) {
2003 int compilecheckedstring(int assignto
, struct string
*sp
, enum type type
) {
2004 compileassign(assignto
);
2005 if (compileconcat(sp
, type
) != 0)
2012 void compileassign(int assignto
) {
2017 compiletemp(assignto
);
2023 void compiletemp(int tempno
) {
2024 printf("t__%d", tempno
);
2028 void compiletext(char *s
) {
2031 for ( ; *s
!= '\0'; s
++) {
2044 int compileconcat(struct string
*sp
, enum type type
) {
2050 return compilenull(type
);
2051 if (sp
->next
== NULL
)
2052 return compilesimple(sp
, type
);
2053 if (type
!= T_INTEGER
) {
2054 for (elements
= 0, sp1
= sp
; sp1
!= NULL
; elements
++, sp1
= sp1
->next
) ;
2055 printf("dis_concat%d(", elements
);
2058 for (sp1
= sp
; sp1
!= NULL
; sp1
= sp1
->next
) {
2060 if (type
!= T_INTEGER
)
2062 if (sp1
->type
== S_ARRAY
)
2063 compilearrayref(sp1
->value
.array
);
2065 if (compilesimple(sp1
, type
) != 0)
2068 if (type
!= T_INTEGER
)
2074 int compilenull(enum type type
) {
2075 if (type
== T_INTEGER
) {
2076 fprintf(stderr
, "%s: empty integer expression\n", progname
);
2084 int compilesimple(struct string
*sp
, enum type type
) {
2086 return compilenull(type
);
2089 if (type
== T_INTEGER
)
2090 printf("%s", sp
->value
.text
);
2092 compiletext(sp
->value
.text
);
2095 compilebitstring(sp
->value
.bits
);
2098 compilebitsplice(sp
->value
.bitsplice
);
2101 putchar(sp
->value
.parameter
->name
);
2103 case S_FUNCTIONCALL
:
2104 return compilefunctioncall(sp
);
2106 if (compilearrayref(sp
->value
.array
) != 0)
2110 fprintf(stderr
, "compilesimple case %d", sp
->type
);
2117 int compilearrayref(struct array
*ap
) {
2118 compiletemp(ap
->tempno
);
2119 if (simplearray(ap
)) {
2121 if (compileconcat(ap
->index
, T_INTEGER
) != 0)
2129 int compilefunctioncall(struct string
*sp
) {
2130 struct function
*fp
;
2131 struct stringlist
*actualp
;
2132 struct arg
*formalp
;
2135 enum type formaltype
;
2137 assert(sp
->type
== S_FUNCTIONCALL
);
2138 fp
= sp
->value
.functioncall
->function
;
2139 printf("%s%c", fp
->name
, fp
->isarray
? '[' : '(');
2143 actualp
= sp
->value
.functioncall
->args
;
2144 while (actualp
!= NULL
) {
2147 formaltype
= T_INTEGER
;
2149 if (formalp
== NULL
) {
2150 fprintf(stderr
, "%s: too many arguments to %s:\n", progname
,
2152 showstring(stderr
, sp
);
2156 formaltype
= formalp
->type
;
2157 formalp
= formalp
->next
;
2159 if (actualp
->type
!= T_UNKNOWN
&& actualp
->type
!= formaltype
) {
2160 fprintf(stderr
, "%s: argument to %s has the wrong type:\n",
2161 progname
, fp
->name
);
2162 showstring(stderr
, actualp
->string
);
2168 if (compileconcat(actualp
->string
, formaltype
) != 0)
2170 actualp
= actualp
->next
;
2172 putchar(fp
->isarray
? ']' : ')');
2177 int walkstring(struct string
*sp
, enum walkstringop op
, int tempno
) {
2178 struct stringlist
*lp
;
2181 for ( ; sp
!= NULL
; sp
= sp
->next
) {
2184 ap
= sp
->value
.array
;
2185 for (lp
= ap
->elements
; lp
!= NULL
; lp
= lp
->next
)
2186 tempno
= walkstring(lp
->string
, op
, tempno
);
2187 tempno
= walkstring(ap
->index
, op
, tempno
);
2188 ap
->tempno
= ++tempno
;
2191 if (simplearray(ap
)) {
2194 compilesimplearray(&ap
->type
, NULL
, tempno
, ap
);
2199 if (!simplearray(ap
))
2200 if (compilearray(ap
) != 0)
2207 case S_FUNCTIONCALL
:
2208 for (lp
= sp
->value
.functioncall
->args
; lp
!= NULL
; lp
= lp
->next
)
2209 tempno
= walkstring(lp
->string
, op
, tempno
);
2219 int compilearray(struct array
*ap
) {
2220 struct stringlist
*ep
;
2225 if (compileconcat(ap
->index
, T_INTEGER
) != 0)
2227 printf(") {\n"/*}*/);
2228 for (i
= 0, ep
= ap
->elements
; ep
!= NULL
; i
++, ep
= ep
->next
) {
2230 printf("case %d:\n", i
);
2232 if (compilecheckedstring(ap
->tempno
, ep
->string
, ap
->type
) != 0)
2244 void compilesimplearray(enum type
*tp
, char *name
, int num
, struct array
*ap
) {
2245 struct stringlist
*lp
;
2248 fixedlength
= (*tp
== T_INTEGER
) ? 0 : checkfixedlength(ap
);
2249 if (fixedlength
> 0)
2252 compiletype(stdout
, tp
);
2258 if (fixedlength
> 0)
2259 printf("[%d]", fixedlength
);
2260 printf(" = {\n"/*}*/);
2262 for (lp
= ap
->elements
; lp
!= NULL
; lp
= lp
->next
) {
2264 compilesimple(lp
->string
, lp
->type
);
2269 printf(/*{*/"};\n");
2273 void declarearray(struct array
*ap
) {
2275 compiletype(stdout
, &ap
->type
);
2276 compiletemp(ap
->tempno
);
2281 void compilebitstring(struct bits
*bp
) {
2285 printf("code & 0x%lx", bp
->mask
);
2287 printf(") >> %d", bp
->shift
);
2292 void compilebitsplice(struct bitsplice
*splicep
) {
2293 struct bitsplicebits
*bsp
;
2297 for (bsp
= splicep
->splice
; bsp
!= NULL
; bsp
= bsp
->next
) {
2300 if (bsp
->type
== S_PARAMETER
)
2301 putchar(bsp
->value
.arg
->name
);
2303 assert(bsp
->type
== S_BITSTRING
);
2304 if (bsp
->value
.mask
== 0)
2307 printf("(code & 0x%lx)", bsp
->value
.mask
);
2310 printf(" << %d", bsp
->shift
);
2311 else if (bsp
->shift
< 0)
2312 printf(" >> %d", -bsp
->shift
);
2314 if (splicep
->entry
.value
!= 0)
2315 printf("%s0x%lx", last
, splicep
->entry
.value
);
2320 int bitcount(bits x
) {
2323 for (nbits
= 0; x
!= 0; x
>>= 1) {
2331 bits
allbitsset(int nbits
) {
2332 return (nbits
== MAXBITS
) ? ~0 : (1 << nbits
) - 1;
2336 void findent(FILE *f
) {
2339 for (i
= 1; i
< indentation
; i
+= 2)
2341 if (i
== indentation
)
2351 void *xrealloc(char *oldp
, size_t size
) {
2357 p
= realloc(oldp
, size
);
2359 fprintf(stderr
, "%s: allocate of %d bytes failed: %s\n", progname
,
2360 (int) size
, strerror(errno
));
2367 void *xmalloc(size_t size
) {
2368 return xrealloc(NULL
, size
);
2372 void *xstrdup(char *s
) {
2374 size_t i
= strlen(s
) + 1;
2382 int prematureeof() {
2383 fprintf(stderr
, "%s: %s(%d): premature end of file\n", progname
, filename
,