darwin-xnu/osfmk/ddb/makedis.c
<<
>>
Prefs
   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 <emcmanus@gr.osf.org>, 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. */
 292typedef unsigned long bits;
 293enum type {T_ERROR, T_UNKNOWN, T_INTEGER, T_STRING};
 294const char *const typename[] = {"error", "unknown", "integer", "string"};
 295enum walkstringop {COUNTARRAYS, DECLAREARRAYS, COMPILEARRAYS};
 296char *bitstype = "unsigned long";
 297
 298int maxfunctionname, maxargwidth;
 299char *progname = "makedis";
 300char **global_argv;
 301char *filename;
 302char *headerfilename;
 303FILE *headerfile;
 304int lineno;
 305int indentation;
 306int 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.  */
 311bits componentbits;
 312
 313
 314struct entry;
 315struct arg;
 316struct string;
 317struct functioncall;
 318struct array;
 319struct bits;
 320struct bitsplice;
 321
 322
 323int main(int argc, char **argv);
 324int makedis(FILE *f, char *fname);
 325struct function *findfunction(char *function);
 326int parseextern(struct function *fp, FILE *f);
 327struct function *makefunction(char *function);
 328int parsebits(struct function *fp, char *bitstring, int nbits);
 329int parseentrybits(struct entry *ep, char *bitstring, int nbits, int issplice);
 330int parsecontrol(char *name, char *value);
 331int parseargs(struct function *fp, FILE *f, int *cp);
 332int parsestring(struct function *fp, char *str);
 333enum type makestring(struct function *fp, struct string **stringlink,
 334                     char **stringp, char *magic, enum type targettype);
 335int parsedollar(struct function *fp, char **stringp, struct string *sp);
 336int parsebitsplice(struct function *fp, char *bitstring, int nbits,
 337                   struct string *sp);
 338int findvariable(struct function *fp, int name, struct string *sp);
 339int parsefunctioncall(struct function *fp, char *start, char **stringp,
 340                      struct string *sp);
 341int parsearray(struct function *fp, char **stringp, struct string *sp,
 342               enum type t);
 343void dumpfunctions(void);
 344void dumpfunction(struct function *fp);
 345void showentry(FILE *f, struct function *fp, struct entry *ep, bits highlight);
 346void showbits(FILE *f, struct entry *ep, int nbits, bits highlight);
 347void showargs(FILE *f, struct arg *ap, int fieldwidth);
 348void showstring(FILE *f, struct string *sp);
 349void showstringelement(FILE *f, struct string *sp);
 350void showfunctioncall(FILE *f, struct functioncall *fcp);
 351void showarray(FILE *f, struct array *ap);
 352int outputfunctions(void);
 353void outputidentity(FILE *f);
 354int outputdeclarations(void);
 355void outputconcats(void);
 356void outputconcat(int n);
 357void outputconcatheader(FILE *f, int n);
 358void findarrays(void);
 359int checkfixedlength(struct array *ap);
 360int outputfunction(struct function *fp);
 361void functionarray(struct function *fp);
 362void functionheader(FILE *f, struct function *fp);
 363int simplearray(struct array *ap);
 364void compiletype(FILE *f, enum type *tp);
 365int functionswitch(struct function *fp, bits mask, bits value);
 366int compilestring(int assignto, struct string *sp, enum type type);
 367int compilecheckedstring(int assignto, struct string *sp, enum type type);
 368void compileassign(int assignto);
 369void compiletemp(int tempno);
 370void compiletext(char *s);
 371int compileconcat(struct string *sp, enum type type);
 372int compilenull(enum type type);
 373int compilesimple(struct string *sp, enum type type);
 374int compilearrayref(struct array *ap);
 375int compilefunctioncall(struct string *sp);
 376int walkstring(struct string *sp, enum walkstringop op, int tempno);
 377int compilearray(struct array *ap);
 378void compilesimplearray(enum type *tp, char *name, int num, struct array *ap);
 379void declarearray(struct array *ap);
 380void compilebitstring(struct bits *bp);
 381void compilebitsplice(struct bitsplice *splicep);
 382int bitcount(bits x);
 383bits allbitsset(int nbits);
 384void findent(FILE *f);
 385void indent(void);
 386void *xrealloc(char *oldp, size_t size);
 387void *xmalloc(size_t size);
 388void *xstrdup(char *s);
 389int prematureeof(void);
 390
 391
 392int 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:
 412Usage:
 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
 429int 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.  */
 559struct 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};
 571struct 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.  */
 576struct 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.  */
 601int 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).  */
 628struct 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   */
 640struct 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.  */
 674struct 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.  */
 684int 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.  */
 700int 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".  */
 753int 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  */
 767struct 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.  */
 781int 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.  */
 887int 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.  */
 905struct 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.  */
 922struct 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.  */
 930struct 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.  */
 939struct 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.  */
 959enum 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.  */
