merentha_fluffos_v2/
merentha_fluffos_v2/bin/
merentha_fluffos_v2/fluffos-2.9-ds2.03/
merentha_fluffos_v2/fluffos-2.9-ds2.03/ChangeLog.old/
merentha_fluffos_v2/fluffos-2.9-ds2.03/Win32/
merentha_fluffos_v2/fluffos-2.9-ds2.03/compat/
merentha_fluffos_v2/fluffos-2.9-ds2.03/compat/simuls/
merentha_fluffos_v2/fluffos-2.9-ds2.03/include/
merentha_fluffos_v2/fluffos-2.9-ds2.03/testsuite/
merentha_fluffos_v2/fluffos-2.9-ds2.03/testsuite/clone/
merentha_fluffos_v2/fluffos-2.9-ds2.03/testsuite/command/
merentha_fluffos_v2/fluffos-2.9-ds2.03/testsuite/data/
merentha_fluffos_v2/fluffos-2.9-ds2.03/testsuite/etc/
merentha_fluffos_v2/fluffos-2.9-ds2.03/testsuite/include/
merentha_fluffos_v2/fluffos-2.9-ds2.03/testsuite/inherit/
merentha_fluffos_v2/fluffos-2.9-ds2.03/testsuite/inherit/master/
merentha_fluffos_v2/fluffos-2.9-ds2.03/testsuite/log/
merentha_fluffos_v2/fluffos-2.9-ds2.03/testsuite/single/
merentha_fluffos_v2/fluffos-2.9-ds2.03/testsuite/single/tests/compiler/
merentha_fluffos_v2/fluffos-2.9-ds2.03/testsuite/single/tests/efuns/
merentha_fluffos_v2/fluffos-2.9-ds2.03/testsuite/single/tests/operators/
merentha_fluffos_v2/fluffos-2.9-ds2.03/testsuite/u/
merentha_fluffos_v2/fluffos-2.9-ds2.03/tmp/
merentha_fluffos_v2/fluffos-2.9-ds2.03/windows/
merentha_fluffos_v2/lib/cfg/
merentha_fluffos_v2/lib/cfg/races/
merentha_fluffos_v2/lib/cmds/abilities/
merentha_fluffos_v2/lib/cmds/actions/
merentha_fluffos_v2/lib/cmds/spells/
merentha_fluffos_v2/lib/daemon/include/
merentha_fluffos_v2/lib/daemon/services/
merentha_fluffos_v2/lib/doc/
merentha_fluffos_v2/lib/doc/building/
merentha_fluffos_v2/lib/doc/help/classes/
merentha_fluffos_v2/lib/doc/help/general/
merentha_fluffos_v2/lib/doc/help/races/
merentha_fluffos_v2/lib/doc/help/skills/
merentha_fluffos_v2/lib/doc/help/stats/
merentha_fluffos_v2/lib/doc/man/efuns/
merentha_fluffos_v2/lib/doc/man/lfuns/
merentha_fluffos_v2/lib/doc/news/
merentha_fluffos_v2/lib/doc/old/
merentha_fluffos_v2/lib/doc/old/concepts/
merentha_fluffos_v2/lib/doc/old/lpc/constructs/
merentha_fluffos_v2/lib/doc/old/lpc/types/
merentha_fluffos_v2/lib/domains/ROOMS/
merentha_fluffos_v2/lib/domains/obj/armour/
merentha_fluffos_v2/lib/domains/obj/monsters/
merentha_fluffos_v2/lib/domains/obj/other/
merentha_fluffos_v2/lib/domains/obj/weapons/
merentha_fluffos_v2/lib/realms/petrarch/
merentha_fluffos_v2/lib/save/daemons/
merentha_fluffos_v2/lib/save/rid/
merentha_fluffos_v2/lib/save/users/a/
merentha_fluffos_v2/lib/save/users/p/
merentha_fluffos_v2/lib/save/users/t/
merentha_fluffos_v2/lib/std/login/
merentha_fluffos_v2/lib/std/obj/
merentha_fluffos_v2/win32/
#define CONFIGURE_VERSION       5

#define EDIT_SOURCE
#define NO_MALLOC
#define NO_SOCKETS
#define NO_OPCODES
#include "std.h"
#include "lex.h"
#include "preprocess.h"
#include "make_func.h"
#include "cc.h"
#include "hash.h"
#include <stdlib.h>
#include <unistd.h>

#ifdef WIN32
#include <process.h>
#include <malloc.h>
#endif

#if defined(DEBUG) || defined(WIN32)
#define TO_DEV_NULL ""
#else
#define TO_DEV_NULL ">/dev/null 2>&1"
#endif

/* Using an include file at this point would be bad */
#ifdef PEDANTIC
char *malloc(int);
char *realloc(char *, int);
void free(char *);
#endif

char *outp;
static int buffered = 0;
static int nexpands = 0;

FILE *yyin = 0, *yyout = 0;

#define SYNTAX "edit_source [-process file] [-options] [-malloc] [-build_func_spec 'command'] [-build_efuns] [-configure]\n"

/* The files we fool with.  (Actually, there are more.  See -process).
 *
 * TODO: teach this file how to fix bugs in the source code :)
 */
#define OPTIONS_INCL      "options_incl.h"
#define PACKAGES          "packages/packages"
#define OPTIONS_H         "options.h"
#define LOCAL_OPTIONS     "local_options"
#define OPTION_DEFINES    "option_defs.c"
#define FUNC_SPEC         "func_spec.c"
#define FUNC_SPEC_CPP     "func_spec.cpp"
#define EFUN_TABLE        "efunctions.h"
#define OPC_PROF          "opc.h"
#define OPCODES           "opcodes.h"
#define EFUN_PROTO        "efun_protos.h"
#define EFUN_DEFS         "efun_defs.c"

#define PRAGMA_NOTE_CASE_START 1

int num_packages = 0;
char *packages[100];
char ppchar;

char *current_file = 0;
int current_line;

int grammar_mode = 0; /* which section we're in for .y files */
int in_c_case, cquote, pragmas, block_nest;

char yytext[MAXLINE];
static char defbuf[DEFMAX];

typedef struct incstate_t {
    struct incstate_t *next;
    FILE *yyin;
    int line;
    char *file;
} incstate;

static incstate *inctop = 0;

#define CHAR_QUOTE 1
#define STRING_QUOTE 2

static void add_define (const char *, int, char *);

#ifdef WIN32
#include <io.h>

int compile(char *command) {
   FILE *tf = fopen("trash_me.bat","wt+");

   fprintf(tf,"%s%s\n%s",
        "@echo off\n",
      command,
      "if errorlevel == 1 goto error\n"
      "del trash_me.err >nul\n"
      "goto ok\n"
      ":error\n"
      "echo ERROR > trash_me.err\n"
      ":ok\n");
   fclose(tf);

   if (!system("trash_me.bat > nul")) return 1;
   if (_access("trash_me.err",0) ) return 1;
   return 0;
}
#else
int compile (char * str) {
    return system(str);
}
#endif

#if defined(WIN32) 
int dos_style_link (char * x, char * y) {
    char link_cmd[100];
    sprintf(link_cmd, "copy %s %s", x, y);
    return system(link_cmd);
}
#endif

void yyerror (const char * str)
{
    fprintf(stderr, "%s:%d: %s\n", current_file, current_line, str);
    exit(1);
}

void mf_fatal (char * str)
{
    yyerror(str);
}

void yywarn (char * str)
{
    /* ignore errors :)  local_options generates redefinition warnings,
       which we don't want to see */
}

void yyerrorp (char * str)
{
    char buff[200];
    sprintf(buff, str, ppchar);
    fprintf(stderr, "%s:%d: %s\n", current_file, current_line, buff);
    exit(1);
}

