Annotation of XNU/osfmk/ddb/makedis.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * @OSF_COPYRIGHT@
                     24:  */
                     25: /*
                     26:  * HISTORY
                     27:  * 
                     28:  * Revision 1.1.1.1  1998/09/22 21:05:48  wsanchez
                     29:  * Import of Mac OS X kernel (~semeria)
                     30:  *
                     31:  * Revision 1.1.1.1  1998/03/07 02:26:09  wsanchez
                     32:  * Import of OSF Mach kernel (~mburg)
                     33:  *
                     34:  * Revision 1.1.2.1  1997/03/27  18:46:52  barbou
                     35:  *     Created.
                     36:  *     [1997/03/27  13:58:42  barbou]
                     37:  *
                     38:  * $EndLog$
                     39:  */
                     40: 
                     41: /* makedis.c - make a disassembler. */
                     42: 
                     43: /*    ,
                     44:    By Eamonn McManus <[email protected]>, April 1995.
                     45:    Copyright 1995 by Eamonn McManus.  Non-commercial use is permitted.  */
                     46: 
                     47: /* DESCRIPTION
                     48:    
                     49:    This program generates a disassembler in C from a file describing the
                     50:    opcodes of the machine in question.  Lines in the description file are
                     51:    either comments beginning with #, or contain three fields, with the
                     52:    first two being terminated by space and the third containing the rest
                     53:    of the line.  Long logical lines can be split onto several physical
                     54:    lines by ending each one except the last with a \.  A logical line
                     55:    can also be split immediately after a |.  Unlike \, | is considered
                     56:    part of the logical line.  Leading spaces on continuation lines
                     57:    following either \ or | are ignored.
                     58: 
                     59:    Here is a concise description of the meanings of the three fields.
                     60:    Examples later will make it clearer what they are used for.
                     61: 
                     62:    The first field of the three is a function name.  This will produce
                     63:    a function or array of the same name in the C output, so it should
                     64:    not conflict with other identifiers or C keywords.  By default the
                     65:    function named returns a string (a (char *) in C), but if the first
                     66:    field is preceded by %, the function returns an unsigned long
                     67:    integer.
                     68: 
                     69:    The second field describes the arguments of the function.  It consists
                     70:    of two parts, either but not both of which may be omitted.  The first
                     71:    part is a string which is a bitmask describing the first argument of
                     72:    the function.  Each character of the string represents one bit,
                     73:    with the least significant bit being the last.  A character can be
                     74:    0 or 1, representing that constant value, or a letter, representing
                     75:    part of a bitfield.  A given bitfield consists of all of the
                     76:    contiguous bits containing the same letter.  Upper and lower case
                     77:    letters are considered different.
                     78: 
                     79:    The second part of the second field is a list of parameters
                     80:    describing the parameters of the function, or the parameters after
                     81:    the first if the bitfield part was present.  The list is contained
                     82:    in parentheses () and the individual parameters are separated by
                     83:    commas.  Spaces are not allowed.  Each parameter name is a single
                     84:    letter, optionally preceded by %.  The parameter is an unsigned
                     85:    long integer if % is present, otherwise a string.  Again, upper and
                     86:    lower case parameter names are different.
                     87: 
                     88:    The third field describes the value of the function.  If a bitmask
                     89:    is present in the second field and it contains constant bits (0s or
                     90:    1s), then the third field is the value of the function only in the
                     91:    case where its first argument contains matching values in those bit
                     92:    positions.  There can be many different lines naming the same
                     93:    function but with different bitpatterns.  The generated C code will
                     94:    arrange to return the value corresponding to the pattern that
                     95:    matches the actual first argument of the function when it is
                     96:    called.  This argument should not have bits set in positions beyond
                     97:    those present in the bitpattern.
                     98: 
                     99:    It is only allowed for two different lines to name the same function
                    100:    if there is a bitstring in the second field.  It is not allowed for
                    101:    two such lines to specify exactly the same constant bit values.  But
                    102:    it is allowed for a line to have all the same constant bit values as
                    103:    another plus some extra constant values.  In this case the more
                    104:    specific line applies when all of its constant bits match, and
                    105:    otherwise the less specific line applies.
                    106: 
                    107:    Apart from the contents of the bitstring, the second field must be
                    108:    identical on every line referring to a given function, and the
                    109:    bitstring must always be of the same length.
                    110: 
                    111:    For string-valued functions, the third field is the string value.
                    112:    For integer-valued functions, it is a C integer expression
                    113:    generating the value.  In both cases there may be several special
                    114:    values:
                    115: 
                    116:    - A $ followed by a single letter is replaced by the value of the
                    117:      argument or bitfield with that name.  The value of a bitfield is
                    118:      shifted as if that bitfield were in the least-significant bit
                    119:      position.  Thus, a single-bit field always has value 0 or 1.
                    120: 
                    121:    - A $ followed by the name of a function and an argument list in
                    122:      parentheses () is replaced by the value returned by the function
                    123:      with those arguments.  An integer value cannot be inserted into a
                    124:      string without being converted by a function, nor can a string
                    125:      value be used in an integer expression.
                    126: 
                    127:    - A $ followed by a bitstring enclosed in [] is replaced by the
                    128:      value of that bitstring.  The bitstring has the same syntax as in
                    129:      the second field, described above.  Each contiguous sequence of
                    130:      the same repeated letter in the bitstring is replaced by the
                    131:      value of the argument or bitfield-argument with that name,
                    132:      shifted into the appropriate position.
                    133: 
                    134:    - A list of strings, separated by |, enclosed in
                    135:      {}, and followed by an integer expression enclosed in [], is
                    136:      replaced by the string in the list whose number matches the value
                    137:      of the expression.  The first string in the list is numbered 0.
                    138:      If there is no string corresponding to the value of the
                    139:      expression, the behaviour is undefined.  The strings in the list
                    140:      may themselves contain $ or {} operations.
                    141: 
                    142:    - A \ followed by any character is replaced by that
                    143:      character, without regard to any meaning it may usually have.
                    144:      This is used to obtain strings containing characters such as
                    145:      {, $, or \.  The use of backslash to split long logical
                    146:      lines takes precedence over this use, so \\ should not appear
                    147:      at the end of a line.
                    148: 
                    149:    The third field may also be a lone colon ":", in which case the
                    150:    function is assumed to be defined externally and only a function
                    151:    declaration (prototype) is generated.
                    152: 
                    153: 
                    154:    EXAMPLES
                    155: 
                    156:    Here are some examples from the description file for the Z80
                    157:    microprocessor.  This processor has 8-bit opcodes which are
                    158:    disassembled by a generated function "inst" which looks like this:
                    159: 
                    160:    typedef unsigned long bits;
                    161:    char *inst(bits code) {...}
                    162: 
                    163:    The simplest sort of line in the description file is one that looks
                    164:    like this:
                    165: 
                    166:    inst    01110110        halt
                    167: 
                    168:    The first field names the function, "inst".  The second field
                    169:    implies that that function has exactly one argument which is an
                    170:    integer, and that this line specifies the value of the function
                    171:    when this integer has the binary value 01110110 (hex 0x76).  This
                    172:    value will be the string "halt".
                    173: 
                    174:    A more complex line is one looking like this:
                    175: 
                    176:    inst    001aa111        {daa|cpl|scf|ccf}[$a]
                    177: 
                    178:    This line is compatible with the previous one, because it has the
                    179:    same number of bits and the constant bits are different.  It
                    180:    specifies the value of inst when its argument looks like
                    181:    001aa111, i.e., for the binary values
                    182:    00100111,
                    183:    00101111,
                    184:    00110111, and
                    185:    00111111.  The value of $a for these four values will be
                    186:    respectively binary 00, 01, 10, 11, i.e., 0 to 3.  The
                    187:    corresponding values of the inst function will be "daa", "cpl",
                    188:    "scf", and "ccf".
                    189: 
                    190:    The description defines a helper function "reg8" like this:
                    191: 
                    192:    reg8    rrr             {b|c|d|e|h|l|(hl)|a}[$r]
                    193: 
                    194:    This simply selects one of the eight strings between {} depending
                    195:    on the value of the argument, which is assumed to be a three-bit
                    196:    value.  This could just as easily have been written:
                    197: 
                    198:    reg8    (%r)            {b|c|d|e|h|l|(hl)|a}[$r]
                    199: 
                    200:    The generated C code is the same -- in each case makedis realises
                    201:    that the function can be represented by an array rather than
                    202:    compiling a C function.
                    203: 
                    204:    The reg8 function is used in lines like this one:
                    205: 
                    206:    inst    01rrrsss        ld $reg8($r),$reg8($s)
                    207: 
                    208:    Thus if the argument to inst is
                    209:           01010011
                    210:    then $r is 010 (2) and $s is 011 (3).  Since reg8(2) is "d" and
                    211:    reg8(3) is "e", the value of inst with this argument will be the
                    212:    string "ld d,e".
                    213: 
                    214:    Note that the opcode for "halt" given above matches this pattern,
                    215:    but because the bitpattern for "halt" is more specific (has more
                    216:    constant bits) it is the one chosen when the argument is 01110110.
                    217: 
                    218:    The description also uses an external C function "hexprint" defined
                    219:    like this:
                    220: 
                    221:    char *hexprint(bits digits, bits n) {
                    222:        char *p = dis_alloc(digits + 1);
                    223:        sprintf(p, "%0*lx", (int) digits, n);
                    224:        return p;
                    225:    }
                    226: 
                    227:    The value of this function is a string containing the number n
                    228:    spelt out in hex with "digits" digits.  In the description
                    229:    file this function is declared like this:
                    230: 
                    231:    hexprint  (%w,%n)       :
                    232: 
                    233:    The names of the parameters are not important in this case as long
                    234:    as they are letters and are different from each other.
                    235: 
                    236:    The hexprint function is used in lines like this one:
                    237: 
                    238:    inst    11vvv111        rst $hexprint(2,$v << 3)
                    239: 
                    240:    If the argument to inst is
                    241:           11011111
                    242:    then $v is 011 (3) and the arguments to hexprint are 2 and (3 << 3),
                    243:    i.e., 0x18.  So the value of inst with this argument will be the
                    244:    string "rst 18".
                    245: 
                    246:    Instead of writing $v << 3, it would be possible to write
                    247:    $[00vvv000].  For instance when $v is binary 011, this becomes
                    248:      00011000.  The leading 0s could be omitted.
                    249: 
                    250:    The $[...] operation is particularly useful for moving bits around.
                    251:    For instance, the HP PA-RISC opcodes contain bits assigned to
                    252:    apparently random parts of the instruction word.  One of the helper
                    253:    functions in its description file looks like this:
                    254: 
                    255:    im21l aaaaabbccddddddddddde l'$hex($[edddddddddddbbaaaaacc00000000000])
                    256: 
                    257:    So    111110011000000000001 produces 10000000000000111111100000000000.
                    258: 
                    259:    The $[...] operation can also be used to spell out binary constants,
                    260:    since C has no syntax for this.
                    261: 
                    262: 
                    263:    ...More to come...  */
                    264: 
                    265: /* To do:
                    266:    - More error detection, e.g., bitstring or arg not used in entry.
                    267:    - Better error recovery -- nearly all errors are currently fatal.
                    268:    - Clean up type handling, which is somewhat haphazard.  It works but there
                    269:      is stuff that is surely redundant.
                    270:    - Make generated functions void by default, with $ prefix to indicate
                    271:      string-value.  In a void function, instead of returning a string (or
                    272:      integer) it would be output via a user-supplied function.
                    273:    - Further optimise and tidy generated code, e.g.: arrays of one-character
                    274:      strings could be replaced by arrays of characters; switches with just
                    275:      one case could be replaced by ifs.
                    276:  */
                    277: 
                    278: #include <assert.h>
                    279: #include <ctype.h>
                    280: #include <errno.h>
                    281: #include <limits.h>
                    282: #include <stdio.h>
                    283: #include <stdlib.h>
                    284: #include <string.h>
                    285: 
                    286: #ifndef        LONG_BIT
                    287: #define LONG_BIT       (CHAR_BIT * sizeof (long))
                    288: #endif /* LONG_BIT */
                    289: 
                    290: #define MAXfunction 32         /* Max function name length. */
                    291: #define MAXBITS LONG_BIT       /* Max bitstring length. */
                    292: typedef unsigned long bits;
                    293: enum type {T_ERROR, T_UNKNOWN, T_INTEGER, T_STRING};
                    294: const char *const typename[] = {"error", "unknown", "integer", "string"};
                    295: enum walkstringop {COUNTARRAYS, DECLAREARRAYS, COMPILEARRAYS};
                    296: char *bitstype = "unsigned long";
                    297: 
                    298: int maxfunctionname, maxargwidth;
                    299: char *progname = "makedis";
                    300: char **global_argv;
                    301: char *filename;
                    302: char *headerfilename;
                    303: FILE *headerfile;
                    304: int lineno;
                    305: int indentation;
                    306: int debug, dump, warnings;
                    307: 
                    308: /* componentbits has a 1 bit for every possible number of strings we may want
                    309:    to concatenate together at some stage.  A separate C function is compiled
                    310:    for each such case.  */
                    311: bits componentbits;
                    312: 
                    313: 
                    314: struct entry;
                    315: struct arg;
                    316: struct string;
                    317: struct functioncall;
                    318: struct array;
                    319: struct bits;
                    320: struct bitsplice;
                    321: 
                    322: 
                    323: int main(int argc, char **argv);
                    324: int makedis(FILE *f, char *fname);
                    325: struct function *findfunction(char *function);
                    326: int parseextern(struct function *fp, FILE *f);
                    327: struct function *makefunction(char *function);
                    328: int parsebits(struct function *fp, char *bitstring, int nbits);
                    329: int parseentrybits(struct entry *ep, char *bitstring, int nbits, int issplice);
                    330: int parsecontrol(char *name, char *value);
                    331: int parseargs(struct function *fp, FILE *f, int *cp);
                    332: int parsestring(struct function *fp, char *str);
                    333: enum type makestring(struct function *fp, struct string **stringlink,
                    334:                     char **stringp, char *magic, enum type targettype);
                    335: int parsedollar(struct function *fp, char **stringp, struct string *sp);
                    336: int parsebitsplice(struct function *fp, char *bitstring, int nbits,
                    337:                   struct string *sp);
                    338: int findvariable(struct function *fp, int name, struct string *sp);
                    339: int parsefunctioncall(struct function *fp, char *start, char **stringp,
                    340:                      struct string *sp);
                    341: int parsearray(struct function *fp, char **stringp, struct string *sp,
                    342:               enum type t);
                    343: void dumpfunctions(void);
                    344: void dumpfunction(struct function *fp);
                    345: void showentry(FILE *f, struct function *fp, struct entry *ep, bits highlight);
                    346: void showbits(FILE *f, struct entry *ep, int nbits, bits highlight);
                    347: void showargs(FILE *f, struct arg *ap, int fieldwidth);
                    348: void showstring(FILE *f, struct string *sp);
                    349: void showstringelement(FILE *f, struct string *sp);
                    350: void showfunctioncall(FILE *f, struct functioncall *fcp);
                    351: void showarray(FILE *f, struct array *ap);
                    352: int outputfunctions(void);
                    353: void outputidentity(FILE *f);
                    354: int outputdeclarations(void);
                    355: void outputconcats(void);
                    356: void outputconcat(int n);
                    357: void outputconcatheader(FILE *f, int n);
                    358: void findarrays(void);
                    359: int checkfixedlength(struct array *ap);
                    360: int outputfunction(struct function *fp);
                    361: void functionarray(struct function *fp);
                    362: void functionheader(FILE *f, struct function *fp);
                    363: int simplearray(struct array *ap);
                    364: void compiletype(FILE *f, enum type *tp);
                    365: int functionswitch(struct function *fp, bits mask, bits value);
                    366: int compilestring(int assignto, struct string *sp, enum type type);
                    367: int compilecheckedstring(int assignto, struct string *sp, enum type type);
                    368: void compileassign(int assignto);
                    369: void compiletemp(int tempno);
                    370: void compiletext(char *s);
                    371: int compileconcat(struct string *sp, enum type type);
                    372: int compilenull(enum type type);
                    373: int compilesimple(struct string *sp, enum type type);
                    374: int compilearrayref(struct array *ap);
                    375: int compilefunctioncall(struct string *sp);
                    376: int walkstring(struct string *sp, enum walkstringop op, int tempno);
                    377: int compilearray(struct array *ap);
                    378: void compilesimplearray(enum type *tp, char *name, int num, struct array *ap);
                    379: void declarearray(struct array *ap);
                    380: void compilebitstring(struct bits *bp);
                    381: void compilebitsplice(struct bitsplice *splicep);
                    382: int bitcount(bits x);
                    383: bits allbitsset(int nbits);
                    384: void findent(FILE *f);
                    385: void indent(void);
                    386: void *xrealloc(char *oldp, size_t size);
                    387: void *xmalloc(size_t size);
                    388: void *xstrdup(char *s);
                    389: int prematureeof(void);
                    390: 
                    391: 
                    392: int main(int argc, char **argv) {
                    393:     int i;
                    394:     FILE *f;
                    395: 
                    396:     global_argv = argv;
                    397:     if (argc > 0)
                    398:        progname = argv[0];
                    399:     for (i = 1; i < argc && argv[i][0] == '-'; i++) {
                    400:        switch (argv[i][1]) {
                    401:        case 'h':
                    402:            if (++i >= argc)
                    403:                goto Usage;
                    404:            headerfilename = argv[i]; break;
                    405:        case 'd':
                    406:            debug = 1; break;
                    407:        case 'D':
                    408:            dump = 1; break;
                    409:        case 'w':
                    410:            warnings = 1; break;
                    411:        default:
                    412: Usage:
                    413:            fprintf(stderr, "Usage: %s [file]\n", progname);
                    414:            return 1;
                    415:        }
                    416:     }
                    417:     if (i == argc)
                    418:        return makedis(stdin, "<stdin>");
                    419:     if (i + 1 != argc)
                    420:        goto Usage;
                    421:     if ((f = fopen(argv[i], "r")) == NULL) {
                    422:        fprintf(stderr, "%s: %s: %s\n", progname, argv[i], strerror(errno));
                    423:        return 1;
                    424:     }
                    425:     return makedis(f, argv[i]);
                    426: }
                    427: 
                    428: 
                    429: int makedis(FILE *f, char *fname) {
                    430:     int c, i;
                    431:     char function[MAXfunction], bitstring[MAXBITS];
                    432:     static char *string = NULL;
                    433:     int stringlen = 0;
                    434:     struct function *fp;
                    435: 
                    436:     filename = fname;
                    437:     lineno = 1;
                    438:     /* Loop for every line in the description. */
                    439:     while (1) {
                    440:        /* Ignore initial spaces and newlines. */
                    441:        while (isspace(c = getc(f)))
                    442:            if (c == '\n')
                    443:                lineno++;
                    444:        if (c == EOF)
                    445:            break;
                    446: 
                    447:        /* Ignore comments.  # only allowed at start of line. */
                    448:        if (c == '#') {
                    449:            while ((c = getc(f)) != '\n')
                    450:                if (c == EOF)
                    451:                    return prematureeof();
                    452:            lineno++;
                    453:            continue;
                    454:        }
                    455: 
                    456:        /* Read function name, terminated by space. */
                    457:        for (i = 0; i < sizeof function && !isspace(c); i++, c = getc(f)) {
                    458:            if (c == EOF)
                    459:                return prematureeof();
                    460:            function[i] = c;
                    461:        }
                    462:        if (i >= sizeof function) {
                    463:            fprintf(stderr, "%s: %s(%d): function name is too long: %.*s\n",
                    464:                    progname, filename, lineno, i, function);
                    465:            return 1;
                    466:        }
                    467:        function[i] = '\0';
                    468: 
                    469:        /* Skip to next field.  */
                    470:        while (isspace(c) && c != '\n')
                    471:            c = getc(f);
                    472: 
                    473:        /* If not a control statement, read bitstring and/or arguments. */
                    474:        if (function[0] == ':')
                    475:            fp = 0;     /* Silence gcc. */
                    476:        else {
                    477:            fp = makefunction(function);
                    478:            if (fp == NULL)
                    479:                return 1;
                    480: 
                    481:            /* Read optional bitstring. */
                    482:            for (i = 0; i < sizeof bitstring && isalnum(c); i++, c = getc(f)) {
                    483:                if (c == EOF)
                    484:                    return prematureeof();
                    485:                bitstring[i] = c;
                    486:            }
                    487:            if (isalnum(c)) {
                    488:                fprintf(stderr, "%s: %s(%d): bit string is too long: %.*s\n",
                    489:                        progname, filename, lineno, i, bitstring);
                    490:                return 1;
                    491:            }
                    492:            if (parsebits(fp, bitstring, i) != 0)
                    493:                return 1;
                    494: 
                    495:            /* Read optional arguments. */
                    496:            if (parseargs(fp, f, &c) != 0)
                    497:                return 1;
                    498: 
                    499:            /* Skip to next field. */
                    500:            while (isspace(c) && c != '\n')
                    501:                c = getc(f);
                    502: 
                    503:            /* : indicates an external (C) function. */
                    504:            if (c == ':') {
                    505:                if (parseextern(fp, f) != 0)
                    506:                    return 1;
                    507:                continue;
                    508:            }
                    509:        }
                    510: 
                    511:        /* Read associated text. */
                    512:        i = 0;
                    513:        while (1) {
                    514:            for ( ; c != '\n'; i++, c = getc(f)) {
                    515:                if (c == EOF)
                    516:                    return prematureeof();
                    517:                if (i >= stringlen) {
                    518:                    stringlen = stringlen * 2 + 16;
                    519:                    string = xrealloc(string, stringlen);
                    520:                }
                    521:                string[i] = c;
                    522:            }
                    523:            lineno++;
                    524:            if (i > 0) {
                    525:                switch (string[i - 1]) {
                    526:                case '\\':
                    527:                    i--;
                    528:                    /* Fall in... */
                    529:                case '|':
                    530:                    while (isspace(c = getc(f)) && c != '\n') ;
                    531:                    continue;
                    532:                }
                    533:            }
                    534:            break;
                    535:        }
                    536:        if (i >= stringlen) {
                    537:            stringlen = stringlen * 2 + 16;
                    538:            string = xrealloc(string, stringlen);
                    539:        }
                    540:        string[i] = '\0';
                    541: 
                    542:        /* Parse the line just read. */
                    543:        if (function[0] == ':') {
                    544:            if (parsecontrol(function + 1, string) != 0)
                    545:                return 1;
                    546:        } else {
                    547:            if (parsestring(fp, string) != 0)
                    548:                return 1;
                    549:        }
                    550:     }
                    551:     if (dump)
                    552:        dumpfunctions();
                    553:     return outputfunctions();
                    554: }
                    555: 
                    556: 
                    557: /* A function in the description file.  nbits and nargs are -1 until the
                    558:    real values are known.  */
                    559: struct function {
                    560:     struct function *next;
                    561:     char *name;
                    562:     enum type type;
                    563:     int nbits;         /* Number of bits in the bitpattern, 0 if none. */
                    564:     int nargs;         /* Number of (x,y,...) parameters, 0 if none. */
                    565:     char isarray;      /* Will be represented by a C array. */
                    566:     int fixedlength;   /* If a C array, will be a char [][N] not a char *[]. */
                    567:     struct entry *first, *last;
                    568:                        /* Links to the value(s) supplied. */
                    569:     struct arg *args;  /* List of (x,y,...) names and types. */
                    570: };
                    571: struct function *functions;
                    572: 
                    573: 
                    574: /* Find the function with the given name.  If not found, create a structure
                    575:    for it, fill it out with a template, and return that.  */
                    576: struct function *findfunction(char *name) {
                    577:     struct function *fp;
                    578: 
                    579:     for (fp = functions; fp != NULL; fp = fp->next) {
                    580:        if (strcmp(fp->name, name) == 0)
                    581:            return fp;
                    582:     }
                    583:     if (strlen(name) > maxfunctionname)
                    584:        maxfunctionname = strlen(name);
                    585:     fp = xmalloc(sizeof *fp);
                    586:     fp->next = functions;
                    587:     functions = fp;
                    588:     fp->name = xstrdup(name);
                    589:     fp->type = T_UNKNOWN;
                    590:     fp->nbits = fp->nargs = -1;                /* nbits will be set correctly later. */
                    591:     fp->isarray = 0;
                    592:     fp->first = fp->last = NULL;
                    593:     return fp;
                    594: }
                    595: 
                    596: 
                    597: /* Parse an external (C) function declaration.  This will look something like:
                    598:        malloc (%s) :
                    599:    We're called just after seeing the ':'.
                    600:    Return 0 if parsing is successful, 1 otherwise.  */
                    601: int parseextern(struct function *fp, FILE *f) {
                    602:     int c;
                    603: 
                    604:     if ((c = getc(f)) != '\n') {
                    605:        fprintf(stderr,
                    606:                "%s: %s(%d): extern declaration should be a lone `:'\n",
                    607:                progname, filename, lineno);
                    608:        return 1;
                    609:     }
                    610:     if (fp->nbits != 0) {
                    611:        fprintf(stderr,
                    612:                "%s: %s(%d): extern functions should not have bitstrings\n",
                    613:                progname, filename, lineno);
                    614:        return 1;
                    615:     }
                    616:     free(fp->first);
                    617:     fp->first = fp->last = NULL;
                    618:     return 0;
                    619: }
                    620: 
                    621: 
                    622: /* A value supplied for a function (the third field in a description line).
                    623:    In general there can be any number of such values, differing in the
                    624:    bitpattern supplied.  The mask and value fields describe the constant
                    625:    bits in the bitpattern: mask indicates which bits they are and value
                    626:    indicates the values of those bits.  So this entry matches
                    627:    ((x & mask) == value).  */
                    628: struct entry {
                    629:     struct entry *next;
                    630:     bits mask, value;
                    631:     struct bits *bits;         /* List of named bitfields. */
                    632:     struct string *string;     /* Value of function when bitpattern matched. */
                    633:     char done;                 /* This entry has already been compiled. */
                    634: };
                    635: 
                    636: 
                    637: /* We've just seen a definition of function "name".  Make a structure for it
                    638:    if necessary, and a template entry that will describe the value given here.
                    639:    */
                    640: struct function *makefunction(char *name) {
                    641:     struct function *fp;
                    642:     struct entry *ep = xmalloc(sizeof *ep);
                    643:     enum type type;
                    644: 
                    645:     if (name[0] == '%') {
                    646:        name++;
                    647:        type = T_INTEGER;
                    648:     } else
                    649:        type = T_STRING;
                    650:     fp = findfunction(name);
                    651:     if (fp->type == T_UNKNOWN)
                    652:        fp->type = type;
                    653:     else if (fp->type != type) {
                    654:        fprintf(stderr, "%s: %s(%d): function %s previously declared as %s, "
                    655:                        "here as %s\n", progname, filename, lineno, name,
                    656:                        typename[fp->type], typename[type]);
                    657:        return NULL;
                    658:     }
                    659:     ep->next = NULL;
                    660:     ep->bits = NULL;
                    661:     ep->done = 0;
                    662:     if (fp->first != NULL)
                    663:        fp->last->next = ep;
                    664:     else
                    665:        fp->first = ep;
                    666:     fp->last = ep;
                    667:     return fp;
                    668: }
                    669: 
                    670: 
                    671: /* A named bitfield within the bitpattern of a function entry, or within a
                    672:    $[...] bitsplice.  The mask covers the bitfield and the shift says how
                    673:    many 0 bits there are after the last 1 in the mask.  */
                    674: struct bits {
                    675:     struct bits *next;
                    676:     int shift;
                    677:     bits mask;
                    678:     char name;
                    679: };
                    680: 
                    681: 
                    682: /* Parse the bitstring supplied for the given function.  nbits says how many
                    683:    bits there are; it can legitimately be 0.  Return value is 0 on success.  */
                    684: int parsebits(struct function *fp, char *bitstring, int nbits) {
                    685:     if (fp->nbits < 0)
                    686:        fp->nbits = nbits;
                    687:     else if (fp->nbits != nbits) {
                    688:        fprintf(stderr, "%s: %s(%d): bit string of length %d;\n",
                    689:                progname, filename, lineno, nbits);
                    690:        fprintf(stderr, "  function %s has bit strings of length %d\n",
                    691:                fp->name, fp->nbits);
                    692:        return 1;
                    693:     }
                    694:     return parseentrybits(fp->last, bitstring, nbits, 0);
                    695: }
                    696: 
                    697: 
                    698: /* Parse a bitstring that is the pattern for a function entry or that is in a
                    699:    $[...] bitsplice.  Put the result in ep.  Return value is 0 on success.  */
                    700: int parseentrybits(struct entry *ep, char *bitstring, int nbits, int issplice) {
                    701:     int i, j;
                    702:     char bit;
                    703:     bits mask, value, entrymask;
                    704:     struct bits *bp;
                    705: 
                    706:     mask = value = 0;
                    707:     for (i = 0; i < nbits; i++) {
                    708:        bit = bitstring[nbits - 1 - i];
                    709:        switch (bit) {
                    710:        case '1':
                    711:            value |= 1 << i;
                    712:            /* Fall in... */
                    713:        case '0':
                    714:            mask |= 1 << i;
                    715:            continue;
                    716:        }
                    717:        if (!isalpha(bit)) {
                    718:            fprintf(stderr, "%s: %s(%d): invalid character in bitstring: %c\n",
                    719:                    progname, filename, lineno, bit);
                    720:            return 1;
                    721:        }
                    722:        if (!issplice) {
                    723:            for (bp = ep->bits; bp != NULL; bp = bp->next) {
                    724:                if (bp->name == bit) {
                    725:                    fprintf(stderr,
                    726:                            "%s: %s(%d): bitstring name %c used twice\n",
                    727:                            progname, filename, lineno, bit);
                    728:                    return 1;
                    729:                }
                    730:            }
                    731:        }
                    732:        entrymask = 1 << i;
                    733:        for (j = i + 1; j < nbits && bitstring[nbits - 1 - j] == bit; j++)
                    734:            entrymask |= 1 << j;
                    735:        bp = xmalloc(sizeof *bp);
                    736:        bp->shift = i;
                    737:        bp->mask = entrymask;
                    738:        bp->name = bit;
                    739:        bp->next = ep->bits;
                    740:        ep->bits = bp;
                    741:        i = j - 1;
                    742:     }
                    743:     ep->mask = mask;
                    744:     ep->value = value;
                    745:     return 0;
                    746: }
                    747: 
                    748: 
                    749: /* Parse a control line.  This looks something like:
                    750:    :bitstype unsigned int
                    751:    in which case we will be called with name "bitstype" and
                    752:    value "unsigned int".  */
                    753: int parsecontrol(char *name, char *value) {
                    754:     if (strcmp(name, "bitstype") == 0)
                    755:        bitstype = xstrdup(value);
                    756:     else {
                    757:        fprintf(stderr, "%s: %s(%d): unrecognised control keyword %s\n",
                    758:                progname, filename, lineno, name);
                    759:        return 1;
                    760:     }
                    761:     return 0;
                    762: }
                    763: 
                    764: 
                    765: /* A parameter to a function, e.g., x in:
                    766:    %f aaa(%x) $a + $x  */
                    767: struct arg {
                    768:     struct arg *next;
                    769:     enum type type;
                    770:     char name;
                    771: };
                    772: 
                    773: 
                    774: /* Parse the parameters (x,y,...) to a function and put the result in fp.
                    775:    The entry that is being built is fp->last.  cp points to the opening
                    776:    (; if it does not point to a ( then there are no parameters.  If
                    777:    this is the first entry for the function, fp->nargs will be -1 and
                    778:    we will build up an argument list.  Otherwise, fp->nargs will be
                    779:    >= 0 and we will only check that the arguments here are consistent
                    780:    with what went before.  Return value is 0 on success.  */
                    781: int parseargs(struct function *fp, FILE *f, int *cp) {
                    782:     struct arg **arglink, *ap;
                    783:     struct bits *bp;
                    784:     int nargs, width;
                    785:     char name;
                    786:     enum type t;
                    787: 
                    788:     arglink = &fp->args;
                    789:     width = nargs = 0;
                    790:     if (*cp == '(') {
                    791:        *cp = getc(f);
                    792:        if (*cp != ')') {
                    793:            width = 1;
                    794:            while (1) {
                    795:                nargs++;
                    796:                width += 2;
                    797:                if (fp->nargs >= 0 && nargs > fp->nargs) {
                    798:                    fprintf(stderr,
                    799:                            "%s: %s(%d): %d arg(s) instead of %d for %s\n",
                    800:                            progname, filename, lineno, nargs, fp->nargs,
                    801:                            fp->name);
                    802:                    return 1;
                    803:                }
                    804:                t = T_STRING;
                    805:                if (*cp == '%') {
                    806:                    width++;
                    807:                    t = T_INTEGER;
                    808:                    *cp = getc(f);
                    809:                }
                    810:                name = *cp;
                    811:                if (!isalpha(name)) {
                    812:                    fprintf(stderr,
                    813:                            "%s: %s(%d): argument should be letter: %c\n",
                    814:                            progname, filename, lineno, name);
                    815:                    return 1;
                    816:                }
                    817:                for (bp = fp->last->bits; bp != NULL; bp = bp->next) {
                    818:                    if (bp->name == name) {
                    819:                        fprintf(stderr,
                    820:                                "%s: %s(%d): %c is a bitstring and an arg\n",
                    821:                                progname, filename, lineno, name);
                    822:                        return 1;
                    823:                    }
                    824:                }
                    825:                if (fp->nargs >= 0) {
                    826:                    if ((*arglink)->name != name) {
                    827:                        fprintf(stderr,
                    828:                                "%s: %s(%d): arg %d of %s is %c not %c\n",
                    829:                                progname, filename, lineno, nargs, fp->name,
                    830:                                (*arglink)->name, name);
                    831:                        return 1;
                    832:                    }
                    833:                    if ((*arglink)->type != t) {
                    834:                        fprintf(stderr,
                    835:                                "%s: %s(%d): arg %c of %s: inconsistent type\n",
                    836:                                progname, filename, lineno, name, fp->name);
                    837:                        return 1;
                    838:                    }
                    839:                } else {
                    840:                    for (ap = fp->args; ap != *arglink; ap = ap->next) {
                    841:                        if (ap->name == name) {
                    842:                            fprintf(stderr,
                    843:                                    "%s: %s(%d): argument name %c used twice\n",
                    844:                                    progname, filename, lineno, name);
                    845:                            return 1;
                    846:                        }
                    847:                    }
                    848:                    *arglink = xmalloc(sizeof **arglink);
                    849:                    (*arglink)->name = name;
                    850:                    (*arglink)->type = t;
                    851:                }
                    852:                arglink = &(*arglink)->next;
                    853:                *cp = getc(f);
                    854:                if (*cp == ')')
                    855:                    break;
                    856:                if (*cp != ',') {
                    857:                    fprintf(stderr,
                    858:                            "%s: %s(%d): bad character in argument list: %c\n"
                    859:                            "  (arguments must be single letters)\n",
                    860:                            progname, filename, lineno, *cp);
                    861:                    return 1;
                    862:                }
                    863:                *cp = getc(f);
                    864:            }
                    865:        }
                    866:        *cp = getc(f);
                    867:     }
                    868:     if (fp->nargs < 0) {
                    869:        fp->nargs = nargs;
                    870:        width += fp->nbits;
                    871:        if (width > maxargwidth)
                    872:            maxargwidth = width;
                    873:     } else if (fp->nargs != nargs) {
                    874:        fprintf(stderr, "%s: %s(%d): argument list of length %d;\n",
                    875:                progname, filename, lineno, nargs);
                    876:        fprintf(stderr, "  function %s has argument lists of length %d\n",
                    877:                fp->name, fp->nargs);
                    878:        return 1;
                    879:     }
                    880:     *arglink = NULL;
                    881:     return 0;
                    882: }
                    883: 
                    884: 
                    885: /* Parse the string describing the value of this entry for our
                    886:    function.  Return 0 on success.  */
                    887: int parsestring(struct function *fp, char *str) {
                    888:     enum type t;
                    889: 
                    890:     t = makestring(fp, &fp->last->string, &str, NULL, fp->type);
                    891:     if (t == T_ERROR)
                    892:        return 1;
                    893:     if (fp->type != t && t != T_UNKNOWN) {
                    894:        fprintf(stderr, "%s: %s(%d): function %s has inconsistent types\n",
                    895:                progname, filename, lineno, fp->name);
                    896:        return 1;
                    897:     }
                    898:     return 0;
                    899: }
                    900: 
                    901: 
                    902: /* A parsed representation of the whole string describing a value of a
                    903:    function, or certain strings within that (e.g., array indices).  This is a
                    904:    linked list of substrings whose type is given by the type field.  */
                    905: struct string {
                    906:     struct string *next;
                    907:     enum elementtype {
                    908:        S_TEXT, S_BITSTRING, S_BITSPLICE, S_PARAMETER, S_FUNCTIONCALL, S_ARRAY
                    909:     } type;
                    910:     union value {      /* The fields here correspond to the enum values. */
                    911:        char *text;                             /* plain text */
                    912:        struct bits *bits;                      /* $x where x is a bitfield */
                    913:        struct bitsplice *bitsplice;            /* $[...] */
                    914:        struct arg *parameter;                  /* $x where x is a parameter */
                    915:        struct functioncall *functioncall;      /* $func(...) */
                    916:        struct array *array;                    /* {...}[...] */
                    917:     } value;
                    918: };
                    919: 
                    920: /* The representation of a function call $func(...) in the description of a
                    921:    function value.  */
                    922: struct functioncall {
                    923:     struct function *function;
                    924:     struct stringlist *args;
                    925: };
                    926: 
                    927: /* The representation of an array selection {...|...}[...] in the description
                    928:    of a function value.  tempno is used when constructing a C variable name
                    929:    that will contain the strings or numbers in an array.  */
                    930: struct array {
                    931:     struct string *index;              /* what's between [...] */
                    932:     struct stringlist *elements;       /* what's between {...} */
                    933:     enum type type;                    /* the type of each element */
                    934:     int tempno;        
                    935: };
                    936: 
                    937: /* A list of strings, being the list of arguments in a function call or the
                    938:    list of elements of an array.  This is a linked list of linked lists.  */
                    939: struct stringlist {
                    940:     struct stringlist *next;
                    941:     enum type type;
                    942:     struct string *string;
                    943: };
                    944: 
                    945: 
                    946: /* The following are the only characters with special meaning at the top level
                    947:    of parsing of a function value.  When parsing arrays or function calls,
                    948:    other characters become special.  */
                    949: #define MAKESTRING_MAGIC "${"/*}*/
                    950: 
                    951: 
                    952: /* Parse a function return-value string or substring and make a struct string
                    953:    list for it.  The string starts at *stringp and ends at a \0 or at any
                    954:    character in the `magic' string other than { or $.  *stringp is updated
                    955:    to point to the terminating character.  The parsed representation is put
                    956:    at *stringlink.  `fp' is the function whose return value is being parsed.
                    957:    `targettype' is the expected type of the result, if known.
                    958:    The return value is the actual type.  */
                    959: enum type makestring(struct function *fp, struct string **stringlink,
                    960:                     char **stringp, char *magic, enum type targettype) {
                    961:     char *p, *q;
                    962:     struct string *sp, **firststringlink;
                    963:     int n, components;
                    964:     int parenlevel = 0;
                    965:     enum type t = targettype, newt;
                    966: 
                    967:     if (magic == NULL)
                    968:        magic = MAKESTRING_MAGIC;
                    969:     p = *stringp;
                    970:     firststringlink = stringlink;
                    971:     components = 0;
                    972:     while (*p != '\0') {
                    973:        sp = xmalloc(sizeof *sp);
                    974:        q = p;
                    975:        n = 0;
                    976:        do {
                    977:            if (strchr(magic, *q) != NULL) {
                    978:                if (*q != ')' || parenlevel == 0)
                    979:                    break;
                    980:            }
                    981:            switch (*q) {
                    982:            case '(':
                    983:                parenlevel++; break;
                    984:            case ')':
                    985:                parenlevel--; break;
                    986:            case '\\':
                    987:                if (q[1] != '\0')
                    988:                    q++;
                    989:                break;
                    990:            }
                    991:            n++;
                    992:        } while (*++q != '\0');
                    993:        if (n > 0) {
                    994:            sp->type = S_TEXT;
                    995:            sp->value.text = q = xmalloc(n + 1);
                    996:            do {
                    997:                if (*p == '\\')
                    998:                    p++;
                    999:                *q++ = *p++;
                   1000:            } while (--n > 0);
                   1001:            *q = '\0';
                   1002:            newt = t;
                   1003:        } else if (*p == '$') {
                   1004:            if (parsedollar(fp, &p, sp) != 0)
                   1005:                return T_ERROR;
                   1006:            switch (sp->type) {
                   1007:            case S_BITSTRING:
                   1008:            case S_BITSPLICE:
                   1009:                newt = T_INTEGER;
                   1010:                break;
                   1011:            case S_PARAMETER:
                   1012:                newt = sp->value.parameter->type;
                   1013:                break;
                   1014:            case S_FUNCTIONCALL:
                   1015:                newt = sp->value.functioncall->function->type;
                   1016:                break;
                   1017:            default:
                   1018:                fprintf(stderr, "makestring type %d\n", sp->type);
                   1019:                abort();
                   1020:            }
                   1021:        } else if (*p == '{'/*}*/) {
                   1022:            if (parsearray(fp, &p, sp, t) != 0)
                   1023:                return T_ERROR;
                   1024:            newt = sp->value.array->type;
                   1025:        } else {
                   1026:            free(sp);
                   1027:            break;
                   1028:        }
                   1029:        if (t == T_UNKNOWN)
                   1030:            t = newt;
                   1031:        else if (newt != T_UNKNOWN && t != newt) {
                   1032:            if (stringlink == firststringlink) {
                   1033:                fprintf(stderr, "%s: %s(%d): expected %s type:\n", progname,
                   1034:                        filename, lineno, typename[t]);
                   1035:                showstringelement(stderr, sp);
                   1036:                return T_ERROR;
                   1037:            }
                   1038:            *stringlink = NULL;
                   1039:            fprintf(stderr, "%s: %s(%d): mixed types in string:\n",
                   1040:                    progname, filename, lineno);
                   1041:            showstring(stderr, *firststringlink);
                   1042:            fprintf(stderr, " -- %s\n", typename[t]);
                   1043:            showstringelement(stderr, sp);
                   1044:            fprintf(stderr, " -- %s\n", typename[newt]);
                   1045:            return T_ERROR;
                   1046:        }
                   1047:        *stringlink = sp;
                   1048:        stringlink = &sp->next;
                   1049:        components++;
                   1050:     }
                   1051:     *stringlink = NULL;
                   1052:     *stringp = p;
                   1053:     if (components >= MAXBITS) {
                   1054:        fprintf(stderr, "%s: %s(%d): excessively complicated string\n",
                   1055:                progname, filename, lineno);
                   1056:        return T_ERROR;
                   1057:     }
                   1058:     componentbits |= 1 << components;
                   1059:     return t;
                   1060: }
                   1061: 
                   1062: 
                   1063: /* Parse a $ operation at **stringp and update *stringp to point past it.
                   1064:    `fp' is the function whose return value is being parsed.  The parsed
                   1065:    item will be put at *sp.  Return 0 on success, nonzero on error.  */
                   1066: int parsedollar(struct function *fp, char **stringp, struct string *sp) {
                   1067:     char *p, *start;
                   1068: 
                   1069:     p = *stringp;
                   1070:     assert(*p == '$');
                   1071:     start = ++p;
                   1072:     if (*p == '[')
                   1073:        p++;
                   1074:     while (isalnum(*p) || *p == '_')
                   1075:        p++;
                   1076:     if (*start == '[') {
                   1077:        if (*p != ']') {
                   1078:            fprintf(stderr, "%s: %s(%d): missing ] or bad character in $[\n",
                   1079:                    progname, filename, lineno);
                   1080:            return 1;
                   1081:        }
                   1082:        *stringp = p + 1;
                   1083:        return parsebitsplice(fp, start + 1, p - start - 1, sp);
                   1084:     }
                   1085:     if (p == start) {
                   1086:        fprintf(stderr, "%s: %s(%d): missing identifier after $\n", progname,
                   1087:                filename, lineno);
                   1088:        return 1;
                   1089:     }
                   1090:     if (p == start + 1) {
                   1091:        if (findvariable(fp, *start, sp) != 0)
                   1092:            return 1;
                   1093:     } else {
                   1094:        if (parsefunctioncall(fp, start, &p, sp) != 0)
                   1095:            return 1;
                   1096:     }
                   1097:     *stringp = p;
                   1098:     return 0;
                   1099: }
                   1100: 
                   1101: 
                   1102: /* The representation of a $[...] bitsplice.  It is parsed into a
                   1103:    struct entry just as if it were a bitfield parameter, then analysed
                   1104:    into a chain of struct bitsplicebits.  These in conjunction with
                   1105:    the constant portion of the struct entry will allow the bitsplice to
                   1106:    be compiled.  Each bitsplicebits element represents either a numeric
                   1107:    argument to the current function, in which case it will be shifted
                   1108:    into place; or a bitfield name from the bitfield description of the
                   1109:    current function, in which case it will be shifted by the difference
                   1110:    between the position of the bitfield in the argument and the position
                   1111:    it occurs in the bitsplice.  `shift' indicates how much to shift left
                   1112:    the associated value; if it is negative the value is shifted right.
                   1113:    For instance, in a function like this:
                   1114:      %oh  xx00(%y)  $[yyxx]
                   1115:    the bitsplicebits for y will have shift = 2 and value.arg pointing to y,
                   1116:    and those for x will have shift = -2 and value.mask = binary 1100.
                   1117:    As an optimisation, contiguous bitfields that are also contiguous in the
                   1118:    bitsplice will be combined.  For instance:
                   1119:      %oh  xxyy00    $[0xxyy0]
                   1120:    will compile the same code as:
                   1121:      %oh  zzzz00    $[0zzzz0].
                   1122:    As another optimisation, a bitfield that occupies the entire bitstring
                   1123:    for a function will be treated like a parameter in that it will not be
                   1124:    masked in the bitsplice.  For instance:
                   1125:      %oh  xxxxxx    $[0xxxxxx0]
                   1126:    will compile the same code as:
                   1127:      %oh  (%x)      $[0xxxxxx0].  */
                   1128: struct bitsplice {
                   1129:     struct entry entry;
                   1130:     int nbits;
                   1131:     struct bitsplicebits *splice;
                   1132: };
                   1133: struct bitsplicebits {
                   1134:     struct bitsplicebits *next;
                   1135:     int shift;
                   1136:     enum elementtype type;
                   1137:     union {
                   1138:        struct arg *arg;
                   1139:        bits mask;
                   1140:     } value;
                   1141: };
                   1142: 
                   1143: 
                   1144: int parsebitsplice(struct function *fp, char *bitstring, int nbits,
                   1145:                   struct string *sp) {
                   1146:     struct bitsplice *splicep;
                   1147:     struct bitsplicebits *bsp, *lastbsp, **bspp;
                   1148:     struct bits *bp;
                   1149:     int shift, nfrombits, ntobits;
                   1150:     bits allbits, b;
                   1151: 
                   1152:     splicep = xmalloc(sizeof *splicep);
                   1153:     splicep->nbits = nbits;
                   1154:     if (parseentrybits(&splicep->entry, bitstring, nbits, 1) != 0)
                   1155:        return 1;
                   1156:     bspp = &splicep->splice;
                   1157:     lastbsp = NULL;
                   1158:     for (bp = splicep->entry.bits; bp != NULL; bp = bp->next) {
                   1159:        if (findvariable(fp, bp->name, sp) != 0)
                   1160:            return 1;
                   1161:        shift = bp->shift;
                   1162:        if (sp->type == S_BITSTRING) {
                   1163:            nfrombits = bitcount(sp->value.bits->mask);
                   1164:            ntobits = bitcount(bp->mask);
                   1165:            if (warnings) {
                   1166:                if (nfrombits != ntobits) {
                   1167:                    fprintf(stderr, "%s: %s(%d): warning: "
                   1168:                                    "bitstring $%c %ser than its place "
                   1169:                                    "in bitsplice\n",
                   1170:                            progname, filename, lineno, bp->name,
                   1171:                            (nfrombits > ntobits) ? "bigg" : "small");
                   1172:                }
                   1173:            }
                   1174:            shift -= sp->value.bits->shift;
                   1175: 
                   1176:            /* See if this bitfield can be combined with a previous contiguous
                   1177:               bitfield.  */
                   1178:            if (lastbsp != NULL && lastbsp->type == S_BITSTRING
                   1179:                && lastbsp->shift == shift) {
                   1180:                lastbsp->value.mask |= sp->value.bits->mask;
                   1181:                continue;
                   1182:            }
                   1183:        } else {
                   1184:            assert(sp->type == S_PARAMETER);
                   1185:            if (sp->value.parameter->type != T_INTEGER) {
                   1186:                fprintf(stderr,
                   1187:                        "%s: %s(%d): variable %c in $[...] should be integer\n",
                   1188:                        progname, filename, lineno, sp->value.parameter->name);
                   1189:                return 1;
                   1190:            }
                   1191:        }
                   1192:        *bspp = bsp = xmalloc(sizeof *bsp);
                   1193:        bsp->type = sp->type;
                   1194:        bsp->shift = shift;
                   1195:        if (sp->type == S_PARAMETER)
                   1196:            bsp->value.arg = sp->value.parameter;
                   1197:        else
                   1198:            bsp->value.mask = sp->value.bits->mask;
                   1199:        bspp = &bsp->next;
                   1200:        lastbsp = bsp;
                   1201:     }
                   1202:     *bspp = NULL;
                   1203: 
                   1204:     /* Look for a spliced element that is the entire bitstring argument to
                   1205:        this function and therefore doesn't need to be masked.  */
                   1206:     allbits = allbitsset(fp->nbits);
                   1207:     for (bsp = splicep->splice; bsp != NULL; bsp = bsp->next) {
                   1208:        if (bsp->type == S_BITSTRING) {
                   1209:            for (b = bsp->value.mask; b != 0 && !(b & 1); b >>= 1) ;
                   1210:            if (b == allbits)
                   1211:                bsp->value.mask = 0;
                   1212:        }
                   1213:     }
                   1214:     sp->type = S_BITSPLICE;
                   1215:     sp->value.bitsplice = splicep;
                   1216:     return 0;
                   1217: }
                   1218: 
                   1219: 
                   1220: int findvariable(struct function *fp, int name, struct string *sp) {
                   1221:     struct bits *bp;
                   1222:     struct arg *ap;
                   1223: 
                   1224:     for (bp = fp->last->bits; bp != NULL; bp = bp->next) {
                   1225:        if (bp->name == name) {
                   1226:            sp->type = S_BITSTRING;
                   1227:            sp->value.bits = bp;
                   1228:            return 0;
                   1229:        }
                   1230:     }
                   1231:     for (ap = fp->args; ap != NULL; ap = ap->next) {
                   1232:        if (ap->name == name) {
                   1233:            sp->type = S_PARAMETER;
                   1234:            sp->value.parameter = ap;
                   1235:            return 0;
                   1236:        }
                   1237:     }
                   1238:     fprintf(stderr, "%s: %s(%d): undefined parameter %c\n", progname, filename,
                   1239:            lineno, name);
                   1240:     return 1;
                   1241: }
                   1242: 
                   1243: 
                   1244: int parsefunctioncall(struct function *fp, char *start, char **stringp,
                   1245:                      struct string *sp) {
                   1246:     char *p;
                   1247:     struct functioncall *fcp;
                   1248:     struct stringlist **arglink, *arg;
                   1249:     enum type t;
                   1250: 
                   1251:     p = *stringp;
                   1252:     if (*p != '(') {
                   1253:        fprintf(stderr, "%s: %s(%d): missing ( after function %.*s\n", progname,
                   1254:                filename, lineno, p - start, start);
                   1255:        return 1;
                   1256:     }
                   1257:     sp->type = S_FUNCTIONCALL;
                   1258:     sp->value.functioncall = fcp = xmalloc(sizeof *fcp);
                   1259:     *p = '\0'; /* Ugly. */
                   1260:     fcp->function = findfunction(start);
                   1261:     *p = '(';
                   1262:     arglink = &fcp->args;
                   1263:     if (*++p != ')') {
                   1264:        while (1) {
                   1265:            arg = xmalloc(sizeof *arg);
                   1266:            t = makestring(fp, &arg->string, &p, MAKESTRING_MAGIC ",)",
                   1267:                           T_UNKNOWN);
                   1268:            if (t == T_ERROR)
                   1269:                return 1;
                   1270:            arg->type = t;
                   1271:            *arglink = arg;
                   1272:            arglink = &arg->next;
                   1273:            if (*p == ')')
                   1274:                break;
                   1275:            assert(*p == ',');
                   1276:            p++;
                   1277:        }
                   1278:     }
                   1279:     *arglink = NULL;
                   1280:     assert(*p == ')');
                   1281:     *stringp = p + 1;
                   1282:     return 0;
                   1283: }
                   1284: 
                   1285: 
                   1286: int parsearray(struct function *fp, char **stringp, struct string *sp,
                   1287:               enum type t) {
                   1288:     char *p;
                   1289:     struct array *ap;
                   1290:     struct stringlist **elementlink, *element;
                   1291: 
                   1292:     p = *stringp;
                   1293:     assert(*p == '{'/*}*/);
                   1294:     sp->type = S_ARRAY;
                   1295:     sp->value.array = ap = xmalloc(sizeof *ap);
                   1296:     ap->tempno = -1;
                   1297:     elementlink = &ap->elements;
                   1298:     ap->type = t;
                   1299:     if (*++p != /*{*/'}') {
                   1300:        while (1) {
                   1301:            element = xmalloc(sizeof *element);
                   1302:            t = makestring(fp, &element->string, &p,
                   1303:                           MAKESTRING_MAGIC /*{*/"|}", t);
                   1304:            if (t == T_ERROR)
                   1305:                return 1;
                   1306:            element->type = t;
                   1307:            if (ap->type == T_UNKNOWN)
                   1308:                ap->type = t;
                   1309:            else if (t != T_UNKNOWN && ap->type != t) {
                   1310:                fprintf(stderr, "%s: %s(%d): mixed types in array:\n",
                   1311:                        progname, filename, lineno);
                   1312:                showstring(stderr, ap->elements->string);
                   1313:                fprintf(stderr, " -- %s\n", typename[ap->type]);
                   1314:                showstring(stderr, element->string);
                   1315:                fprintf(stderr, " -- %s\n", typename[t]);
                   1316:                return 1;
                   1317:            }
                   1318:            *elementlink = element;
                   1319:            elementlink = &element->next;
                   1320:            if (*p == /*{*/'}')
                   1321:                break;
                   1322:            assert(*p == '|');
                   1323:            p++;
                   1324:        }
                   1325:     }
                   1326:     *elementlink = NULL;
                   1327:     assert(*p == /*{*/'}');
                   1328:     if (*++p != '[') {
                   1329:        fprintf(stderr, "%s: %s(%d): missing [index] after array\n",
                   1330:                progname, filename, lineno);
                   1331:        return 1;
                   1332:     }
                   1333:     ++p;
                   1334:     t = makestring(fp, &ap->index, &p, MAKESTRING_MAGIC "]", T_INTEGER);
                   1335:     if (t == T_ERROR)
                   1336:        return 1;
                   1337:     if (t == T_STRING) {
                   1338:        fprintf(stderr, "%s: %s(%d): array index cannot be string:\n",
                   1339:                progname, filename, lineno);
                   1340:        showstring(stderr, ap->index);
                   1341:        return 1;
                   1342:     }
                   1343:     if (*p != ']') {
                   1344:        fprintf(stderr, "%s: %s(%d): [ without ]\n", progname, filename,
                   1345:                lineno);
                   1346:        return 1;
                   1347:     }
                   1348:     *stringp = p + 1;
                   1349:     return 0;
                   1350: }
                   1351: 
                   1352: 
                   1353: void dumpfunctions() {
                   1354:     struct function *fp;
                   1355: 
                   1356:     for (fp = functions; fp != NULL; fp = fp->next)
                   1357:        dumpfunction(fp);
                   1358: }
                   1359: 
                   1360: 
                   1361: void dumpfunction(struct function *fp) {
                   1362:     struct entry *ep;
                   1363: 
                   1364:     for (ep = fp->first; ep != NULL; ep = ep->next)
                   1365:        showentry(stderr, fp, ep, 0);
                   1366: }
                   1367: 
                   1368: 
                   1369: /* Entries are not shown exactly as they would be input, since \ would
                   1370:    need to be provided before some characters such as $ or {.  But the
                   1371:    characters "|},]" pose a problem since a \ is only needed in certain
                   1372:    contexts and is annoying otherwise.  It's not worth doing this right,
                   1373:    since it's only used for error messages.  */
                   1374: void showentry(FILE *f, struct function *fp, struct entry *ep, bits highlight) {
                   1375:     if (fp->type == T_INTEGER)
                   1376:        putc('%', f);
                   1377:     fprintf(f, "%-*s ", maxfunctionname + 1, fp->name);
                   1378:     if (fp->nbits == 0 && fp->nargs == 0)
                   1379:        fprintf(f, "%-*s", maxargwidth, "()");
                   1380:     else {
                   1381:        showbits(f, ep, fp->nbits, 0);
                   1382:        showargs(f, fp->args, maxargwidth - fp->nbits);
                   1383:     }
                   1384:     putc(' ', f);
                   1385:     showstring(f, ep->string);
                   1386:     putc('\n', f);
                   1387:     if (highlight != 0) {
                   1388:        fprintf(f, "%-*s ", maxfunctionname + 1, "");
                   1389:        showbits(f, ep, fp->nbits, highlight);
                   1390:        putc('\n', f);
                   1391:     }
                   1392: }
                   1393: 
                   1394: 
                   1395: void showbits(FILE *f, struct entry *ep, int nbits, bits highlight) {
                   1396:     struct bits *bp;
                   1397:     bits i, value;
                   1398:     char zero, one;
                   1399: 
                   1400:     if (nbits == 0)
                   1401:        return;
                   1402:     i = 1 << (nbits - 1);
                   1403:     bp = ep->bits;
                   1404:     if (highlight) {
                   1405:        value = highlight;
                   1406:        zero = ' ';
                   1407:        one = '^';
                   1408:     } else {
                   1409:        value = ep->value;
                   1410:        zero = '0';
                   1411:        one = '1';
                   1412:     }
                   1413:     do {
                   1414:        if (highlight != 0 || (ep->mask & i)) {
                   1415:            putc((value & i) ? one : zero, f);
                   1416:            i >>= 1;
                   1417:        } else {
                   1418:            assert(bp != NULL && (bp->mask & i));
                   1419:            do {
                   1420:                putc(bp->name, f);
                   1421:                i >>= 1;
                   1422:            } while (bp->mask & i);
                   1423:            bp = bp->next;
                   1424:        }
                   1425:     } while (i != 0);
                   1426: }
                   1427: 
                   1428: 
                   1429: void showargs(FILE *f, struct arg *ap, int fieldwidth) {
                   1430:     int width;
                   1431:     int lastc;
                   1432:     int isint;
                   1433: 
                   1434:     if (ap == NULL)
                   1435:        width = 0;
                   1436:     else {
                   1437:        width = 1;
                   1438:        lastc = '(';
                   1439:        do {
                   1440:            isint = (ap->type == T_INTEGER);
                   1441:            fprintf(f, "%c%s%c", lastc, isint ? "%" : "", ap->name);
                   1442:            width += 2 + isint;
                   1443:            ap = ap->next;
                   1444:            lastc = ',';
                   1445:        } while (ap != NULL);
                   1446:        putc(')', f);
                   1447:     }
                   1448:     fprintf(f, "%-*s", fieldwidth - width, "");
                   1449: }
                   1450: 
                   1451: 
                   1452: void showstring(FILE *f, struct string *sp) {
                   1453:     for ( ; sp != NULL; sp = sp->next)
                   1454:        showstringelement(f, sp);
                   1455: }
                   1456: 
                   1457: 
                   1458: void showstringelement(FILE *f, struct string *sp) {
                   1459:     struct bitsplice *bsp;
                   1460: 
                   1461:     switch (sp->type) {
                   1462:     case S_TEXT:
                   1463:        fputs(sp->value.text, f);
                   1464:        break;
                   1465:     case S_BITSTRING:
                   1466:        fprintf(f, "$%c", sp->value.bits->name);
                   1467:        break;
                   1468:     case S_BITSPLICE:
                   1469:        fprintf(f, "$[");
                   1470:        bsp = sp->value.bitsplice;
                   1471:        showbits(f, &bsp->entry, bsp->nbits, 0);
                   1472:        fprintf(f, "]");
                   1473:        break;
                   1474:     case S_PARAMETER:
                   1475:        fprintf(f, "$%c", sp->value.parameter->name);
                   1476:        break;
                   1477:     case S_FUNCTIONCALL:
                   1478:        showfunctioncall(f, sp->value.functioncall);
                   1479:        break;
                   1480:     case S_ARRAY:
                   1481:        showarray(f, sp->value.array);
                   1482:        break;
                   1483:     default:
                   1484:        fprintf(stderr, "showstring case %d\n", sp->type);
                   1485:        abort();
                   1486:     }
                   1487: }
                   1488: 
                   1489: 
                   1490: void showfunctioncall(FILE *f, struct functioncall *fcp) {
                   1491:     struct stringlist *sp;
                   1492:     char *last;
                   1493: 
                   1494:     fprintf(f, "$%s(", fcp->function->name);
                   1495:     last = "";
                   1496:     for (sp = fcp->args; sp != NULL; sp = sp->next) {
                   1497:        fputs(last, f);
                   1498:        last = ",";
                   1499:        showstring(f, sp->string);
                   1500:     }
                   1501:     putc(')', f);
                   1502: }
                   1503: 
                   1504: 
                   1505: void showarray(FILE *f, struct array *ap) {
                   1506:     struct stringlist *sp;
                   1507:     char *last;
                   1508: 
                   1509:     putc('{'/*}*/, f);
                   1510:     last = "";
                   1511:     for (sp = ap->elements; sp != NULL; sp = sp->next) {
                   1512:        fputs(last, f);
                   1513:        last = "|";
                   1514:        showstring(f, sp->string);
                   1515:     }
                   1516:     fputs(/*{*/"}[", f);
                   1517:     showstring(f, ap->index);
                   1518:     putc(']', f);
                   1519: }
                   1520: 
                   1521: 
                   1522: const char commonpreamble[] = "\
                   1523: typedef %s bits;\n\
                   1524: \n\
                   1525: ";
                   1526: 
                   1527: const char concatpreamble[] = "\
                   1528: static char *dis_buf;\n\
                   1529: static int dis_bufindex, dis_buflen;\n\
                   1530: \n\
                   1531: void *dis_alloc(size_t size)\n\
                   1532: {\n\
                   1533:     void *p;\n\
                   1534:     int newindex = dis_bufindex + size;\n\
                   1535:     if (newindex > dis_buflen) {\n\
                   1536:        dis_buflen = newindex * 4;\n\
                   1537:        dis_buf = malloc(dis_buflen);\n\
                   1538:        /* We can't use realloc because there might be pointers extant into\n\
                   1539:           the old buffer.  So we waste the memory of the old buffer.  We\n\
                   1540:           should soon reach an adequate buffer size and stop leaking.  */\n\
                   1541:        if (dis_buf == 0) {\n\
                   1542:            perror(\"malloc\");\n\
                   1543:            exit(1);\n\
                   1544:        }\n\
                   1545:        dis_bufindex = 0;\n\
                   1546:     }\n\
                   1547:     p = dis_buf + dis_bufindex;\n\
                   1548:     dis_bufindex = newindex;\n\
                   1549:     return p;\n\
                   1550: }\n\
                   1551: \n\
                   1552: void dis_done()\n\
                   1553: {\n\
                   1554:     dis_bufindex = 0;\n\
                   1555: }\n\
                   1556: \n\
                   1557: ";
                   1558: 
                   1559: const char concatdeclarations[] = "\
                   1560: #include <string.h>\n\
                   1561: #include <stdlib.h>\n\
                   1562: #include <errno.h>\n\
                   1563: \n\
                   1564: extern void *dis_realloc(void *p, size_t size); /* User-provided. */\n\
                   1565: void *dis_alloc(size_t size);\n\
                   1566: void dis_done(void);\n\
                   1567: ";
                   1568: 
                   1569: const char nonconcatpreamble[] = "\
                   1570: void dis_done() {}\n\
                   1571: ";
                   1572: 
                   1573: 
                   1574: int outputfunctions() {
                   1575:     struct function *fp;
                   1576: 
                   1577:     outputidentity(stdout);
                   1578:     if (headerfilename != NULL) {
                   1579:        if ((headerfile = fopen(headerfilename, "w")) == NULL) {
                   1580:            fprintf(stderr, "%s: create %s: %s\n", progname, headerfilename,
                   1581:                    strerror(errno));
                   1582:            return 1;
                   1583:        }
                   1584:        outputidentity(headerfile);
                   1585:        fprintf(headerfile, commonpreamble, bitstype);
                   1586:        printf("\n#include \"%s\"\n", headerfilename);
                   1587:     } else
                   1588:        printf(commonpreamble, bitstype);
                   1589:     findarrays();
                   1590:     if (outputdeclarations() != 0)
                   1591:        return 1;
                   1592:     outputconcats();
                   1593:     for (fp = functions; fp != NULL; fp = fp->next) {
                   1594:        if (fp->isarray)
                   1595:            functionarray(fp);
                   1596:     }
                   1597:     for (fp = functions; fp != NULL; fp = fp->next) {
                   1598:        if (fp->first != NULL && !fp->isarray) {
                   1599:            if (outputfunction(fp) != 0)
                   1600:                return 1;
                   1601:        }
                   1602:     }
                   1603:     return 0;
                   1604: }
                   1605: 
                   1606: 
                   1607: void outputidentity(FILE *f) {
                   1608:     char **p;
                   1609: 
                   1610:     fprintf(f, "/*\n * This file was generated by:\n *");
                   1611:     for (p = global_argv; *p != NULL; p++)
                   1612:        fprintf(f, " %s", *p);
                   1613:     fprintf(f, "\n */\n\n");
                   1614: }
                   1615: 
                   1616: 
                   1617: int outputdeclarations() {
                   1618:     FILE *f = headerfile ? headerfile : stdout;
                   1619:     struct function *fp;
                   1620: 
                   1621:     for (fp = functions; fp != NULL; fp = fp->next) {
                   1622:        if (fp->type != T_UNKNOWN) {
                   1623:            if (fp->isarray) {
                   1624:                fprintf(f, "extern ");
                   1625:                if (fp->fixedlength > 0)
                   1626:                    fprintf(f, "char %s[][%d]", fp->name, fp->fixedlength);
                   1627:                else {
                   1628:                    compiletype(f, &fp->type);
                   1629:                    fprintf(f, "%s[]", fp->name);
                   1630:                }
                   1631:            } else
                   1632:                functionheader(f, fp);
                   1633:            fprintf(f, ";\n");
                   1634:        }
                   1635:     }
                   1636:     return 0;
                   1637: }
                   1638: 
                   1639: 
                   1640: void outputconcats() {
                   1641:     int i;
                   1642: 
                   1643:     if (componentbits & ~3) {
                   1644:        fputs(concatdeclarations, headerfile ? headerfile : stdout);
                   1645:        fputs(concatpreamble, stdout);
                   1646:     } else
                   1647:        fputs(nonconcatpreamble, stdout);
                   1648:     for (i = 2; i < MAXBITS; i++) {
                   1649:        if (componentbits & (1 << i))
                   1650:            outputconcat(i);
                   1651:     }
                   1652: }
                   1653: 
                   1654: 
                   1655: void outputconcat(int n) {
                   1656:     int i;
                   1657:     char *last;
                   1658: 
                   1659:     assert(n > 1);
                   1660:     if (headerfile) {
                   1661:        outputconcatheader(headerfile, n);
                   1662:        fprintf(headerfile, ";\n");
                   1663:     }
                   1664:     outputconcatheader(stdout, n);
                   1665:     printf("\n{\n    void *p;\n    int len = ");
                   1666:     last = "";
                   1667:     for (i = 0; i < n; i++) {
                   1668:        printf("%sstrlen(p%d)", last, i);
                   1669:        last = " + ";
                   1670:     }
                   1671:     printf(";\n    p = dis_alloc(len + 1);\n    return ");
                   1672:     for (i = 1; i < n; i++)
                   1673:        printf("strcat(");
                   1674:     printf("strcpy(p, p0)");
                   1675:     for (i = 1; i < n; i++)
                   1676:        printf(", p%d)", i);
                   1677:     printf(";\n}\n\n");
                   1678: }
                   1679: 
                   1680: 
                   1681: void outputconcatheader(FILE *f, int n) {
                   1682:     int i;
                   1683:     char *last = "";
                   1684: 
                   1685:     fprintf(f, "char *dis_concat%d(", n);
                   1686:     for (i = 0; i < n; i++) {
                   1687:        fprintf(f, "%schar *p%d", last, i);
                   1688:        last = ", ";
                   1689:     }
                   1690:     fprintf(f, ")");
                   1691: }
                   1692: 
                   1693: 
                   1694: void findarrays() {
                   1695:     struct function *fp;
                   1696:     struct entry *ep;
                   1697:     struct string *estr, *indexstr;
                   1698:     struct bits *bp;
                   1699: 
                   1700:     for (fp = functions; fp != NULL; fp = fp->next) {
                   1701:        if (fp->nbits > 0 && fp->nargs > 0)
                   1702:            continue;
                   1703:        if (fp->nargs > 1)
                   1704:            continue;
                   1705:        ep = fp->first;
                   1706:        if (ep == NULL || ep->next != NULL)
                   1707:            continue;
                   1708:        estr = ep->string;
                   1709:        if (estr == NULL || estr->next != NULL || estr->type != S_ARRAY)
                   1710:            continue;
                   1711:        indexstr = estr->value.array->index;
                   1712:        if (indexstr->next != NULL)
                   1713:            continue;
                   1714:        if (fp->nbits > 0) {
                   1715:            bp = ep->bits;
                   1716:            if (bp == NULL || bp->next != NULL || bp->shift != 0)
                   1717:                continue;
                   1718:            if (bp->mask != allbitsset(fp->nbits))
                   1719:                continue;
                   1720:            if (indexstr->type != S_BITSTRING || indexstr->value.bits != bp)
                   1721:                continue;
                   1722:        } else {
                   1723:            if (indexstr->type != S_PARAMETER
                   1724:                || indexstr->value.parameter != fp->args)
                   1725:                continue;
                   1726:        }
                   1727:        if (!simplearray(estr->value.array))
                   1728:            continue;
                   1729:        fp->isarray = 1;
                   1730:        fp->fixedlength =
                   1731:            (fp->type == T_INTEGER) ? 0 : checkfixedlength(estr->value.array);
                   1732:     }
                   1733: }
                   1734: 
                   1735: 
                   1736: int checkfixedlength(struct array *ap) {
                   1737:     int len, maxlen, wasted, n;
                   1738:     struct stringlist *lp;
                   1739: 
                   1740:     maxlen = 0;
                   1741:     for (lp = ap->elements; lp != NULL; lp = lp->next) {
                   1742:        if (lp->string == NULL)
                   1743:            continue;
                   1744:        assert(lp->string->type == S_TEXT);
                   1745:        len = strlen(lp->string->value.text);
                   1746:        if (len > maxlen)
                   1747:            maxlen = len;
                   1748:     }
                   1749:     for (wasted = n = 0, lp = ap->elements; lp != NULL; n++, lp = lp->next) {
                   1750:        if (lp->string == NULL)
                   1751:            continue;
                   1752:        wasted += maxlen - strlen(lp->string->value.text);
                   1753:     }
                   1754:     if (wasted < n * sizeof(char *))   /* Should be target's sizeof. */
                   1755:        return maxlen + 1;
                   1756:     return 0;
                   1757: }
                   1758: 
                   1759: 
                   1760: int outputfunction(struct function *fp) {
                   1761:     printf("\n");
                   1762:     functionheader(stdout, fp);
                   1763:     printf("\n{\n"/*}*/);
                   1764:     switch (functionswitch(fp, 0, 0)) {
                   1765:     case -1:
                   1766:        return 1;
                   1767:     case 0:
                   1768:        if (warnings) {
                   1769:            fprintf(stderr, "%s: warning: not all cases of %s covered\n",
                   1770:                    progname, fp->name);
                   1771:        }
                   1772:     }
                   1773:     printf(/*{*/"}\n");
                   1774:     return 0;
                   1775: }
                   1776: 
                   1777: 
                   1778: void functionarray(struct function *fp) {
                   1779:     struct array *ap;
                   1780: 
                   1781:     ap = fp->first->string->value.array;
                   1782:     printf("\n");
                   1783:     compilesimplearray(&fp->type, fp->name, 0, ap);
                   1784: }
                   1785: 
                   1786: 
                   1787: void functionheader(FILE *f, struct function *fp) {
                   1788:     char *last;
                   1789:     struct arg *ap;
                   1790: 
                   1791:     compiletype(f, &fp->type);
                   1792:     fprintf(f, "%s(", fp->name);
                   1793:     last = "";
                   1794:     if (fp->nbits > 0) {
                   1795:        fprintf(f, "bits code");
                   1796:        last = ", ";
                   1797:     }
                   1798:     for (ap = fp->args; ap != NULL; ap = ap->next) {
                   1799:        fprintf(f, last);
                   1800:        compiletype(f, &ap->type);
                   1801:        putc(ap->name, f);
                   1802:        last = ", ";
                   1803:     }
                   1804:     if (*last == '\0')
                   1805:        fprintf(f, "void");
                   1806:     putc(')', f);
                   1807: }
                   1808: 
                   1809: 
                   1810: int simplearray(struct array *ap) {
                   1811:     struct stringlist *lp;
                   1812: 
                   1813:     for (lp = ap->elements; lp != NULL; lp = lp->next) {
                   1814:        if (lp->string != NULL
                   1815:            && (lp->string->next != NULL || lp->string->type != S_TEXT))
                   1816:            break;
                   1817:     }
                   1818:     return (lp == NULL);
                   1819: }
                   1820: 
                   1821: 
                   1822: void compiletype(FILE *f, enum type *tp) {
                   1823:     switch (*tp) {
                   1824:     case T_UNKNOWN:
                   1825:        *tp = T_STRING;
                   1826:        /* Fall in... */
                   1827:     case T_STRING:
                   1828:        fprintf(f, "char *");
                   1829:        break;
                   1830:     case T_INTEGER:
                   1831:        fprintf(f, "bits ");
                   1832:        break;
                   1833:     default:
                   1834:        fprintf(stderr, "compiletype type %d\n", *tp);
                   1835:        abort();
                   1836:     }
                   1837: }
                   1838: 
                   1839: 
                   1840: /* Generate code for entries in function fp whose bitstring b satisfies
                   1841:    the constraint (b & mask) == value.  Return 1 if generated switch
                   1842:    always does `return', 0 if not, -1 on error.
                   1843:    The algorithm is as follows.  Scan the eligible entries to find the
                   1844:    largest set of bits not in the passed-in mask which always have a
                   1845:    constant value (are not variable).  One `default' entry is allowed
                   1846:    all of whose bits are variable.  For each value of the constant bits,
                   1847:    generate a `switch' case and invoke the function recursively with
                   1848:    that value included in the constraint parameters.  The recursion
                   1849:    stops when no set of constant bits is found, perhaps because the
                   1850:    mask parameter has all bits set.
                   1851:    This algorithm could be improved.  Currently it will fail if there
                   1852:    are input lines "xxyy", "00xx" and "yy00", each of which is default with
                   1853:    respect to the others.  The correct behaviour would then be to select
                   1854:    a bit that is sometimes constant and deal with those cases first.
                   1855:    But this problem has not yet arisen in real life.  */
                   1856: int functionswitch(struct function *fp, bits mask, bits value) {
                   1857:     struct entry *ep, *defaultcase;
                   1858:     bits allbits, constbits, missingcases;
                   1859:     int nhits, ncases, nconstbits, alwaysreturns;
                   1860: 
                   1861:     indentation++;
                   1862:     allbits = allbitsset(fp->nbits);
                   1863:     constbits = allbits & ~mask;
                   1864:     if (debug) {
                   1865:        findent(stderr);
                   1866:        fprintf(stderr,
                   1867:                "functionswitch(%s): (x & 0x%lx) == 0x%lx; const == 0x%lx\n",
                   1868:                fp->name, mask, value, constbits);
                   1869:     }
                   1870:     defaultcase = NULL;
                   1871:     ncases = nhits = 0;
                   1872:     alwaysreturns = 1;
                   1873:     for (ep = fp->first; ep != NULL; ep = ep->next) {
                   1874:        /* If this is not one of the entries under consideration, skip.  */
                   1875:        if (ep->done
                   1876:            || (ep->mask & mask) != mask || (ep->value & mask) != value)
                   1877:            continue;
                   1878:        if (debug) {
                   1879:            findent(stderr);
                   1880:            showentry(stderr, fp, ep, 0);
                   1881:        }
                   1882:        /* If this entry has no constant bits in the still-variable portion,
                   1883:           it's the default.  */
                   1884:        if ((constbits & ep->mask) == 0) {
                   1885:            if (defaultcase != NULL) {
                   1886:                fprintf(stderr,
                   1887:                        "%s: function %s: unable to distinguish between:\n",
                   1888:                        progname, fp->name);
                   1889:                showentry(stderr, fp, defaultcase, 0);
                   1890:                showentry(stderr, fp, ep, 0);
                   1891:                return -1;
                   1892:            }
                   1893:            defaultcase = ep;
                   1894:            if (debug) {
                   1895:                findent(stderr);
                   1896:                fprintf(stderr, "^^ default case\n");
                   1897:            }
                   1898:        } else {
                   1899:            if (debug && (constbits & ~ep->mask)) {
                   1900:                findent(stderr);
                   1901:                fprintf(stderr, "const now 0x%lx\n", constbits & ep->mask);
                   1902:            }
                   1903:            constbits &= ep->mask;
                   1904:            nhits++;
                   1905:        }
                   1906:     }
                   1907:     if (nhits > 0) {
                   1908:        indent();
                   1909:        if (constbits == allbits)
                   1910:            printf("switch (code) {\n"/*}*/);
                   1911:        else
                   1912:            printf("switch (code & 0x%lx) {\n"/*}*/, constbits);
                   1913:        for (ep = fp->first; ep != NULL; ep = ep->next) {
                   1914:            /* If this is not one of the entries under consideration, skip.  */
                   1915:            if ((ep->mask & mask) != mask || (ep->value & mask) != value)
                   1916:                continue;
                   1917:            if (ep->done || ep == defaultcase)
                   1918:                continue;
                   1919:            ncases++;
                   1920:            indent();
                   1921:            printf("case 0x%lx:\n", ep->value & constbits);
                   1922:            switch (functionswitch(fp, mask | constbits,
                   1923:                                value | (ep->value & constbits))) {
                   1924:            case -1:
                   1925:                return -1;
                   1926:            case 0:
                   1927:                alwaysreturns = 0;
                   1928:                indentation++; indent(); indentation--;
                   1929:                printf("break;\n");
                   1930:            }
                   1931:        }
                   1932:        indent();
                   1933:        printf(/*{*/"}\n");
                   1934:     }
                   1935:     nconstbits = bitcount(constbits);
                   1936:     missingcases = ((nconstbits == MAXBITS) ? 0 : 1 << nconstbits) - ncases;
                   1937:     if (alwaysreturns) {
                   1938:        switch (missingcases) {
                   1939:        case 0:
                   1940:            if (defaultcase != NULL) {
                   1941:                fprintf(stderr, "%s: warning: redundant entry:\n", progname);
                   1942:                showentry(stderr, fp, defaultcase, 0);
                   1943:                defaultcase = NULL;
                   1944:            }
                   1945:            break;
                   1946:        case 1:
                   1947:            if (defaultcase != NULL && nconstbits != 0) {
                   1948:                fprintf(stderr,
                   1949:                        "%s: warning: variable bit(s) could be constant:\n",
                   1950:                        progname);
                   1951:                showentry(stderr, fp, defaultcase, constbits);
                   1952:                break;
                   1953:            }
                   1954:            /* Fall in... */
                   1955:        default:
                   1956:            alwaysreturns = 0;
                   1957:        }
                   1958:     }
                   1959:     if (defaultcase != NULL) {
                   1960:        /* If defaultcase has some constant bits of its own, recursion will
                   1961:           check that they have the required value.  */
                   1962:        if ((defaultcase->mask & ~mask) == 0) {
                   1963:            alwaysreturns = 1;
                   1964:            if (compilestring(-1, defaultcase->string, fp->type) != 0)
                   1965:                return -1;
                   1966:            defaultcase->done = 1;
                   1967:        } else {
                   1968:            indentation--;
                   1969:            alwaysreturns = functionswitch(fp, mask, value);
                   1970:            indentation++;
                   1971:        }
                   1972:     }
                   1973:     indentation--;
                   1974:     return alwaysreturns;
                   1975: }
                   1976: 
                   1977: 
                   1978: int compilestring(int assignto, struct string *sp, enum type type) {
                   1979:     int tempno;
                   1980: 
                   1981:     tempno = walkstring(sp, COUNTARRAYS, assignto);
                   1982:     if (tempno > assignto) {
                   1983:        indent();
                   1984:        printf("{\n"/*}*/);
                   1985:        indentation++;
                   1986:        (void) walkstring(sp, DECLAREARRAYS, assignto);
                   1987:        if (walkstring(sp, COMPILEARRAYS, assignto) < 0)
                   1988:            return 1;
                   1989:     }
                   1990:     if (compilecheckedstring(assignto, sp, type) != 0)
                   1991:        return 1;
                   1992:     if (tempno > assignto) {
                   1993:        indentation--;
                   1994:        indent();
                   1995:        printf(/*{*/"}\n");
                   1996:     }
                   1997:     return 0;
                   1998: }
                   1999: 
                   2000: 
                   2001: int compilecheckedstring(int assignto, struct string *sp, enum type type) {
                   2002:     compileassign(assignto);
                   2003:     if (compileconcat(sp, type) != 0)
                   2004:        return 1;
                   2005:     printf(";\n");
                   2006:     return 0;
                   2007: }
                   2008: 
                   2009: 
                   2010: void compileassign(int assignto) {
                   2011:     indent();
                   2012:     if (assignto < 0)
                   2013:        printf("return ");
                   2014:     else {
                   2015:        compiletemp(assignto);
                   2016:        printf(" = ");
                   2017:     }
                   2018: }
                   2019: 
                   2020: 
                   2021: void compiletemp(int tempno) {
                   2022:     printf("t__%d", tempno);
                   2023: }
                   2024: 
                   2025: 
                   2026: void compiletext(char *s) {
                   2027:     putchar('"');
                   2028:     if (s != NULL) {
                   2029:        for ( ; *s != '\0'; s++) {
                   2030:            switch (*s) {
                   2031:            case '"':
                   2032:            case '\\':
                   2033:                putchar('\\');
                   2034:            }
                   2035:            putchar(*s);
                   2036:        }
                   2037:     }
                   2038:     putchar('"');
                   2039: }
                   2040: 
                   2041: 
                   2042: int compileconcat(struct string *sp, enum type type) {
                   2043:     int elements;
                   2044:     struct string *sp1;
                   2045:     char *last;
                   2046: 
                   2047:     if (sp == NULL)
                   2048:        return compilenull(type);
                   2049:     if (sp->next == NULL)
                   2050:        return compilesimple(sp, type);
                   2051:     if (type != T_INTEGER) {
                   2052:        for (elements = 0, sp1 = sp; sp1 != NULL; elements++, sp1 = sp1->next) ;
                   2053:        printf("dis_concat%d(", elements);
                   2054:     }
                   2055:     last = "";
                   2056:     for (sp1 = sp; sp1 != NULL; sp1 = sp1->next) {
                   2057:        printf(last);
                   2058:        if (type != T_INTEGER)
                   2059:            last = ", ";
                   2060:        if (sp1->type == S_ARRAY)
                   2061:            compilearrayref(sp1->value.array);
                   2062:        else
                   2063:            if (compilesimple(sp1, type) != 0)
                   2064:                return 1;
                   2065:     }
                   2066:     if (type != T_INTEGER)
                   2067:        printf(")");
                   2068:     return 0;
                   2069: }
                   2070: 
                   2071: 
                   2072: int compilenull(enum type type) {
                   2073:     if (type == T_INTEGER) {
                   2074:        fprintf(stderr, "%s: empty integer expression\n", progname);
                   2075:        return 1;
                   2076:     }
                   2077:     printf("\"\"");
                   2078:     return 0;
                   2079: }
                   2080: 
                   2081: 
                   2082: int compilesimple(struct string *sp, enum type type) {
                   2083:     if (sp == NULL)
                   2084:        return compilenull(type);
                   2085:     switch (sp->type) {
                   2086:     case S_TEXT:
                   2087:        if (type == T_INTEGER)
                   2088:            printf("%s", sp->value.text);
                   2089:        else
                   2090:            compiletext(sp->value.text);
                   2091:        break;
                   2092:     case S_BITSTRING:
                   2093:        compilebitstring(sp->value.bits);
                   2094:        break;
                   2095:     case S_BITSPLICE:
                   2096:        compilebitsplice(sp->value.bitsplice);
                   2097:        break;
                   2098:     case S_PARAMETER:
                   2099:        putchar(sp->value.parameter->name);
                   2100:        break;
                   2101:     case S_FUNCTIONCALL:
                   2102:        return compilefunctioncall(sp);
                   2103:     case S_ARRAY:
                   2104:        if (compilearrayref(sp->value.array) != 0)
                   2105:            return 1;
                   2106:        break;
                   2107:     default:
                   2108:        fprintf(stderr, "compilesimple case %d", sp->type);
                   2109:        abort();
                   2110:     }
                   2111:     return 0;
                   2112: }
                   2113: 
                   2114: 
                   2115: int compilearrayref(struct array *ap) {
                   2116:     compiletemp(ap->tempno);
                   2117:     if (simplearray(ap)) {
                   2118:        printf("[");
                   2119:        if (compileconcat(ap->index, T_INTEGER) != 0)
                   2120:            return 1;
                   2121:        printf("]");
                   2122:     }
                   2123:     return 0;
                   2124: }
                   2125: 
                   2126: 
                   2127: int compilefunctioncall(struct string *sp) {
                   2128:     struct function *fp;
                   2129:     struct stringlist *actualp;
                   2130:     struct arg *formalp;
                   2131:     char *last;
                   2132:     int nbits;
                   2133:     enum type formaltype;
                   2134: 
                   2135:     assert(sp->type == S_FUNCTIONCALL);
                   2136:     fp = sp->value.functioncall->function;
                   2137:     printf("%s%c", fp->name, fp->isarray ? '[' : '(');
                   2138:     last = "";
                   2139:     nbits = fp->nbits;
                   2140:     formalp = fp->args;
                   2141:     actualp = sp->value.functioncall->args;
                   2142:     while (actualp != NULL) {
                   2143:        if (nbits > 0) {
                   2144:            nbits = 0;
                   2145:            formaltype = T_INTEGER;
                   2146:        } else {
                   2147:            if (formalp == NULL) {
                   2148:                fprintf(stderr, "%s: too many arguments to %s:\n", progname,
                   2149:                        fp->name);
                   2150:                showstring(stderr, sp);
                   2151:                putc('\n', stderr);
                   2152:                return 1;
                   2153:            }
                   2154:            formaltype = formalp->type;
                   2155:            formalp = formalp->next;
                   2156:        }
                   2157:        if (actualp->type != T_UNKNOWN && actualp->type != formaltype) {
                   2158:            fprintf(stderr, "%s: argument to %s has the wrong type:\n",
                   2159:                    progname, fp->name);
                   2160:            showstring(stderr, actualp->string);
                   2161:            putc('\n', stderr);
                   2162:            return 1;
                   2163:        }
                   2164:        printf(last);
                   2165:        last = ", ";
                   2166:        if (compileconcat(actualp->string, formaltype) != 0)
                   2167:            return 1;
                   2168:        actualp = actualp->next;
                   2169:     }
                   2170:     putchar(fp->isarray ? ']' : ')');
                   2171:     return 0;
                   2172: }
                   2173: 
                   2174: 
                   2175: int walkstring(struct string *sp, enum walkstringop op, int tempno) {
                   2176:     struct stringlist *lp;
                   2177:     struct array *ap;
                   2178: 
                   2179:     for ( ; sp != NULL; sp = sp->next) {
                   2180:        switch (sp->type) {
                   2181:        case S_ARRAY:
                   2182:            ap = sp->value.array;
                   2183:            for (lp = ap->elements; lp != NULL; lp = lp->next)
                   2184:                tempno = walkstring(lp->string, op, tempno);
                   2185:            tempno = walkstring(ap->index, op, tempno);
                   2186:            ap->tempno = ++tempno;
                   2187:            switch (op) {
                   2188:            case DECLAREARRAYS:
                   2189:                if (simplearray(ap)) {
                   2190:                    indent();
                   2191:                    printf("static ");
                   2192:                    compilesimplearray(&ap->type, NULL, tempno, ap);
                   2193:                } else
                   2194:                    declarearray(ap);
                   2195:                break;
                   2196:            case COMPILEARRAYS:
                   2197:                if (!simplearray(ap))
                   2198:                    if (compilearray(ap) != 0)
                   2199:                        return -1;
                   2200:                break;
                   2201:            default:
                   2202:                break;
                   2203:            }
                   2204:            break;
                   2205:        case S_FUNCTIONCALL:
                   2206:            for (lp = sp->value.functioncall->args; lp != NULL; lp = lp->next)
                   2207:                tempno = walkstring(lp->string, op, tempno);
                   2208:            break;
                   2209:        default:
                   2210:            break;
                   2211:        }
                   2212:     }
                   2213:     return tempno;
                   2214: }
                   2215: 
                   2216: 
                   2217: int compilearray(struct array *ap) {
                   2218:     struct stringlist *ep;
                   2219:     int i;
                   2220: 
                   2221:     indent();
                   2222:     printf("switch (");
                   2223:     if (compileconcat(ap->index, T_INTEGER) != 0)
                   2224:        return 1;
                   2225:     printf(") {\n"/*}*/);
                   2226:     for (i = 0, ep = ap->elements; ep != NULL; i++, ep = ep->next) {
                   2227:        indent();
                   2228:        printf("case %d:\n", i);
                   2229:        indentation++;
                   2230:        if (compilecheckedstring(ap->tempno, ep->string, ap->type) != 0)
                   2231:            return 1;
                   2232:        indent();
                   2233:        printf("break;\n");
                   2234:        indentation--;
                   2235:     }
                   2236:     indent();
                   2237:     printf(/*{*/"}\n");
                   2238:     return 0;
                   2239: }
                   2240: 
                   2241: 
                   2242: void compilesimplearray(enum type *tp, char *name, int num, struct array *ap) {
                   2243:     struct stringlist *lp;
                   2244:     int fixedlength;
                   2245: 
                   2246:     fixedlength = (*tp == T_INTEGER) ? 0 : checkfixedlength(ap);
                   2247:     if (fixedlength > 0)
                   2248:        printf("char ");
                   2249:     else
                   2250:        compiletype(stdout, tp);
                   2251:     if (name != NULL)
                   2252:        printf(name);
                   2253:     else
                   2254:        compiletemp(num);
                   2255:     printf("[]");
                   2256:     if (fixedlength > 0)
                   2257:        printf("[%d]", fixedlength);
                   2258:     printf(" = {\n"/*}*/);
                   2259:     indentation++;
                   2260:     for (lp = ap->elements; lp != NULL; lp = lp->next) {
                   2261:        indent();
                   2262:        compilesimple(lp->string, lp->type);
                   2263:        printf(",\n");
                   2264:     }
                   2265:     indentation--;
                   2266:     indent();
                   2267:     printf(/*{*/"};\n");
                   2268: }
                   2269: 
                   2270: 
                   2271: void declarearray(struct array *ap) {
                   2272:     indent();
                   2273:     compiletype(stdout, &ap->type);
                   2274:     compiletemp(ap->tempno);
                   2275:     printf(";\n");
                   2276: }
                   2277: 
                   2278: 
                   2279: void compilebitstring(struct bits *bp) {
                   2280:     printf("(");
                   2281:     if (bp->shift != 0)
                   2282:        printf("(");
                   2283:     printf("code & 0x%lx", bp->mask);
                   2284:     if (bp->shift != 0)
                   2285:        printf(") >> %d", bp->shift);
                   2286:     printf(")");
                   2287: }
                   2288: 
                   2289: 
                   2290: void compilebitsplice(struct bitsplice *splicep) {
                   2291:     struct bitsplicebits *bsp;
                   2292:     char *last = "";
                   2293: 
                   2294:     printf("(");
                   2295:     for (bsp = splicep->splice; bsp != NULL; bsp = bsp->next) {
                   2296:        printf(last);
                   2297:        last = " | ";
                   2298:        if (bsp->type == S_PARAMETER)
                   2299:            putchar(bsp->value.arg->name);
                   2300:        else {
                   2301:            assert(bsp->type == S_BITSTRING);
                   2302:            if (bsp->value.mask == 0)
                   2303:                printf("code");
                   2304:            else
                   2305:                printf("(code & 0x%lx)", bsp->value.mask);
                   2306:        }
                   2307:        if (bsp->shift > 0)
                   2308:            printf(" << %d", bsp->shift);
                   2309:        else if (bsp->shift < 0)
                   2310:            printf(" >> %d", -bsp->shift);
                   2311:     }
                   2312:     if (splicep->entry.value != 0)
                   2313:        printf("%s0x%lx", last, splicep->entry.value);
                   2314:     printf(")");
                   2315: }
                   2316: 
                   2317: 
                   2318: int bitcount(bits x) {
                   2319:     int nbits;
                   2320: 
                   2321:     for (nbits = 0; x != 0; x >>= 1) {
                   2322:        if (x & 1)
                   2323:            nbits++;
                   2324:     }
                   2325:     return nbits;
                   2326: }
                   2327: 
                   2328: 
                   2329: bits allbitsset(int nbits) {
                   2330:     return (nbits == MAXBITS) ? ~0 : (1 << nbits) - 1;
                   2331: }
                   2332: 
                   2333: 
                   2334: void findent(FILE *f) {
                   2335:     int i;
                   2336: 
                   2337:     for (i = 1; i < indentation; i += 2)
                   2338:        putc('\t', f);
                   2339:     if (i == indentation)
                   2340:        fputs("    ", f);
                   2341: }
                   2342: 
                   2343: 
                   2344: void indent() {
                   2345:     findent(stdout);
                   2346: }
                   2347: 
                   2348: 
                   2349: void *xrealloc(char *oldp, size_t size) {
                   2350:     void *p;
                   2351: 
                   2352:     if (oldp == NULL)
                   2353:        p = malloc(size);
                   2354:     else
                   2355:        p = realloc(oldp, size);
                   2356:     if (p == NULL) {
                   2357:        fprintf(stderr, "%s: allocate of %d bytes failed: %s\n", progname,
                   2358:                (int) size, strerror(errno));
                   2359:        exit(1);
                   2360:     }
                   2361:     return p;
                   2362: }
                   2363: 
                   2364: 
                   2365: void *xmalloc(size_t size) {
                   2366:     return xrealloc(NULL, size);
                   2367: }
                   2368: 
                   2369: 
                   2370: void *xstrdup(char *s) {
                   2371:     char *p;
                   2372: 
                   2373:     p = xmalloc(strlen(s) + 1);
                   2374:     strcpy(p, s);
                   2375:     return p;
                   2376: }
                   2377: 
                   2378: 
                   2379: int prematureeof() {
                   2380:     fprintf(stderr, "%s: %s(%d): premature end of file\n", progname, filename,
                   2381:            lineno);
                   2382:     return 1;
                   2383: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.