1066int 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].  */
1128struct bitsplice {
1129    struct entry entry;
1130    int nbits;
1131    struct bitsplicebits *splice;
1132};
1133struct 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
1144int 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
1220int 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
1244int 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
1286int 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
1353void dumpfunctions() {
1354    struct function *fp;
1355
1356    for (fp = functions; fp != NULL; fp = fp->next)
1357        dumpfunction(fp);
1358}
1359
1360
1361void 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.  */
1374void 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
1395void 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
1429void 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
1452void showstring(FILE *f, struct string *sp) {
1453    for ( ; sp != NULL; sp = sp->next)
1454        showstringelement(f, sp);
1455}
1456
1457
1458void 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
1490void 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
1505void 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
1522const char commonpreamble[] = "\
1523typedef %s bits;\n\
1524\n\
1525";
1526
1527const char concatpreamble[] = "\
1528static char *dis_buf;\n\
1529static int dis_bufindex, dis_buflen;\n\
1530\n\
1531void *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\
1552void dis_done()\n\
1553{\n\
1554    dis_bufindex = 0;\n\
1555}\n\
1556\n\
1557";
1558
1559const char concatdeclarations[] = "\
1560#include <string.h>\n\
1561#include <stdlib.h>\n\
1562#include <errno.h>\n\
1563\n\
1564extern void *dis_realloc(void *p, size_t size); /* User-provided. */\n\
1565void *dis_alloc(size_t size);\n\
1566void dis_done(void);\n\
1567";
1568
1569const char nonconcatpreamble[] = "\
1570void dis_done() {}\n\
1571";
1572
1573
1574int 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
1607void 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
1617int 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
1640void 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
1655void 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
1681void 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
1694void 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
1736int 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
1760int 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
1778void 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
1787void 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
1810int 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
1822void 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.  */
1856int 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
1978int 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
2001int 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
2010void compileassign(int assignto) {
2011    indent();
2012    if (assignto < 0)
2013        printf("return ");
2014    else {
2015        compiletemp(assignto);
2016        printf(" = ");
2017    }
2018}
2019
2020
2021void compiletemp(int tempno) {
2022    printf("t__%d", tempno);
2023}
2024
2025
2026void 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
2042int 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
2072int 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
2082int 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
2115int 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
2127int 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
2175int 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
2217int 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
2242void 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
2271void declarearray(struct array *ap) {
2272    indent();
2273    compiletype(stdout, &ap->type);
2274    compiletemp(ap->tempno);
2275    printf(";\n");
2276}
2277
2278
2279void 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
2290void 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
2318int 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
2329bits allbitsset(int nbits) {
2330    return (nbits == MAXBITS) ? ~0 : (1 << nbits) - 1;
2331}
2332
2333
2334void 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
2344void indent() {
2345    findent(stdout);
2346}
2347
2348
2349void *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
2365void *xmalloc(size_t size) {
2366    return xrealloc(NULL, size);
2367}
2368
2369
2370void *xstrdup(char *s) {
2371    char *p;
2372
2373    p = xmalloc(strlen(s) + 1);
2374    strcpy(p, s);
2375    return p;
2376}
2377
2378
2379int prematureeof() {
2380    fprintf(stderr, "%s: %s(%d): premature end of file\n", progname, filename,
2381            lineno);
2382    return 1;
2383}
2384
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.