static void add_input (char * p)
{
    int l = strlen(p);

    if (outp - l < defbuf) yyerror("Macro expansion buffer overflow.\n");
    strncpy(outp - l, p, l);
    outp -= l;
}

#define SKIPW(foo) while (isspace(*foo)) foo++;

static char *skip_comment(char *tmp, int flag)
{
    int c;

    for (;;) {
        while ((c = *++tmp) !=  '*') {
            if (c == EOF) yyerror("End of file in a comment");
            if (c == '\n') {
                nexpands = 0;
                current_line++;
                if (!fgets(yytext, MAXLINE - 1, yyin)) yyerror("End of file in a comment");
                if (flag && yyout) fputs(yytext, yyout);
                tmp = yytext - 1;
            }
        }
        do {
            if ((c = *++tmp) == '/')
                return tmp + 1;
            if (c == '\n') {
                nexpands = 0;
                current_line++;
                if (!fgets(yytext, MAXLINE - 1, yyin)) yyerror("End of file in a comment");
                if (flag && yyout) fputs(yytext, yyout);
                tmp = yytext - 1;
            }
        } while (c == '*');
    }
}

static void refill()
{
    register char *p, *yyp;
    int c;

    if (fgets(p = yyp = defbuf + (DEFMAX >> 1), MAXLINE - 1, yyin)) {
      while (((c = *yyp++) != '\n') && (c != EOF)) {
          if (c == '/') {
              if ((c = *yyp) == '*') {
                  yyp = skip_comment(yyp, 0);
                  continue;
              }
              else if (c == '/') break;
          }
          *p++ = c;
      }
    }
    else yyerror("End of macro definition in \\");
    nexpands = 0;
    current_line++;
    *p = 0;
    return;
}

static void handle_define()
{
    char namebuf[NSIZE];
    char args[NARGS][NSIZE];
    char mtext[MLEN];
    char *end;
    register char *tmp = outp, *q;

    q = namebuf;
    end = q + NSIZE - 1;
    while (isalunum(*tmp)) {
        if (q < end) *q++ = *tmp++;
        else yyerror("Name too long.\n");
    }
    if (q == namebuf) yyerror("Macro name missing.\n");
    if (*namebuf != '_' && !isalpha(*namebuf)) yyerror("Invalid macro name.\n");
    *q = 0;
    if (*tmp == '(') {            /* if "function macro" */
        int arg;
        int inid;
        char *ids = (char *) NULL;

        tmp++;                    /* skip '(' */
        SKIPW(tmp);
        if (*tmp == ')') {
            arg = 0;
        } else {
            for (arg = 0; arg < NARGS;) {
                end = (q = args[arg]) + NSIZE - 1;
                while (isalunum(*tmp) || (*tmp == '#')) {
                    if (q < end) *q++ = *tmp++;
                    else yyerror("Name too long.\n");
                }
                if (q == args[arg]) {
                    char buff[200];
                    sprintf(buff, "Missing argument %d in #define parameter list", arg + 1);
                    yyerror(buff);
                }
                arg++;
                SKIPW(tmp);
                if (*tmp == ')')
                    break;
                if (*tmp++ != ',') {
                    yyerror("Missing ',' in #define parameter list");
                }
                SKIPW(tmp);
            }
            if (arg == NARGS) yyerror("Too many macro arguments");
        }
        tmp++;                    /* skip ')' */
        end = mtext + MLEN - 2;
        for (inid = 0, q = mtext; *tmp;) {
            if (isalunum(*tmp)) {
                if (!inid) {
                    inid++;
                    ids = tmp;
                }
            } else {
                if (inid) {
                    int idlen = tmp - ids;
                    int n, l;

                    for (n = 0; n < arg; n++) {
                        l = strlen(args[n]);
                        if (l == idlen && strncmp(args[n], ids, l) == 0) {
                            q -= idlen;
                            *q++ = MARKS;
                            *q++ = n + MARKS + 1;
                            break;
                        }
                    }
                    inid = 0;
                }
            }
            if ((*q = *tmp++) == MARKS) *++q = MARKS;
            if (q < end) q++;
            else yyerror("Macro text too long");
            if (!*tmp && tmp[-2] == '\\') {
                q -= 2;
                refill();
                tmp = defbuf + (DEFMAX >> 1);
            }
        }
        *--q = 0;
        add_define(namebuf, arg, mtext);
    } else if (isspace(*tmp) || (!*tmp && (*(tmp+1) = '\0', *tmp = ' '))) {
        end = mtext + MLEN - 2;
        for (q = mtext; *tmp;) {
            *q = *tmp++;
            if (q < end) q++;
            else yyerror("Macro text too long");
            if (!*tmp && tmp[-2] == '\\') {
                q -= 2;
                refill();
                tmp = defbuf + (DEFMAX >> 1);
            }
        }
        *q = 0;
        add_define(namebuf, -1, mtext);
    } else {
        yyerror("Illegal macro symbol");
    }
    return;
}

#define SKPW while (isspace(*outp)) outp++

static int cmygetc() {
    int c;

    for (;;) {
      if ((c = *outp++) == '/') {
          if ((c = *outp) == '*') outp = skip_comment(outp, 0);
          else if (c == '/') return -1;
          else return c;
      } else return c;
    }
}

/* Check if yytext is a macro and expand if it is. */
static int expand_define()
{
    defn_t *p;
    char expbuf[DEFMAX];
    char *args[NARGS];
    char buf[DEFMAX];
    char *q, *e, *b;

    if (nexpands++ > EXPANDMAX) yyerror("Too many macro expansions");
    if (!(p = lookup_define(yytext))) return 0;
    if (p->nargs == -1) {
        add_input(p->exps);
    } else {
        int c, parcnt = 0, dquote = 0, squote = 0;
        int n;

        SKPW;
        if (*outp++ != '(') yyerror("Missing '(' in macro call");
        SKPW;
        if ((c = *outp++) == ')')
            n = 0;
        else {
            q = expbuf;
            args[0] = q;
            for (n = 0; n < NARGS;) {
                switch (c) {
                case '"':
                    if (!squote)
                        dquote ^= 1;
                    break;
                case '\'':
                    if (!dquote)
                        squote ^= 1;
                    break;
                case '(':
                    if (!squote && !dquote)
                        parcnt++;
                    break;
                case ')':
                    if (!squote && !dquote)
                        parcnt--;
                    break;
                case '#':
                    if (!squote && !dquote) {
                        *q++ = c;
                        if (*outp++ != '#') yyerror("'#' expected");
                  }
                    break;
                case '\\':
                    if (squote || dquote) {
                        *q++ = c;
                        c = *outp++;
                  } break;
                case '\n':
                    if (squote || dquote) yyerror("Newline in string");
                  break;
              }
                if (c == ',' && !parcnt && !dquote && !squote) {
                    *q++ = 0;
                    args[++n] = q;
              } else if (parcnt < 0) {
                    *q++ = 0;
                    n++;
                    break;
              } else {
                    if (c == EOF) yyerror("Unexpected end of file");
                    if (q >= expbuf + DEFMAX - 5) {
                        yyerror("Macro argument overflow");
                  } else {
                        *q++ = c;
                  }
              }
                if (!squote && !dquote) {
                    if ((c = cmygetc()) < 0) yyerror("End of macro in // comment");
              }
                else c = *outp++;
          }
            if (n == NARGS) {
                yyerror("Maximum macro argument count exceeded");
                return 0;
          }
      }
        if (n != p->nargs) {
            yyerror("Wrong number of macro arguments");
            return 0;
      }
        /* Do expansion */
        b = buf;
        e = p->exps;
        while (*e) {
            if (*e == '#' && *(e + 1) == '#')
                e += 2;
            if (*e == MARKS) {
                if (*++e == MARKS)
                    *b++ = *e++;
                else {
                    for (q = args[*e++ - MARKS - 1]; *q;) {
                        *b++ = *q++;
                        if (b >= buf + DEFMAX) yyerror("Macro expansion overflow");
                  }
              }
          } else {
                *b++ = *e++;
                if (b >= buf + DEFMAX) yyerror("Macro expansion overflow");
          }
      }
        *b++ = 0;
        add_input(buf);
    }
    return 1;
}

