Annotation of XNU/osfmk/ddb/makedis.c, revision 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.