static int exgetc()
{
    register char c, *yyp;

    SKPW;
    while (isalpha(c = *outp) || c == '_') {
      yyp = yytext;
      do {
          *yyp++ = c;
      } while (isalnum(c = *++outp) || (c == '_'));
      *yyp = '\0';
      if (!strcmp(yytext, "defined")) {
          /* handle the defined "function" in #/%if */
          SKPW;
          if (*outp++ != '(') yyerror("Missing ( after 'defined'");
          SKPW;
          yyp = yytext;
          if (isalpha(c = *outp) || c == '_') {
              do {
                  *yyp++ = c;
              } while (isalnum(c = *++outp) || (c == '_'));
              *yyp = '\0';
          }
          else yyerror("Incorrect definition macro after defined(\n");
          SKPW;
          if (*outp != ')') yyerror("Missing ) in defined");
          if (lookup_define(yytext))
              add_input("1 ");
          else
              add_input("0 ");
      } else {
          if (!expand_define())
              add_input("0 ");
          else SKPW;
      }
    }
    return c;
}

static int skip_to(char *token, char *atoken)
{
    char b[20], *p, *end;
    int c;
    int nest;

    for (nest = 0;;) {
        if (!fgets(outp = defbuf + (DEFMAX >> 1), MAXLINE-1,yyin)) {
            yyerror("Unexpected end of file while skipping");
        }
        current_line++;
        if ((c = *outp++) == ppchar) {
            while (isspace(*outp)) outp++;
            end = b + sizeof b - 1;
            for (p = b; (c = *outp++) != '\n' && !isspace(c) && c != EOF;) {
                if (p < end) *p++ = c;
            }
            *p = 0;
            if (!strcmp(b, "if") || !strcmp(b, "ifdef") || !strcmp(b, "ifndef")) {
                nest++;
            } else if (nest > 0) {
                if (!strcmp(b, "endif"))
                    nest--;
            } else {
                if (!strcmp(b, token)) {
                    *--outp = c;
                    add_input(b);
                    *--outp = ppchar;
                    buffered = 1;
                    return 1;
                } else if (atoken && !strcmp(b, atoken)) {
                    *--outp = c;
                    add_input(b);
                    *--outp = ppchar;
                    buffered = 1;
                    return 0;
                } else if (!strcmp(b, "elif")) {
                    *--outp = c;
                    add_input(b);
                    *--outp = ppchar;
                    buffered = 1;
                    return !atoken;
                }
            }
        }
    }
}

#include "preprocess.c"

static int maybe_open_input_file (char * fn) {
    if ((yyin = fopen(fn, "r")) == NULL) {
        return 0;
    }
    if (current_file) free((char *)current_file);
    current_file = (char *)malloc(strlen(fn) + 1);
    current_line = 0;
    strcpy(current_file, fn);
    return 1;
}

static void open_input_file (char * fn) {
    if (!maybe_open_input_file(fn)) {
        perror(fn);
        exit(-1);
    }
}

static void open_output_file (char * fn) {
    if ((yyout = fopen(fn, "w")) == NULL) {
        perror(fn);
        exit(-1);
    }
}

static void close_output_file() {
    fclose(yyout);
    yyout = 0;
}

static char *protect (char * p) {
    static char buf[1024];
    char *bufp = buf;

    while (*p) {
        if (*p=='"' || *p == '\\') *bufp++ = '\\';
        *bufp++ = *p++;
    }
    *bufp = 0;
    return buf;
}

static void
create_option_defines() {
    defn_t *p;
    int count = 0;
    int i;

    fprintf(stderr, "Writing build options to %s ...\n", OPTION_DEFINES);
    open_output_file(OPTION_DEFINES);
    fprintf(yyout, "{\n");
    for (i = 0; i < DEFHASH; i++) {
        for (p = defns[i]; p; p = p->next)
            if (!(p->flags & DEF_IS_UNDEFINED)) {
                count++;
                fprintf(yyout, "  \"__%s__\", \"%s\",\n",
                        p->name, protect(p->exps));
                if (strncmp(p->name, "PACKAGE_", 8)==0) {
                    int len;
                    char *tmp, *t;

                    len = strlen(p->name + 8);
                    t = tmp = (char *)malloc(len + 1);
                    strcpy(tmp, p->name + 8);
                    while (*t) {
                        if (isupper(*t))
                            *t = tolower(*t);
                        t++;
                    }
                    if (num_packages == 100) {
                        fprintf(stderr, "Too many packages.\n");
                        exit(-1);
                    }
                    packages[num_packages++] = tmp;
                }
            }
    }
    fprintf(yyout,"};\n\n#define NUM_OPTION_DEFS %d\n\n", count);
    close_output_file();
}

static void deltrail() {
    register char *p;

    p = outp;
    while (*p && !isspace(*p) && *p != '\n') {
      p++;
    }
    *p = 0;
}

static void
handle_include (char * name)
{
    char *p;
    static char buf[1024];
    FILE *f;
    incstate *is;

    if (*name != '"') {
        defn_t *d;

        if ((d = lookup_define(name)) && d->nargs == -1) {
            char *q;

            q = d->exps;
            while (isspace(*q))
                q++;
            handle_include(q);
      } else {
            yyerrorp("Missing leading \" in %cinclude");
      }
        return;
    }
    for (p = ++name; *p && *p != '"'; p++);
    if (!*p) yyerrorp("Missing trailing \" in %cinclude");

    *p = 0;
    if ((f = fopen(name, "r")) != NULL) {
        is = (incstate *)
            malloc(sizeof(incstate) /*, 61, "handle_include: 1" */);
        is->yyin = yyin;
        is->line = current_line;
        is->file = current_file;
        is->next = inctop;
        inctop = is;
        current_line = 0;
        current_file = (char *)malloc(strlen(name) + 1 /*, 62, "handle_include: 2" */);
        strcpy(current_file, name);
        yyin = f;
    } else {
        sprintf(buf, "Cannot %cinclude %s", ppchar, name);
        yyerror(buf);
    }
}

static void
handle_pragma (char * name)
{
    if (!strcmp(name, "auto_note_compiler_case_start"))
        pragmas |= PRAGMA_NOTE_CASE_START;
    else if (!strcmp(name, "no_auto_note_compiler_case_start"))
        pragmas &= ~PRAGMA_NOTE_CASE_START;
    else if (!strncmp(name, "ppchar:", 7) && *(name + 8))
        ppchar = *(name + 8);
    else yyerrorp("Unidentified %cpragma");
}

static void
preprocess() {
    register char *yyp, *yyp2;
    int c;
    int cond;

    while (buffered ? (yyp = yyp2 = outp) : fgets(yyp = yyp2 = defbuf + (DEFMAX >> 1), MAXLINE-1, yyin)) {
        if (!buffered) current_line++;
        else buffered = 0;
        while (isspace(*yyp2)) yyp2++;
        if ((c = *yyp2) == ppchar) {
            int quote = 0;
            char sp_buf = 0, *oldoutp;

            if (c == '%' && yyp2[1] == '%')
                grammar_mode++;
            outp = 0;
            if (yyp != yyp2) yyerrorp("Misplaced '%c'.\n");
            while (isspace(*++yyp2));
            yyp++;
            for (;;) {
                if ((c = *yyp2++) == '"') quote ^= 1;
                else{
                    if (!quote && c == '/') {
                        if (*yyp2 == '*') {
                            yyp2 = skip_comment(yyp2, 0);
                            continue;
                        }
                        else if (*yyp2 == '/') break;
                    }
                    if (!outp && isspace(c)) outp = yyp;
                    if (c == '\n' || c == EOF) break;
                }
                *yyp++ = c;
            }

            if (outp) {
                if (yyout) sp_buf = *(oldoutp = outp);
                *outp++ = 0;
                while (isspace(*outp)) outp++;
            }
            else outp = yyp;
            *yyp = 0;
            yyp = defbuf + (DEFMAX >> 1) + 1;

            if (!strcmp("define", yyp)) {
                handle_define();
            } else if (!strcmp("if", yyp)) {
                cond = cond_get_exp(0);
                if (*outp != '\n') yyerrorp("Condition too complex in %cif");
                else handle_cond(cond);
            } else if (!strcmp("ifdef", yyp)) {
                deltrail();
                handle_cond(lookup_define(outp) != 0);
            } else if (!strcmp("ifndef", yyp)) {
                deltrail();
                handle_cond(!lookup_define(outp));
            } else if (!strcmp("elif", yyp)) {
                handle_elif();
            } else if (!strcmp("else", yyp)) {
                handle_else();
            } else if (!strcmp("endif", yyp)) {
                handle_endif();
            } else if (!strcmp("undef", yyp)) {
                defn_t *d;

                deltrail();
                if ((d = lookup_definition(outp))) {
                    d->flags |= DEF_IS_UNDEFINED;
                    d->flags &= ~DEF_IS_NOT_LOCAL;
                } else {
                    add_define(outp, -1, " ");
                    d = lookup_definition(outp);
                    d->flags |= DEF_IS_UNDEFINED;
                    d->flags &= ~DEF_IS_NOT_LOCAL;
                }
            } else if (!strcmp("echo", yyp)) {
                fprintf(stderr, "echo at line %d of %s: %s\n", current_line, current_file, outp);
            } else if (!strcmp("include", yyp)) {
                handle_include(outp);
            } else if (!strcmp("pragma", yyp)) {
                handle_pragma(outp);
            } else if (yyout) {
                if (!strcmp("line", yyp)) {
                    fprintf(yyout, "#line %d \"%s\"\n", current_line,
                            current_file);
                } else {
                    if (sp_buf) *oldoutp = sp_buf;
                    if (pragmas & PRAGMA_NOTE_CASE_START) {
                        if (*yyp == '%') pragmas &= ~PRAGMA_NOTE_CASE_START;
                    }
                    fprintf(yyout, "%s\n", yyp-1);
                }
            } else {
                char buff[200];
                sprintf(buff, "Unrecognised %c directive : %s\n", ppchar, yyp);
                yyerror(buff);
            }
        }
        else if (c == '/') {
            if ((c = *++yyp2) == '*') {
                if (yyout) fputs(yyp, yyout);
                yyp2 = skip_comment(yyp2, 1);
            } else if (c == '/' && !yyout) continue;
            else if (yyout) {
                fprintf(yyout, "%s", yyp);
            }
        }
        else if (yyout) {
            fprintf(yyout, "%s", yyp);
            if (pragmas & PRAGMA_NOTE_CASE_START) {
                static int line_to_print;

                line_to_print = 0;

                if (!in_c_case) {
                    while (isalunum(*yyp2)) yyp2++;
                    while (isspace(*yyp2)) yyp2++;
                    if (*yyp2 == ':') {
                        in_c_case = 1;
                        yyp2++;
                    }
                }

                if (in_c_case) {
                    while ((c = *yyp2++)) {
                        switch(c) {
                          case '{':
                            {
                                if (!cquote && (++block_nest == 1))
                                    line_to_print = 1;
                                break;
                            }

                          case '}':
                            {
                                if (!cquote) {
                                    if (--block_nest < 0) yyerror("Too many }'s");
                                }
                                break;
                            }

                          case '"':
                            if (!(cquote & CHAR_QUOTE)) cquote ^= STRING_QUOTE;
                            break;

                          case '\'':
                            if (!(cquote & STRING_QUOTE)) cquote ^= CHAR_QUOTE;
                            break;

                          case '\\':
                            if (cquote && *yyp2) yyp2++;
                            break;

                          case '/':
                            if (!cquote) {
                                if ((c = *yyp2) == '*') {
                                    yyp2 = skip_comment(yyp2, 1);
                                } else if (c == '/') {
                                    *(yyp2-1) = '\n';
                                    *yyp2 = '\0';
                                }
                            }
                            break;

                          case ':':
                            if (!cquote && !block_nest)
                                yyerror("Case started before ending previous case with ;");
                            break;

                          case ';':
                            if (!cquote && !block_nest) in_c_case = 0;
                        }
                    }
                }

                if (line_to_print)
                    fprintf(yyout, "#line %d \"%s\"\n", current_line + 1,current_file);

            }
        }
    }
    if (iftop) {
      ifstate_t *p = iftop;

      while (iftop) {
          p = iftop;
          iftop = p->next;
          free((char *)p);
      }
      yyerrorp("Missing %cendif");
    }
    fclose(yyin);
    free(current_file);
    current_file = 0;
    nexpands = 0;
    if (inctop) {
      incstate *p = inctop;

      current_file = p->file;
      current_line = p->line;
      yyin = p->yyin;
      inctop = p->next;
      free((char *) p);
      preprocess();
    } else yyin = 0;
}

void make_efun_tables()
{
#define NUM_FILES     5
    static char* outfiles[NUM_FILES] = {
        EFUN_TABLE, OPC_PROF, OPCODES, EFUN_PROTO, EFUN_DEFS
    };
    FILE *files[NUM_FILES];
    int i;

    fprintf(stderr, "Building efun tables ...\n");
    for (i = 0; i < NUM_FILES; i++) {
        files[i] = fopen(outfiles[i], "w");
        if (!files[i]) {
            fprintf(stderr, "make_func: unable to open %s\n", outfiles[i]);
            exit(-1);
        }
        fprintf(files[i],
                "/*\n\tThis file is automatically generated by make_func.\n");
        fprintf(files[i],
                "\tdo not make any manual changes to this file.\n*/\n\n");
    }

    fprintf(files[0],"\n#include \"efun_protos.h\"\n\n");
    fprintf(files[0],"\ntypedef void (*func_t) (void);\n\n");
    fprintf(files[0],"func_t efun_table[] = {\n");

    fprintf(files[1],"\ntypedef struct opc_s { char *name; int count; } opc_t;\n\n");
    fprintf(files[1],"opc_t opc_efun[] = {\n");

    fprintf(files[2], "\n/* operators */\n\n");
    for (i = 0; i < op_code; i++) {
        fprintf(files[2],"#define %-30s %d\n", oper_codes[i], i+1);
    }

    fprintf(files[2],"\n/* 1 arg efuns */\n#define BASE %d\n\n", op_code+1);
    for (i = 0; i < efun1_code; i++) {
        fprintf(files[0],"\tf_%s,\n", efun1_names[i]);
        fprintf(files[1],"{\"%s\", 0},\n", efun1_names[i]);
        fprintf(files[2],"#define %-30s %d\n", efun1_codes[i], i+op_code+1);
        fprintf(files[3],"void f_%s (void);\n", efun1_names[i]);
    }

    fprintf(files[2],"\n/* efuns */\n#define ONEARG_MAX %d\n\n", efun1_code + op_code+1);
    for (i = 0; i < efun_code; i++) {
        fprintf(files[0],"\tf_%s,\n", efun_names[i]);
        fprintf(files[1],"{\"%s\", 0},\n", efun_names[i]);
        fprintf(files[2],"#define %-30s %d\n", efun_codes[i], i+op_code+efun1_code+1);
        fprintf(files[3],"void f_%s (void);\n", efun_names[i]);
    }
    fprintf(files[0], "};\n");
    fprintf(files[1], "};\n");

    if (efun1_code + op_code >= 256) {
        fprintf(stderr, "You have way too many efuns.  Contact the MudOS developers if you really need this many.\n");
    }
    if (efun_code >= 256) {
        fprintf(stderr, "You have way too many efuns.  Contact the MudOS developers if you really need this many.\n");
    }
    fprintf(files[2],"\n/* efuns */\n#define NUM_OPCODES %d\n\n", efun_code + efun1_code + op_code);

    /* Now sort the main_list */
    for (i = 0; i < num_buff; i++) {
       int j;
       for (j = 0; j < i; j++)
           if (strcmp(key[i], key[j]) < 0) {
              char *tmp;
              tmp = key[i]; key[i] = key[j]; key[j] = tmp;
              tmp = buf[i]; buf[i] = buf[j]; buf[j] = tmp;
           }
    }

    /* Now display it... */
    fprintf(files[4], "{\n");
    for (i = 0; i < num_buff; i++)
        fprintf(files[4], "%s", buf[i]);
    fprintf(files[4], "\n};\nint efun_arg_types[] = {\n");
    for (i=0; i < last_current_type; i++) {
        if (arg_types[i] == 0)
            fprintf(files[4], "0,\n");
        else
            fprintf(files[4], "%s,", ctype(arg_types[i]));
    }
    fprintf(files[4],"};\n");

    for (i=0; i < NUM_FILES; i++)
        fclose(files[i]);
}

static void handle_local_defines(int check) {
    defn_t *p;
    int i;
    int problem = 0;

    for (i = 0; i < DEFHASH; i++)
        for (p = defns[i]; p; p = p->next)
            p->flags |= DEF_IS_NOT_LOCAL;

    /* undefine _OPTIONS_H_ so it doesn't get propagated to the mudlib
       or interfere with copies of options.h */
    if ((p = lookup_define("_OPTIONS_H_"))) {
        p->flags |= DEF_IS_UNDEFINED;
        p->flags &= ~DEF_IS_NOT_LOCAL;
    }
    if ((p = lookup_define("DEBUG")))
        p->flags &= ~DEF_IS_NOT_LOCAL;

    ppchar = '#';
    preprocess();

    if ((p = lookup_define("_OPTIONS_H_")))
        p->flags |= DEF_IS_UNDEFINED;

    if (!check)
        return;

    for (i = 0; i < DEFHASH; i++)
        for (p = defns[i]; p; p = p->next)
            if (p->flags & DEF_IS_NOT_LOCAL) {
                fprintf(stderr, "No setting for %s in '%s'.\n",
                        p->name, LOCAL_OPTIONS);
                problem = 1;
            }

    if (problem) {
        fprintf(stderr, "\
***This local_options file appears to have been written for an\n\
***earlier version of the MudOS driver.  Please lookup the new options\n\
***(mentioned above) in the options.h file, decide how you would like them\n\
***set, and add those settings to the local_options file.\n");
        exit(-1);
    }
}

static void write_options_incl (int local) {
    open_output_file(OPTIONS_INCL);
    if (local) {
        fprintf(yyout, "#include \"%s\"\n", LOCAL_OPTIONS);
    } else {
        fprintf(yyout, "#include \"%s\"\n", OPTIONS_H);
    }
    close_output_file();
}

static void handle_options(int full) {
    open_input_file(OPTIONS_H);
    ppchar = '#';
    preprocess();

    if (!full) {
        /* don't do any checking, just find out what is defined */
        if (maybe_open_input_file(LOCAL_OPTIONS))
            handle_local_defines(0);
        return;
    }

    if (maybe_open_input_file(LOCAL_OPTIONS)) {
        fprintf(stdout, "Using '%s' file ...\n", LOCAL_OPTIONS);
        handle_local_defines(1);
        write_options_incl(1);
    } else {
        fprintf(stderr, "No \"%s\" file present.  If you create one from \"%s\",\nyou can use it when you get a new driver, and you will be warned if there are\nchanges to the real %s which you should include in your local file.\n",
                LOCAL_OPTIONS, OPTIONS_H, OPTIONS_H);
        write_options_incl(0);
    }

    create_option_defines();
}

static void handle_build_func_spec (char * command) {
    char buf[1024];
    int i;

    fprintf(stderr, "Building compiler files ...\n");
    sprintf(buf, "%s %s >%s", command, FUNC_SPEC, FUNC_SPEC_CPP);
    system(buf);
    for (i = 0; i < num_packages; i++) {
        sprintf(buf, "%s -I. packages/%s_spec.c >>%s",
                command, packages[i], FUNC_SPEC_CPP);
        system(buf);
    }

    open_output_file(PACKAGES);
    fprintf(yyout, "SRC=");
    for (i=0; i < num_packages; i++)
        fprintf(yyout, "%s.c ", packages[i]);
    fprintf(yyout, "\nOBJ=");
    for (i=0; i < num_packages; i++)
        fprintf(yyout, "%s.$(O) ", packages[i]);
    fprintf(yyout, "\n");
    close_output_file();
}

static void handle_process (char * file) {
    char buf[1024];
    int l;

    strcpy(buf, file);
    l = strlen(buf);
    if (strcmp(buf + l - 4, ".pre")) {
        fprintf(stderr, "Filename for -process must end in .pre\n");
        exit(-1);
    }
    *(buf + l - 4) = 0;

    fprintf(stderr, "Creating '%s' from '%s' ...\n", buf, file);

#ifdef DEBUG
    /* pass down the DEBUG define from CFLAGS */
    add_define("DEBUG", -1, " ");
#endif

    open_input_file(file);
    open_output_file(buf);
    ppchar = '%';
    preprocess();
    close_output_file();
}

static void handle_build_efuns() {
    void yyparse();

    num_buff = op_code = efun_code = efun1_code = 0;

    open_input_file(FUNC_SPEC_CPP);
    yyparse();
    make_efun_tables();
}

static void handle_applies() {
    FILE *f = fopen("applies", "r");
    FILE *out = fopen("applies.h", "w");
    FILE *table = fopen("applies_table.c", "w");
    char buf[8192];
    char *colon;
    char *p;
    int apply_number = 0;

    fprintf(out, "/* autogenerated from 'applies' */\n#ifndef APPLIES_H\n#define APPLIES_H\n\nextern char *applies_table[];\n\n/* the folowing must be the first character of __INIT */\n#define APPLY___INIT_SPECIAL_CHAR\t\t'#'\n");
    fprintf(table, "/* autogenerated from 'applies' */\n\nchar *applies_table[] = {\n");

    while (fgets(buf, 8192, f)) {
        buf[strlen(buf)-1] = 0;
        if (buf[0] == '#') break;
        if ((colon = strchr(buf, ':'))) {
            *colon++ = 0;
            fprintf(out, "#define APPLY_%-30s\t\"%s\"\n", buf, colon);
        } else {
            fprintf(out, "#define APPLY_%-30s\t", buf);
            p = buf;
            while (*p) {
                *p = tolower(*p);
                p++;
            }
            fprintf(out, "\"%s\"\n", buf);
        }
    }
    while (fgets(buf, 8192, f)) {
        buf[strlen(buf)-1] = 0;
        if ((colon = strchr(buf, ':'))) {
            *colon++ = 0;
            fprintf(table, "\t\"%s\",\n", colon);
            fprintf(out, "#define APPLY_%-30s\t%i\n", buf, apply_number++);
        } else {
            fprintf(out, "#define APPLY_%-30s\t%i\n", buf, apply_number++);
            p = buf;
            while (*p) {
                *p = tolower(*p);
                p++;
            }
            fprintf(table, "\t\"%s\",\n", buf);
        }
    }

    fprintf(table, "};\n");
    fprintf(out, "\n#define NUM_MASTER_APPLIES\t%i\n\n#endif\n", apply_number);

    fclose(out);
    fclose(table);
    fclose(f);
}

static void handle_malloc() {
#ifdef PEDANTIC
    int unlink(char *);
    int link(char *, char *);
#endif

    char *the_malloc = 0, *the_wrapper = 0;

    if (lookup_define("SYSMALLOC"))
        the_malloc = "sysmalloc.c";
    if (lookup_define("SMALLOC"))
        the_malloc = "smalloc.c";
    if (lookup_define("BSDMALLOC"))
        the_malloc = "bsdmalloc.c";
    if (lookup_define("MMALLOC"))
        the_malloc = "mmalloc.c";
    if (lookup_define("GNUMALLOC"))
        the_malloc = "gnumalloc.c";

    if (lookup_define("WRAPPEDMALLOC"))
        the_wrapper = "wrappedmalloc.c";
    if (lookup_define("DEBUGMALLOC"))
        the_wrapper = "debugmalloc.c";

    if (!the_malloc && !the_wrapper) {
        fprintf(stderr, "Memory package and/or malloc wrapper incorrectly specified in options.h\n");
        exit(-1);
    }

    if (unlink("malloc.c") == -1 && errno != ENOENT)
        perror("unlink malloc.c");
    if (unlink("mallocwrapper.c") == -1 && errno != ENOENT)
        perror("unlink mallocwrapper.c");

    if (the_wrapper) {
        printf("Using memory allocation package: %s\n\t\tWrapped with: %s\n",
               the_malloc, the_wrapper);
        if (link(the_wrapper, "mallocwrapper.c") == -1)
            perror("link mallocwrapper.c");
    } else {
        printf("Using memory allocation package: %s\n", the_malloc);
    }
    if (link(the_malloc, "malloc.c") == -1)
        perror("link malloc.c");
}

static int check_include2 (char * tag, char * file,
                             char * before, char * after) {
    char buf[1024];
    FILE *ct;

    printf("Checking for include file <%s> ... ", file);
    ct = fopen("comptest.c", "w");
    fprintf(ct, "#include \"configure.h\"\n#include \"std_incl.h\"\n%s\n#include <%s>\n%s\n",
            before, file, after);
     fclose(ct);

    sprintf(buf, "%s %s -c comptest.c " TO_DEV_NULL, COMPILER, CFLAGS);
    if (!compile(buf)) {
        fprintf(yyout, "#define %s\n", tag);
        /* Make sure the define exists for later checks */
        fflush(yyout);
        printf("exists\n");
        return 1;
    }
    printf("does not exist or is unusable\n");
    return 0;
}

static int check_include (char * tag, char * file) {
    char buf[1024];
    FILE *ct;

    printf("Checking for include file <%s> ... ", file);
    ct = fopen("comptest.c", "w");
    fprintf(ct, "#include \"configure.h\"\n#include \"std_incl.h\"\n#include \"file_incl.h\"\n#include <%s>\n", file);
    fclose(ct);

    sprintf(buf, "%s %s -c comptest.c " TO_DEV_NULL, COMPILER, CFLAGS);
    if (!compile(buf)) {
        fprintf(yyout, "#define %s\n", tag);
        /* Make sure the define exists for later checks */
        fflush(yyout);
        printf("exists\n");
        return 1;
    }
    printf("does not exist\n");
    return 0;
}

static int check_library (char * lib) {
    char buf[1024];
    FILE *ct;

    printf("Checking for library %s ... ", lib);
    ct = fopen("comptest.c", "w");
    fprintf(ct, "int main() { exit(0); }\n");
    fclose(ct);

    sprintf(buf, "%s %s comptest.c %s" TO_DEV_NULL, COMPILER, CFLAGS, lib);
    if (!compile(buf)) {
        fprintf(yyout, " %s", lib);
        printf("exists\n");
        return 1;
    }
    printf("does not exist\n");
    return 0;
}

#if 0 /* not used any more */
static int check_ret_type (char * tag, char * pre,
                             char * type, char * func) {
    char buf[1024];
    FILE *ct;

    printf("Checking return type of %s() ...", func);
    ct = fopen("comptest.c", "w");
    fprintf(ct, "%s\n\n%s%s();\n", pre, type, func);
    fclose(ct);

    sprintf(buf, "%s %s -c comptest.c >/dev/null 2>&1", COMPILER, CFLAGS);
    if (!system(buf)) {
        fprintf(yyout, "#define %s\n", tag);
        printf("returns %s\n", type);
        return 1;
    }
    printf("does not return %s\n", type);
    return 0;
}
#endif

/* This should check a.out existence, not exit value */
static int check_prog (char * tag, char * pre, char * code, int andrun) {
    char buf[1024];
    FILE *ct;

    ct = fopen("comptest.c", "w");
    fprintf(ct, "#include \"configure.h\"\n#include \"std_incl.h\"\n%s\n\nint main() {%s}\n", (pre ? pre : ""), code);
    fclose(ct);

    sprintf(buf, "%s %s comptest.c -o comptest" TO_DEV_NULL, COMPILER, CFLAGS);
    if (!compile(buf) && (!andrun || !system("./comptest"))) {
        if (tag) {
            fprintf(yyout, "#define %s\n", tag);
            fflush(yyout);
        }
        return 1;
    }

    return 0;
}

static int check_code (char * pre, char * code) {
    char buf[1024];
    FILE *ct;
    int rc;

    ct = fopen("comptest.c", "w");
    fprintf(ct, "#include \"configure.h\"\n#include \"std_incl.h\"\n%s\n\nint main() {%s}\n", (pre ? pre : ""), code);
    fclose(ct);

    sprintf(buf, "%s %s comptest.c -o comptest" TO_DEV_NULL, COMPILER, CFLAGS);
    if (compile(buf) || (rc = system("./comptest")) == 127 || rc == -1) {
        return -1;
    }
    return rc;
}

static void check_linux_libc() {
    char buf[1024];
    FILE *ct;

    ct = fopen("comptest.c", "w");
    fprintf(ct, "int main() { }\n");
    fclose(ct);

    sprintf(buf, "%s -g comptest.c -o comptest >/dev/null 2>&1", COMPILER);
    if (system(buf)) {
        fprintf(stderr, "   libg.a/so installed wrong, trying workaround ...\n");
        sprintf(buf, "%s -g comptest.c -lc -o comptest >/dev/null 2>&1", COMPILER);
        if (system(buf)) {
            fprintf(stderr, "*** FAILED.\n");
            exit(-1);
        }
        fprintf(yyout, " -lc");
    }
}

static char *memmove_prog = "\
char buf[80];\n\
strcpy(buf,\"0123456789ABCDEF\");\n\
memmove(&buf[1],&buf[4],13);\n\
if(strcmp(buf,\"0456789ABCDEF\")) exit(-1);\n\
memmove(&buf[8],&buf[6],9);\n\
if(strcmp(buf,\"0456789A9ABCDEF\")) exit(-1);\n\
return 0;\n";

static int check_memmove (char * tag, char * str) {
    return check_prog(tag, str, memmove_prog, 1);
}

static void find_memmove() {
    printf("Checking for memmove() ...");
    if (check_memmove(0, "")) {
        printf(" exists\n");
        return;
    }
    if (check_memmove("USE_BCOPY", "#define memmove(a,b,c) bcopy(b,a,c)")) {
        printf(" simulating via bcopy()\n");
        return;
    }
    printf(" missing; using MudOS's version\n");
    fprintf(yyout, "#define MEMMOVE_MISSING\n");
}

static void verbose_check_prog (char * msg, char * def, char * pre,
                                  char * prog, int andrun) {
    printf("%s ...", msg);
    if (check_prog(def, pre, prog, andrun))
        printf(" exists\n");
    else printf(" does not exist\n");
}

static int check_configure_version() {
    char buf[1024];
    FILE *ct;

    ct = fopen("comptest.c", "w");
    fprintf(ct, "#include \"configure.h\"\n\n#if CONFIGURE_VERSION < %i\nthrash and die\n#endif\n\nint main() { }\n", CONFIGURE_VERSION);
    fclose(ct);

    sprintf(buf, "%s %s comptest.c -o comptest " TO_DEV_NULL, COMPILER, CFLAGS);
    return !compile(buf);
}

static void handle_configure() {
    if (check_configure_version()) return;

    open_output_file("configure.h");

#ifndef WIN32
    check_include("INCL_STDLIB_H", "stdlib.h");
    check_include("INCL_UNISTD_H", "unistd.h");
    if (check_include("INCL_TIME_H", "time.h")) {
        if (!check_prog(0, "#include <time.h>", "tzset();", 0)) {
            if (check_prog(0, 0, "void tzset(); tzset();", 0))
                fprintf(yyout, "#define PROTO_TZSET\n#define USE_TZSET\n");
        }
        else
            fprintf(yyout, "#define USE_TZSET\n");
    } else {
        if (check_prog(0, 0, "void tzset(); tzset();", 0))
            fprintf(yyout, "#define PROTO_TZSET\n#define USE_TZSET\n");
    }
    check_include("INCL_SYS_TIMES_H", "sys/times.h");
    check_include("INCL_FCNTL_H", "fcntl.h");
    check_include("INCL_SYS_TIME_H", "sys/time.h");
    check_include("INCL_DOS_H", "dos.h");
    check_include("INCL_USCLKC_H", "usclkc.h");
    check_include("INCL_LIMITS_H", "limits.h");
    check_include("INCL_LOCALE_H", "locale.h");
    if (!check_prog(0, 0, "int x = USHRT_MAX;", 0)) {
        if (!check_prog(0, 0, "int x = MAXSHORT;", 0))
            check_include("INCL_VALUES_H", "values.h");
        fprintf(yyout, "#define USHRT_MAX  (MAXSHORT)\n");
    }

    check_include("INCL_NETINET_IN_H", "netinet/in.h");
    check_include("INCL_ARPA_INET_H", "arpa/inet.h");

    check_include("INCL_SYS_TYPES_H", "sys/types.h");
    check_include("INCL_SYS_IOCTL_H", "sys/ioctl.h");
    check_include("INCL_SYS_SOCKET_H", "sys/socket.h");
    check_include("INCL_NETDB_H", "netdb.h");
    /* TELOPT_NAWS is missing from <arpa/telnet.h> on some systems */
    check_include2("INCL_ARPA_TELNET_H", "arpa/telnet.h", "", "int i=TELOPT_NAWS;");
    check_include("INCL_SYS_SEMA_H", "sys/sema.h");
    check_include("INCL_SYS_SOCKETVAR_H", "sys/socketvar.h");
    check_include("INCL_SOCKET_H", "socket.h");
    check_include("INCL_RESOLVE_H", "resolve.h");

    check_include("INCL_SYS_STAT_H", "sys/stat.h");

    /* sys/dir.h is BSD, dirent is sys V.  Try to do it the BSD way first. */
    /* If that fails, fall back to sys V */
    if (check_prog("BSD_READDIR", "#include <sys/dir.h>", "struct direct *d; d->d_namlen;", 0)) {
        check_include("INCL_SYS_DIR_H", "sys/dir.h");
    } else {
        /* could be either of these */
        check_include("INCL_DIRENT_H", "dirent.h");
        check_include("INCL_SYS_DIRENT_H", "sys/dirent.h");
        fprintf(yyout, "#define USE_STRUCT_DIRENT\n");
    }

    check_include("INCL_SYS_FILIO_H", "sys/filio.h");
    check_include("INCL_SYS_SOCKIO_H", "sys/sockio.h");
    check_include("INCL_SYS_MKDEV_H", "sys/mkdev.h");
    check_include("INCL_SYS_RESOURCE_H", "sys/resource.h");
    check_include("INCL_SYS_RUSAGE_H", "sys/rusage.h");
    check_include("INCL_SYS_WAIT_H", "sys/wait.h");
    check_include("INCL_SYS_CRYPT_H", "sys/crypt.h");
    check_include("INCL_CRYPT_H", "crypt.h");
    check_include("INCL_MALLOC_H", "my_malloc.h");

    /* for NeXT */
    if (!check_include("INCL_MACH_MACH_H", "mach/mach.h"))
        check_include("INCL_MACH_H", "mach.h");

    /* figure out what we need to do to get major()/minor() */
    check_include("INCL_SYS_SYSMACROS_H", "sys/sysmacros.h");

#ifdef DEBUG
    /* includes just to shut up gcc's warnings on some systems */
    check_include("INCL_BSTRING_H", "bstring.h");
#endif

    /* Runtime loading support */
    if (check_include("INCL_DLFCN_H", "dlfcn.h")) {
        if (!check_prog(0, "#include <dlfcn.h>", "int x = RTLD_LAZY;", 0))
            fprintf(yyout, "#define RTLD_LAZY      1\n");
    } else {
        if (!check_prog(0, 0, "int x = RTLD_LAZY;", 0))
            fprintf(yyout, "#define RTLD_LAZY     1\n");
    }

    /* SunOS is missing definition for INADDR_NONE */
    printf("Checking for missing INADDR_NONE ... ");
    if (!check_prog(0, "#include <netinet/in.h>", "int x = INADDR_NONE;", 0)) {
        printf("missing\n");
        fprintf(yyout, "#define INADDR_NONE (unsigned int)0xffffffff\n");
    } else printf("ok\n");

    printf("Checking for random number generator ...");
    if (check_prog("DRAND48", 0, "srand48(0);", 0)) {
        printf(" using drand48()\n");
    } else
    if (check_prog("RAND", 0, "srand(0);", 0)) {
        printf(" using rand()\n");
    } else
    if (check_prog("RANDOM", 0, "srandom(0);", 0)) {
        printf("using random()\n");
    } else {
        printf("WARNING: did not find a random number generator\n");
        exit(-1);
    }

    if (check_prog("USE_BSD_SIGNALS", 0, "SIGCHLD; wait3(0, 0, 0);", 0)) {
        printf("Using BSD signals.\n");
    } else {
        printf("Using System V signals.\n");
    }

    printf("Checking if signal() returns SIG_ERR on error ...");
    if (check_prog("SIGNAL_ERROR SIG_ERR", 0, "if (signal(0, 0) == SIG_ERR) ;", 0)) {
        printf(" yes\n");
    } else {
        fprintf(yyout, "#define SIGNAL_ERROR BADSIG\n");
        printf(" no\n");
    }

    printf("Checking for inline ...");
    if (!check_prog("INLINE inline", "inline void foo() { }", "foo();", 0)) {
        printf(" __inline ...");
        if (!check_prog("INLINE __inline", "__inline void foo() {}", "foo();", 0)) {
            fprintf(yyout, "#define INLINE\n");
        }
    }
    printf(" const ...\n");
    if (!check_prog("CONST const", "int foo(const int *, const int *);", "", 0))
        fprintf(yyout, "#define CONST\n");

    verbose_check_prog("Checking for strerror()", "HAS_STRERROR",
                       "", "strerror(12);", 0);
    verbose_check_prog("Checking for POSIX getcwd()", "HAS_GETCWD",
                       "", "getcwd(\"\", 1000);", 0);
    verbose_check_prog("Checking for getrusage()", "RUSAGE",
                       "", "getrusage(0, 0);", 0);
    verbose_check_prog("Checking for times()", "TIMES",
                       "", "times(0);", 0);
    verbose_check_prog("Checking for gettimeofday()", "HAS_GETTIMEOFDAY",
                       "", "gettimeofday(0, 0);", 0);
    verbose_check_prog("Checking for fchmod()", "HAS_FCHMOD",
                       "", "fchmod(0, 0);", 0);

    printf("Checking for big or little endian ... ");
    if (!check_code("char num[] = { 0x11, 0x22, 0x33, 0x44 }; int *foo = (int *)num;",
                    "return (*foo == 0x44332211);")) {
        printf("big\n");
        fprintf(yyout, "#define BIGENDIAN 1\n");
        fflush(yyout);
    } else printf("little\n");

    find_memmove();
#endif

    fprintf(yyout, "#define SIZEOF_INT %i\n", sizeof(int));
    fprintf(yyout, "#define SIZEOF_PTR %i\n", sizeof(char *));
    fprintf(yyout, "#define SIZEOF_SHORT %i\n", sizeof(short));
    fprintf(yyout, "#define SIZEOF_FLOAT %i\n", sizeof(float));
    fprintf(yyout, "#define SIZEOF_LONG %i\n", sizeof(long));

    if (sizeof(unsigned long) == 4)
        fprintf(yyout, "#define UINT32 unsigned long\n");
    else if (sizeof(unsigned int) == 4)
        fprintf(yyout, "#define UINT32 unsigned int\n");
    else {
        printf("WARNING: could not find a 32 bit integral type.\n");
        exit(-1);
    }

    /* PACKAGE_DB stuff */
    if (lookup_define("PACKAGE_DB")) {
        /* -I would be nicer for added include paths, but we don't have an easy way to
         * set -I paths right now
         */
        if (lookup_define("USE_MSQL")) {
            if (!(check_include("INCL_LOCAL_MSQL_H", "/usr/local/include/msql.h")
                || check_include("INCL_LOCAL_MSQL_MSQL_H", "/usr/local/msql/include/msql.h")
                || check_include("INCL_LOCAL_MINERVA_MSQL_H", "/usr/local/Minerva/include/msql.h")
                || check_include("INCL_LIB_HUGHES_MSQL_H", "/usr/lib/Hughes/include/msql.h"))) {
                fprintf(stderr, "Cannot find msql.h, compilation is going to fail miserably.\n");
            }
        }
        if (lookup_define("USE_MYSQL")) {
            if (!(check_include("INCL_LOCAL_MYSQL_H", "/usr/local/include/mysql.h")
                || check_include("INCL_LOCAL_INCLUDE_MYSQL_MYSQL_H", "/usr/local/include/mysql/mysql.h")
                || check_include("INCL_LOCAL_MYSQL_MYSQL_H", "/usr/local/mysql/include/mysql.h")
                || check_include("INCL_MYSQL_MYSQL_H", "/usr/include/mysql/mysql.h"))) {
                fprintf(stderr, "Cannot find mysql.h, compilation is going to fail miserably.\n");
            }
        }
    }

    fprintf(yyout, "#define CONFIGURE_VERSION   %i\n\n", CONFIGURE_VERSION);

    close_output_file();

#ifdef WIN32
    system("echo Windows detected. Applying libs.");
    system("echo  -lwsock32 -lws2_32 > system_libs");
    system("copy windows\\configure.h tmp.config.h");
    system("type configure.h >> tmp.config.h");
    system("del configure.h");
    system("rename tmp.config.h configure.h");
#else

    open_output_file("system_libs");
    check_library("-lresolv");
    check_library("-lbsd");
    check_library("-lBSD");
    check_library("-ly");

    /* don't add -lcrypt if crypt() is in libc.a */
    if (!check_prog(0, "#include \"lint.h\"",
                    "char *x = crypt(\"foo\", \"bar\");", 0))
        check_library("-lcrypt");
    /* don't add -lmalloc if malloc() works */
    if (!check_prog(0, "", "char *x = malloc(100);", 0))
        check_library("-lmalloc");

    if (!check_prog(0, "", "void *x = dlopen(0, 0);", 0))
        check_library("-ldl");

    check_library("-lsocket");
    check_library("-linet");
    check_library("-lnsl");
    check_library("-lnsl_s");
    check_library("-lseq");
    check_library("-lm");

    if (lookup_define("MINGW")){
        check_library("-lwsock32");
        check_library("-lws2_32");
    }

    if (lookup_define("HAVE_ZLIB"))
        check_library("-lz");

    fprintf(stderr, "Checking for flaky Linux systems ...\n");
    check_linux_libc();

    /* PACKAGE_DB stuff */
    if (lookup_define("PACKAGE_DB") && lookup_define("USE_MSQL")) {
        if (!(check_library("-lmsql") ||
              check_library("-L/usr/local/lib -lmsql") ||
              check_library("-L/usr/local/msql/lib -lmsql") ||
              check_library("-L/usr/local/Minerva/lib -lmsql") ||
              check_library("-L/usr/lib/Hughes/lib -lmsql"))) {
            fprintf(stderr, "Cannot find libmsql.a, compilation is going to fail miserably\n");
        }
    }
    if (lookup_define("PACKAGE_DB") && lookup_define("USE_MYSQL")) {
        if (!(check_library("-lmysqlclient") ||
              check_library("-L/usr/local/lib -lmysqlclient") ||
              check_library("-L/usr/local/lib/mysql -lmysqlclient") ||
              check_library("-L/usr/local/mysql/lib -lmysqlclient"))) {
            fprintf(stderr, "Cannot find libmysqlclient.a, compilation is going to fail miserably\n");
        }
    }

    fprintf(yyout, "\n\n");
    close_output_file();
#endif
}

int main (int argc, char ** argv) {
    int idx = 1;

    while (idx < argc) {
        if (argv[idx][0] != '-') {
            fprintf(stderr, SYNTAX);
            exit(-1);
        }
        if (strcmp(argv[idx], "-configure")==0) {
            handle_options(0);
            handle_configure();
        } else
        if (strcmp(argv[idx], "-process")==0) {
            handle_process(argv[++idx]);
        } else
        if (strcmp(argv[idx], "-options")==0) {
            handle_options(1);
        } else
        if (strcmp(argv[idx], "-malloc")==0) {
            handle_malloc();
        } else
        if (strcmp(argv[idx], "-build_applies")==0) {
            handle_applies();
        } else
        if (strcmp(argv[idx], "-build_func_spec")==0) {
            handle_build_func_spec(argv[++idx]);
        } else
        if (strcmp(argv[idx], "-build_efuns")==0) {
            handle_build_efuns();
        } else {
            fprintf(stderr, "Unrecognized flag %s\n", argv[idx]);
            exit(-1);
        }
        idx++;
    }
    printf("\n");
    return 0;
}