Example #1
1
File: rc.c Project: mingpen/OpenNT
int _CRTAPI1
rc_main(
    int argc,
    char**argv
    )
{
    PCHAR       r;
    PCHAR       x;
    PCHAR       s1, s2, s3;
    int         n;
    PCHAR       pchIncludeT;
    ULONG       cchIncludeMax;
    int         fInclude = TRUE;        /* by default, search INCLUDE */
    int         fIncludeCurrentFirst = TRUE; /* by default, add current dir to start of includes */
    int         cDefine = 0;
    int         cUnDefine = 0;
    PCHAR       pszDefine[cDefineMax];
    PCHAR       pszUnDefine[cDefineMax];
    CHAR        szDrive[_MAX_DRIVE];
    CHAR        szDir[_MAX_DIR];
    CHAR        szFName[_MAX_FNAME];
    CHAR        szExt[_MAX_EXT];
    CHAR        szFullPath[_MAX_PATH];
    CHAR        szIncPath[_MAX_PATH];
    CHAR        buf[10];
    CHAR        *szRC;
    PCHAR       *ppargv;
    int         rcpp_argc;

    /* Set up for this run of RC */
    if (_setjmp(jb)) {
        return Nerrors;
    }

    hHeap = RCInit();
    if (hHeap == NULL) {
        SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(1120), 0x01000000);
        quit(Msg_Text);
    }

    pchInclude = pchIncludeT = MyAlloc(_MAX_PATH*2);
    cchIncludeMax = _MAX_PATH*2;

    szRC = argv[0];

    /* process the command line switches */
    while ((argc > 1) && (IsSwitchChar(*argv[1]))) {
        switch (toupper(argv[1][1])) {
            case '?':
            case 'H':
                /* print out help, and quit */
                SendError("\n");
                SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(10001),
                        VER_PRODUCTVERSION_STR, VER_PRODUCTBUILD);
                SendError(Msg_Text);
                SendError(GET_MSG(20001));
                SendError("\n");

                return 0;   /* can just return - nothing to cleanup, yet. */

            case 'B':
                if (toupper(argv[1][2]) == 'R') {   /* base resource id */
                    unsigned long id;
                    if (isdigit(argv[1][3]))
                        argv[1] += 3;
                    else if (argv[1][3] == ':')
                        argv[1] += 4;
                    else {
                        argc--;
                        argv++;
                        if (argc <= 1)
                            goto BadId;
                    }
                    if (*(argv[1]) == 0)
                        goto BadId;
                    id = atoi(argv[1]);
                    if (id < 1 || id > 32767)
                        quit(GET_MSG(1210));
                    idBase = (WORD)id;
                    break;

BadId:
                    quit(GET_MSG(1209));
                }
                break;

            case 'C':
                /* Check for the existence of CodePage Number */
                if (argv[1][2])
                    argv[1] += 2;
                else {
                    argc--;
                    argv++;
                }

                /* Now argv point to first digit of CodePage */

                if (!argv[1])
                    quit(GET_MSG(1204));

                uiCodePage = atoi(argv[1]);

                if (uiCodePage == 0)
                    quit(GET_MSG(1205));

                /* Check if uiCodePage exist in registry. */
                if (!IsValidCodePage (uiCodePage))
                    quit(GET_MSG(1206));
                break;

            case 'D':
                /* if not attached to switch, skip to next */
                if (argv[1][2])
                    argv[1] += 2;
                else {
                    argc--;
                    argv++;
                }

                /* remember pointer to string */
                pszDefine[cDefine++] = argv[1];
                if (cDefine > cDefineMax) {
                    SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(1105), argv[1]);
                    quit(Msg_Text);
                }
                break;

            case 'F':
                switch (toupper(argv[1][2])) {
                    case 'O':
                        if (argv[1][3])
                            argv[1] += 3;
                        else {
                            argc--;
                            argv++;
                        }
                        if (argc > 1)
                            strcpy(resname, argv[1]);
                        else
                            quit(GET_MSG(1101));

                        break;

                    default:
                        SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(1103), argv[1]);
                        quit(Msg_Text);
                }
                break;

            case 'I':
                /* add string to directories to search */
                /* note: format is <path>\0<path>\0\0 */

                /* if not attached to switch, skip to next */
                if (argv[1][2])
                    argv[1] += 2;
                else {
                    argc--;
                    argv++;
                }

                if (!argv[1])
                    quit(GET_MSG(1201));

                if ((strlen(argv[1]) + 1 + strlen(pchInclude)) >= cchIncludeMax) {
                    cchIncludeMax = strlen(pchInclude) + strlen(argv[1]) + _MAX_PATH*2;
                    pchIncludeT = MyAlloc(cchIncludeMax);
                    strcpy(pchIncludeT, pchInclude);
                    MyFree(pchInclude);
                    pchInclude = pchIncludeT;
                    pchIncludeT = pchInclude + strlen(pchIncludeT) + 1;
                }

                /* if not first switch, write over terminator with semicolon */
                if (pchInclude != pchIncludeT)
                    pchIncludeT[-1] = ';';

                /* copy the path */
                while ((*pchIncludeT++ = *argv[1]++) != 0)
                    ;
                break;

            case 'L':
                /* if not attached to switch, skip to next */
                if (argv[1][2])
                    argv[1] += 2;
                else {
                    argc--;
                    argv++;
                }

                if (!argv[1])
                    quit(GET_MSG(1202));
                if (sscanf( argv[1], "%x", &language ) != 1)
                    quit(GET_MSG(1203));

                while (*argv[1]++ != 0)
                    ;

                break;

            case 'M':
                fMacRsrcs = TRUE;
                goto MaybeMore;

            case 'N':
                fAppendNull = TRUE;
                goto MaybeMore;

            case 'P':
                fPreprocessOnly = TRUE;
                break;

            case 'R':
                goto MaybeMore;

            case 'S':
                // find out from BRAD what -S does
                fAFXSymbols = TRUE;
                break;

            case 'U':
                /* if not attached to switch, skip to next */
                if (argv[1][2])
                    argv[1] += 2;
                else {
                    argc--;
                    argv++;
                }

                /* remember pointer to string */
                pszUnDefine[cUnDefine++] = argv[1];
                if (cUnDefine > cDefineMax) {
                    SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(1104), argv[1]);
                    quit(Msg_Text);
                }
                break;

            case 'V':
                fVerbose = TRUE; // AFX doesn't set this
                goto MaybeMore;

            case 'X':
                /* remember not to add INCLUDE path */
                fInclude = FALSE;

                // VC seems to feel the current dir s/b added first no matter what...
                // If -X! is specified, don't do that.
                if (argv[1][2] == '!') {
                    fIncludeCurrentFirst = FALSE;
                    argv[1]++;
                }

MaybeMore:      /* check to see if multiple switches, like -xrv */
                if (argv[1][2]) {
                    argv[1][1] = '-';
                    argv[1]++;
                    continue;
                }
                break;

            case 'Z':

                /* if not attached to switch, skip to next */
                if (argv[1][2])
                    argv[1] += 2;
                else {
                    argc--;
                    argv++;
                }

                if (!argv[1])
                    quit(GET_MSG(1211));

                s3 = strchr(argv[1], '/');
                if (s3 == NULL)
                    quit(GET_MSG(1212));

                *s3 = '\0';
                MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, s3+1, -1, szSubstituteFontName, MAXTOKSTR);

                s1 = argv[1];
                do {
                    s2 = strchr(s1, ',');
                    if (s2 != NULL)
                        *s2 = '\0';

                    if (strlen(s1)) {
                        if (nBogusFontNames >= 16)
                            quit(GET_MSG(1213));

                        pszBogusFontNames[nBogusFontNames] = MyAlloc((strlen(s1)+1) * sizeof(WCHAR));
                        MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, s1, -1, pszBogusFontNames[nBogusFontNames], MAXTOKSTR);
                        nBogusFontNames += 1;
                    }

                    if (s2 != NULL)
                        *s2++ = ',';
                    }
                while (s1 = s2);

                *s3 =  '/';

                while (*argv[1]++ != 0)
                    ;
                break;

            default:
                SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(1106), argv[1]);
                quit(Msg_Text);
        }

        /* get next argument or switch */
        argc--;
        argv++;
    }

    /* make sure we have at least one file name to work with */
    if (argc != 2 || *argv[1] == '\0')
        quit(GET_MSG(1107));

    if (fVerbose) {
        SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(10001),
                VER_PRODUCTVERSION_STR, VER_PRODUCTBUILD);
        printf(Msg_Text);
        printf("%s\n", GET_MSG(10002));
    }

    // Support Multi Code Page

    //  If user did NOT indicate code in command line, we have to set Default
    //     for NLS Conversion

    if (uiCodePage == 0) {

        CHAR *pchCodePageString;

        /* At first, search ENVIRONMENT VALUE */

        if ((pchCodePageString = getenv("RCCODEPAGE")) != NULL) {
            uiCodePage = atoi(pchCodePageString);

            if (uiCodePage == 0 || !IsValidCodePage(uiCodePage))
                quit(GET_MSG(1207));
        }
        else
        {
            /* We use System ANSI Code page (ACP) */
            uiCodePage = GetACP();
        }
    }
    uiDefaultCodePage = uiCodePage;
    if (fVerbose)
        printf("Using codepage %d as default\n", uiDefaultCodePage);

    /* If we have no extension, assumer .rc                             */
    /* If .res extension, make sure we have -fo set, or error           */
    /* Otherwise, just assume file is .rc and output .res (or resname)  */

    //
    // We have to be careful upper casing this, because the codepage
    // of the filename might be in something other than current codepage.
    //
    MultiByteToWideChar(uiCodePage, MB_PRECOMPOSED, argv[1], -1, tokenbuf, MAXSTR+1);
    if (CharUpperBuff(tokenbuf, wcslen(tokenbuf)) == 0)
        _wcsupr(tokenbuf);
    WideCharToMultiByte(uiCodePage, 0, tokenbuf, -1, argv[1], strlen(argv[1]), NULL, NULL);
    _splitpath(argv[1], szDrive, szDir, szFName, szExt);

    if (!(*szDir || *szDrive)) {
        strcpy(szIncPath, ".;");
    } else {
        strcpy(szIncPath, szDrive);
        strcat(szIncPath, szDir);
        strcat(szIncPath, ";.;");
    }

    if ((strlen(szIncPath) + 1 + strlen(pchInclude)) >= cchIncludeMax) {
        cchIncludeMax = strlen(pchInclude) + strlen(szIncPath) + _MAX_PATH*2;
        pchIncludeT = MyAlloc(cchIncludeMax);
        strcpy(pchIncludeT, pchInclude);
        MyFree(pchInclude);
        pchInclude = pchIncludeT;
        pchIncludeT = pchInclude + strlen(pchIncludeT) + 1;
    }

    pchIncludeT = MyAlloc(cchIncludeMax);

    if (fIncludeCurrentFirst) {
        strcpy(pchIncludeT, szIncPath);
        strcat(pchIncludeT, pchInclude);
    } else {
        strcpy(pchIncludeT, pchInclude);
        strcat(pchIncludeT, ";");
        strcat(pchIncludeT, szIncPath);
    }

    MyFree(pchInclude);
    pchInclude = pchIncludeT;
    pchIncludeT = pchInclude + strlen(pchIncludeT) + 1;

    if (!szExt[0]) {
        strcpy(szExt, ".RC");
    }
    else if (strcmp (szExt, ".RES") == 0) {
        quit (GET_MSG(1208));
    }

    _makepath(inname, szDrive, szDir, szFName, szExt);
    if (fPreprocessOnly) {
        _makepath(szPreProcessName, NULL, NULL, szFName, ".rcpp");
    }

    /* Create the name of the .RES file */
    if (resname[0] == 0) {
        // if building a Mac resource file, we use .rsc to match mrc's output
        _makepath(resname, szDrive, szDir, szFName, fMacRsrcs ? ".RSC" : ".RES");
    }

    /* create the temporary file names */
    szTempFileName = MyAlloc(_MAX_PATH);

    _fullpath(szFullPath, resname, _MAX_PATH);
    _splitpath(szFullPath, szDrive, szDir, NULL, NULL);

    _makepath(szTempFileName, szDrive, szDir, "RCXXXXXX", "");
    _mktemp (szTempFileName);
    szTempFileName2 = MyAlloc(_MAX_PATH);
    _makepath(szTempFileName2, szDrive, szDir, "RDXXXXXX", "");
    _mktemp (szTempFileName2);

    ppargv = szRCPP;
    *ppargv++ = "RCPP";
    rcpp_argc = 1;

    /* Open the .RES file (deleting any old versions which exist). */
    if ((fhBin = fopen(resname, "w+b")) == NULL) {
        SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(1109), resname);
        quit(Msg_Text);
    }
    else {
        if (fMacRsrcs)
            MySeek(fhBin, MACDATAOFFSET, 0);
        if (fVerbose) {
            SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(10102), resname);
            printf(Msg_Text);
        }

        /* Set up for RCPP. This constructs the command line for it. */
        *ppargv = _strdup("-CP");
        rcpp_argc++ ; ppargv++;
        _itoa(uiCodePage, buf, 10);
        *ppargv = buf;
        rcpp_argc++ ; ppargv++;

        *ppargv = _strdup("-f");
        rcpp_argc++ ; ppargv++;
        *ppargv = _strdup(szTempFileName);
        rcpp_argc++ ; ppargv++;

        *ppargv = _strdup("-g");
        rcpp_argc++ ; ppargv++;
        if (fPreprocessOnly) {
            *ppargv = _strdup(szPreProcessName);
        } else {
            *ppargv = _strdup(szTempFileName2);
        }
        rcpp_argc++ ; ppargv++;

        *ppargv = _strdup("-DRC_INVOKED");
        rcpp_argc++ ; ppargv++;

        if (fAFXSymbols) {
            *ppargv = _strdup("-DAPSTUDIO_INVOKED");
            rcpp_argc++ ; ppargv++;
        }

        if (fMacRsrcs) {
            *ppargv = _strdup("-D_MAC");
            rcpp_argc++ ; ppargv++;
        }

        *ppargv = _strdup("-D_WIN32"); /* to be compatible with C9/VC++ */
        rcpp_argc++ ; ppargv++;

        *ppargv = _strdup("-pc\\:/");
        rcpp_argc++ ; ppargv++;

        *ppargv = _strdup("-E");
        rcpp_argc++ ; ppargv++;

        /* Parse the INCLUDE environment variable */

        if (fInclude) {

            *ppargv = _strdup("-I.");
            rcpp_argc++ ; ppargv++;

            /* add seperator if any -I switches */
            if (pchInclude != pchIncludeT)
                pchIncludeT[-1] = ';';

            /* read 'em */
            x = getenv("INCLUDE");
            if (x == (PCHAR)NULL)
                *pchIncludeT = '\000';
            else {
                if (strlen(pchInclude) + strlen(x) + 1 >= cchIncludeMax) {
                    cchIncludeMax = strlen(pchInclude) + strlen(x) + _MAX_PATH*2;
                    pchIncludeT = MyAlloc(cchIncludeMax);
                    strcpy(pchIncludeT, pchInclude);
                    MyFree(pchInclude);
                    pchInclude = pchIncludeT;
                }

                strcat(pchInclude, x);
                pchIncludeT = pchInclude + strlen(pchInclude);
            }
        }

        /* now put includes on the RCPP command line */
        for (x = pchInclude ; *x ; ) {

            r = x;
            while (*x && *x != ';')
                x = CharNextA(x);

            /* mark if semicolon */
            if (*x)
                *x-- = 0;

            if (*r != '\0' &&       /* empty include path? */
                *r != '%'           /* check for un-expanded stuff */
                // && strchr(r, ' ') == NULL  /* check for whitespace */
                ) {
                /* add switch */
                *ppargv = _strdup("-I");
                rcpp_argc++ ; ppargv++;
                *ppargv = _strdup(r);
                rcpp_argc++ ; ppargv++;
            }

            /* was semicolon, need to fix for searchenv() */
            if (*x) {
                *++x = ';';
                x++;
            }

        }

        /* include defines */
        for (n = 0; n < cDefine; n++) {
            *ppargv = _strdup("-D");
            rcpp_argc++ ; ppargv++;
            *ppargv = pszDefine[n];
            rcpp_argc++ ; ppargv++;
        }

        /* include undefine */
        for (n = 0; n < cUnDefine; n++) {
            *ppargv = _strdup("-U");
            rcpp_argc++ ; ppargv++;
            *ppargv = pszUnDefine[n];
            rcpp_argc++ ; ppargv++;
        }

        if (rcpp_argc > MAX_CMD) {
            quit(GET_MSG(1102));
        }
        if (fVerbose) {
            /* echo the preprocessor command */
            printf("RC:");
            for (n = 0 ; n < rcpp_argc ; n++) {
                wsprintfA(Msg_Text, " %s", szRCPP[n]);
                printf(Msg_Text);
            }
            printf("\n");
        }

        /* Add .rc with rcincludes into szTempFileName */
        if (!RC_PreProcess(inname))
            quit(Msg_Text);

        /* Run the Preprocessor. */
        if (RCPP(rcpp_argc, szRCPP, NULL) != 0)
            quit(GET_MSG(1116));
    }

    if (fPreprocessOnly) {
        sprintf(szBuf, "Preprocessed File Created in: %s\n", szPreProcessName);
        quit(szBuf);
    }

    if (fVerbose)
        printf("\n%s", inname);

    if ((fhInput = fopen(szTempFileName2, "rb")) == NULL_FILE)
        quit(GET_MSG(2180));

    if (!InitSymbolInfo())
        quit(GET_MSG(22103));

    LexInit (fhInput);
    uiCodePage = uiDefaultCodePage;
    ReadRF();               /* create .RES from .RC */
    if (!TermSymbolInfo(fhBin))
        quit(GET_MSG(22204));

    if (!fMacRsrcs)
        MyAlign(fhBin); // Pad end of file so that we can concatenate files

    CleanUpFiles();

    HeapDestroy(hHeap);

    return Nerrors;   // return success, not quitting.
}
Example #2
0
/* initialise everything */
void PicocInitialise(Picoc *pc, int StackSize)
{
	memset(pc, '\0', sizeof(*pc));
	PlatformInit(pc);
	BasicIOInit(pc);
	HeapInit(pc, StackSize);
	TableInit(pc);
	VariableInit(pc);
	LexInit(pc);
	TypeInit(pc);

#ifndef NO_HASH_INCLUDE
	IncludeInit(pc);
#endif

	LibraryInit(pc);

#ifdef BUILTIN_MINI_STDLIB
	LibraryAdd(pc, &pc->GlobalTable, "c library", &CLibrary[0]);
	CLibraryInit(pc);
#endif

	PlatformLibraryInit(pc);
	DebugInit(pc);
}
Example #3
0
/* initialise everything */
void PicocInitialise(int StackSize)
{
    BasicIOInit();
    HeapInit(StackSize);
    TableInit();
    VariableInit();
    LexInit();
    TypeInit();
#ifndef NO_HASH_INCLUDE
    IncludeInit();
#endif
    LibraryInit();
#ifdef BUILTIN_MINI_STDLIB
    LibraryAdd(&GlobalTable, "c library", &CLibrary[0]);
    CLibraryInit();
#endif
    PlatformLibraryInit();
}
int startup(int argc, char *argv[])
{ int i, len;  FULL_CHAR *arg;
  OBJECT t, y, res, s;			/* current token, parser output      */
  BOOLEAN stdin_seen;			/* TRUE when stdin file seen         */
  int source_file_count;		/* number of source files in command */
  FULL_CHAR *cross_db;			/* name of cross reference database  */
  FULL_CHAR *outfile;			/* name of output file               */
  FULL_CHAR *lib;			/* name of library directory         */
  FILE *out_fp;
  long MemCheckLong;
  FULL_CHAR oname[MAX_BUFF], oval[MAX_BUFF], buff[MAX_BUFF], *p;
  int bp;  OBJECT z;
  BOOLEAN seen_wordcount;
#if LOCALE_ON
  char catname[MAX_BUFF], *loc;
#endif

  /* find the name of the library directory, from envt or else from -D */
  lib = AsciiToFull(getenv("LOUTLIB"));
  if( lib == (FULL_CHAR *) NULL )
    lib = AsciiToFull(LIB_DIR);

  /* set locale if that's what we are doing */
#if LOCALE_ON
  loc = setlocale(LC_MESSAGES, "");
  if( loc == (char *) NULL )
  { Error(1, 6, "unable to initialize locale", WARN, no_fpos);
    loc = "C";
  }
  sprintf(catname, "%s/%s/%s/LC_MESSAGES/errors.%s",
    lib, LOCALE_DIR, loc, loc);
  MsgCat = catopen(catname, 0);
#endif

  /* initialise various modules, add current directory to search paths */
  TotalWordCount = 0;
  seen_wordcount = FALSE;
  BackEnd = PS_BackEnd;
  PlainCharWidth = PLAIN_WIDTH;
  PlainCharHeight = PLAIN_HEIGHT;
  PlainFormFeed = FALSE;
  InitializeAll = FALSE;
  UseCollate = COLLATE;
  AllowCrossDb = TRUE;
  InMemoryDbIndexes = TRUE;
  Encapsulated = FALSE;
  SafeExecution = SAFE_DFT ? TRUE : FALSE;
  Kern = TRUE;
  MemInit();
  InitSym();
  LexInit();
  InitFiles();
  AddToPath(SOURCE_PATH,   MakeWord(WORD, STR_EMPTY, no_fpos));
  AddToPath(DATABASE_PATH, MakeWord(WORD, STR_EMPTY, no_fpos));
  AddToPath(INCLUDE_PATH,  MakeWord(WORD, STR_EMPTY, no_fpos));

  /* read command line */
  stdin_seen = FALSE;
  AltErrorFormat = FALSE;
  cross_db = CROSS_DB;
  outfile = STR_STDOUT;
  source_file_count = 0;
  New(CommandOptions, ACAT);
  for( i = 1;  i < argc;  i++ )
  {
    if( *argv[i] == CH_HYPHEN ) switch( *(argv[i]+1) )
    {
      case CH_FLAG_OUTFILE:
     
	/* read name of output file */
	if( (outfile = GetArg(argv, argc, &i)) == NULL )
	  Error(1, 7, "usage: -o <filename>", FATAL, no_fpos);
	if( StringEndsWith(outfile, SOURCE_SUFFIX) )
	  Error(1, 28, "-o: output file name %s ends with %s",
	    FATAL, no_fpos, outfile, SOURCE_SUFFIX);
	break;


      case CH_FLAG_SUPPRESS:
     
	/* suppress references to OldCrossDb and NewCrossDb */
	AllowCrossDb = FALSE;
	break;


      case CH_FLAG_MEMCR:
     
	/* don't use in-memory database indexes */
	InMemoryDbIndexes = FALSE;
	break;


      case CH_FLAG_NOKERN:
     
	/* suppress kerning */
	Kern = FALSE;
	break;


      case CH_FLAG_NOCOLLATE:
     
	/* suppress local collation */
	UseCollate = FALSE;
	break;


      case CH_FLAG_COLLATE:
     
	/* invoke local collation */
	UseCollate = TRUE;
	break;


      case CH_FLAG_CROSS:
     
	/* read name of cross reference database */
	if( (cross_db = GetArg(argv, argc, &i)) == NULL )
	  Error(1, 8, "usage: -c <filename>", FATAL, no_fpos);
	break;


      case CH_FLAG_ERRFILE:
     
	/* read log file name */
	if( (arg = GetArg(argv, argc, &i)) == NULL )
	  Error(1, 9, "usage: -e <filename>", FATAL, no_fpos);
	ErrorInit(arg);
	break;


      case CH_FLAG_ALTERR:
     
	/* alternative error message format */
	AltErrorFormat = TRUE;
	break;


      case CH_FLAG_EPSFIRST:
     
	/* -EPS produces encapsulated PostScript output */
	if( !StringEqual(AsciiToFull(argv[i]+1), STR_EPS) )
	  Error(1, 10, "usage: -EPS", FATAL, no_fpos);
	Encapsulated = TRUE;
	break;


      case CH_FLAG_DIRPATH:
     
	/* add directory to database and sysdatabase paths */
	if( (arg = GetArg(argv, argc, &i)) == NULL )
	  Error(1, 11, "usage: -D <directoryname>", FATAL, no_fpos);
	AddToPath(DATABASE_PATH, MakeWord(WORD, arg, no_fpos));
	AddToPath(SYSDATABASE_PATH, MakeWord(WORD, arg, no_fpos));
	break;


      case CH_FLAG_ENCPATH:
     
	/* add directory to character mapping path */
	if( (arg = GetArg(argv, argc, &i)) == NULL )
	  Error(1, 12, "usage: -C <directoryname>", FATAL, no_fpos);
	AddToPath(MAPPING_PATH, MakeWord(WORD, arg, no_fpos));
	break;


      case CH_FLAG_FNTPATH:
     
	/* add directory to font path */
	if( (arg = GetArg(argv, argc, &i)) == NULL )
	  Error(1, 13, "usage: -F <directoryname>", FATAL, no_fpos);
	AddToPath(FONT_PATH, MakeWord(WORD, arg, no_fpos));
	break;


      case CH_FLAG_HYPPATH:
     
	/* add directory to hyph path */
	if( (arg = GetArg(argv, argc, &i)) == NULL )
	  Error(1, 14, "usage: -H <directoryname>", FATAL, no_fpos);
	AddToPath(HYPH_PATH, MakeWord(WORD, arg, no_fpos));
	break;


      case CH_FLAG_INCPATH:
     
	/* add directory to include and sysinclude paths */
	if( (arg = GetArg(argv, argc, &i)) == NULL )
	  Error(1, 15, "usage: -I <directoryname>", FATAL, no_fpos);
	AddToPath(INCLUDE_PATH, MakeWord(WORD, arg, no_fpos));
	AddToPath(SYSINCLUDE_PATH, MakeWord(WORD, arg, no_fpos));
	break;


      case CH_FLAG_INCLUDE:
     
	/* read sysinclude file and strip any .lt suffix */
	if( (arg = GetArg(argv, argc, &i)) == NULL )
	  Error(1, 16, "usage: -i <filename>", FATAL, no_fpos);
	len = StringLength(arg) - StringLength(SOURCE_SUFFIX);
	if( len >= 0 && StringEqual(&arg[len], SOURCE_SUFFIX) )
	  StringCopy(&arg[len], STR_EMPTY);
	debug0(DFS, D, "  calling DefineFile from main (1)");
	DefineFile(arg, STR_EMPTY, no_fpos, SOURCE_FILE, SYSINCLUDE_PATH);
	break;


      case CH_FLAG_HYPHEN:
     
	/* declare hyphenation file */
	if( FirstFile(HYPH_FILE) != NO_FILE )
	  Error(1, 17, "two -h options illegal", FATAL, no_fpos);
	if( (arg = GetArg(argv, argc, &i)) == NULL )
	  Error(1, 18, "usage: -h <filename>", FATAL, no_fpos);
	debug0(DFS, D, "  calling DefineFile from main (2)");
	DefineFile(arg, STR_EMPTY, no_fpos, HYPH_FILE, INCLUDE_PATH);
	DefineFile(arg, HYPH_SUFFIX, no_fpos, HYPH_PACKED_FILE, INCLUDE_PATH);
	break;


      case CH_FLAG_VERSION:
     
	fprintf(stderr, "%s\n", LOUT_VERSION);
	fprintf(stderr, "%-28s %s\n",
	  "Basser Lout written by:", "Jeffrey H. Kingston ([email protected])");
	fprintf(stderr, "%-28s %s\n",
	  "Free source available from:", "ftp://ftp.cs.usyd.edu.au/jeff/lout");
	fprintf(stderr, "%-28s %s %s\n",
	  "This executable compiled:", __TIME__, __DATE__);
	fprintf(stderr, "%-28s %s%s%s\n", "System include directory:",
	  lib, STR_DIR, INCL_DIR);
	fprintf(stderr, "%-28s %s%s%s\n", "System database directory:",
	  lib, STR_DIR, DATA_DIR);
	fprintf(stderr, "Database index files created afresh automatically:%s\n",
	  USE_STAT ? " yes" : " no");
	fprintf(stderr, "Safe execution (disabling system()) is default:%s\n",
	  SAFE_DFT ? " yes" : " no");
	fprintf(stderr, "strcoll() used for sorting by default:%s\n",
	  COLLATE ? " yes" : " no");
	fprintf(stderr, "PDF compression on:%s\n",
	  PDF_COMPRESSION ? " yes" : " no");
	fprintf(stderr, "Debugging (-d, -dd, -ddd flags) available:%s\n",
	  DEBUG_ON ? " yes" : " no");
	fprintf(stderr, "\n");
	fprintf(stderr, "Basser Lout comes with ABSOLUTELY NO WARRANTY.\n");
	fprintf(stderr, "This is free software, and you are welcome to\n");
	fprintf(stderr, "redistribute it under certain conditions.  For\n");
	fprintf(stderr, "details on both points, consult the GNU General\n");
	fprintf(stderr, "Public License (distributed with this software).\n");
	exit(0);
	break;


      case CH_FLAG_WORDS:
     
	seen_wordcount = TRUE;
	break;


      case CH_FLAG_PDF:

	BackEnd = PDF_BackEnd;
	break;


      case CH_FLAG_FFPLAIN:

	if( StringEqual(AsciiToFull(argv[i]+1), STR_PDF) )
	{
	  BackEnd = PDF_BackEnd;
	  break;
	}
	PlainFormFeed = TRUE;
	/* NB NO BREAK */


      case CH_FLAG_PLAIN:
     
	BackEnd = Plain_BackEnd;
	if( *(argv[i]+2) != '\0' )
	{ float len1, len2;  FULL_CHAR units1, units2;
	  if( sscanf(argv[i]+2, "%f%c%f%c",&len1,&units1,&len2,&units2) != 4 )
	  { Error(1, 19, "usage: lout -%c<length><length>",
	      FATAL, no_fpos, *(argv[i]+1));
	  }
	  switch( units1 )
	  {
	    case CH_UNIT_CM:	PlainCharWidth = len1 * CM; break;
	    case CH_UNIT_IN:	PlainCharWidth = len1 * IN; break;
	    case CH_UNIT_PT:	PlainCharWidth = len1 * PT; break;
	    case CH_UNIT_EM:	PlainCharWidth = len1 * EM; break;

	    default:	Error(1, 20, "lout -%c: units must be c, i, p, or m",
				  FATAL, no_fpos, *(argv[i]+1));
				break;
	  }
	  switch( units2 )
	  {
	    case CH_UNIT_CM:	PlainCharHeight = len2 * CM; break;
	    case CH_UNIT_IN:	PlainCharHeight = len2 * IN; break;
	    case CH_UNIT_PT:	PlainCharHeight = len2 * PT; break;
	    case CH_UNIT_EM:	PlainCharHeight = len2 * EM; break;

	    default:	Error(1, 21, "lout -%c: units must be c, i, p, or m",
				  FATAL, no_fpos, *(argv[i]+1));
				break;
	  }
	}
	break;


      case CH_FLAG_INITALL:

	InitializeAll = TRUE;
	AllowCrossDb = FALSE;
	break;


      case CH_FLAG_USAGE:

	PrintUsage(stderr);
	exit(0);
	break;


      case CH_FLAG_DEBUG:
     
	debug_init(AsciiToFull(argv[i]));
	break;


      case CH_FLAG_MEMCHECK:

	sscanf(argv[i], "-m%ld", &MemCheckLong);
	MemCheck = (POINTER) MemCheckLong;
	fprintf(stderr, "checking memory location %ld\n", (long) MemCheck);
	break;


      case '\0':
     
	/* read stdin as file name */
	if( stdin_seen )
	  Error(1, 23, "standard input specified twice", FATAL, no_fpos);
	stdin_seen = TRUE;
	debug0(DFS, D, "  calling DefineFile from main (3)");
	DefineFile(STR_STDIN, STR_EMPTY, no_fpos, SOURCE_FILE, SOURCE_PATH);
	break;


      case CH_FLAG_OPTION:

	/* read command-line document option */
	if( sscanf(argv[i]+2, "%[^{ ] { %[^}] }", oname, oval) != 2 ||
	  StringLength(oname) == 0 || StringLength(oval) == 0 )
	  Error(1, 24, "error in command-line option %s", FATAL, no_fpos,
	    argv[i]+2);
	y = MakeWord(WORD, oname, no_fpos);
	Link(CommandOptions, y);
	New(y, ACAT);
	Link(CommandOptions, y);
	bp = 0;
	for( p = oval;  *p != '\0';  p++ )  switch( *p )
	{
	  case ' ':
	  case '\t':
	  case '\n':
	  case '{':
	  case '}':

	    if( bp > 0 )
	    { buff[bp++] = '\0';
	      if( Down(y) != y ) 
	      { OBJECT g;
		New(g, GAP_OBJ);
		hspace(g) = 1;  vspace(g) = 0;
		FposCopy(fpos(g), *no_fpos);
		Link(y, g);
	      }
	      z = MakeWord(WORD, buff, no_fpos);
	      Link(y, z);
	      bp = 0;
	    }
	    break;


	  default:

	    buff[bp++] = *p;
	    break;
	}
	if( bp > 0 )
	{ buff[bp++] = '\0';
	  z = MakeWord(WORD, buff, no_fpos);
	  Link(y, z);
	}
	if( Down(y) == y )
	  Error(1, 25, "error in command-line option %s", FATAL, no_fpos,
	    argv[i]+2);
	break;


      case CH_FLAG_SAFE:

	/* ensure safe execution by disabling system calls */
	SafeExecution = TRUE;
	break;

      case CH_FLAG_UNSAFE:

	/* allow unsafe execution */
	SafeExecution = FALSE;
	break;

      default:
     
	PrintUsage(stderr);
	Error(1, 26, "unknown command line flag %s", FATAL, no_fpos, argv[i]);
	break;

    }
    else
    {   /* argument is source file, strip any .lout suffix and define it */
	arg = AsciiToFull(argv[i]);
	len = StringLength(arg) - StringLength(SOURCE_SUFFIX);
	if( len >= 0 && StringEqual(&arg[len], SOURCE_SUFFIX) )
	  StringCopy(&arg[len], STR_EMPTY);
	debug0(DFS, D, "  calling DefineFile from main (4)");
	DefineFile(AsciiToFull(argv[i]), STR_EMPTY, no_fpos,
	    SOURCE_FILE, SOURCE_PATH);
	source_file_count++;
    }
  } /* for */

  if( UseCollate )
  {
    if (!setlocale (LC_COLLATE, ""))
      Error(1, 30, "unable to initialize collation", WARN, no_fpos);
  }

  /* start timing if required */
  ifdebug(DPP, D, ProfileOn("main"));

  /* open output file, or stdout if none specified, and initialize printer */
  if( StringEqual(outfile, STR_STDOUT) )
  {
#if OS_DOS
    /* For DOS/Win32 we need to set binary mode on stdout to prevent
       PDF compressed streams and xrefs from being corrupted - Uwe 12/98 */
    if( BackEnd->code != PLAINTEXT &&
	_setmode(_fileno(stdout), _O_BINARY) == -1 )
      Error(1, 31, "cannot set binary mode on stdout", FATAL, no_fpos);
#endif
    out_fp = stdout;
  }
  else
  { out_fp = StringFOpen(outfile,
		BackEnd->code == PLAINTEXT ? WRITE_TEXT : WRITE_BINARY);
    if( out_fp == null )
      Error(1, 27, "cannot open output file %s", FATAL, no_fpos, outfile);
  }

  /* initialize miscellaneous modules */
  ColourInit();
  LanguageInit();
  BackEnd->PrintInitialize(out_fp);

  /* append default directories to file search paths */
  AddToPath(FONT_PATH,      MakeWordThree(lib, STR_DIR, AsciiToFull(FONT_DIR)));
  AddToPath(HYPH_PATH,      MakeWordThree(lib, STR_DIR, AsciiToFull(HYPH_DIR)));
  AddToPath(MAPPING_PATH,   MakeWordThree(lib, STR_DIR, AsciiToFull(MAPS_DIR)));
  AddToPath(SYSDATABASE_PATH,MakeWordThree(lib,STR_DIR, AsciiToFull(DATA_DIR)));
  AddToPath(DATABASE_PATH,  MakeWordThree(lib, STR_DIR, AsciiToFull(DATA_DIR)));
  AddToPath(SYSINCLUDE_PATH,MakeWordThree(lib, STR_DIR, AsciiToFull(INCL_DIR)));
  AddToPath(INCLUDE_PATH,   MakeWordThree(lib, STR_DIR, AsciiToFull(INCL_DIR)));

  /* use stdin if no source files were mentioned */
  if( source_file_count == 0 )
  { debug0(DFS, D, "  calling DefineFile from main (5)");
    DefineFile(STR_STDIN, STR_EMPTY, no_fpos, SOURCE_FILE, SOURCE_PATH);
  }

  /* load predefined symbols into symbol table */
  StartSym      = nilobj;  /* Not a mistake */
  StartSym      = load(KW_START,        0, FALSE,  FALSE,  TRUE,  NO_PREC     );
  GalleySym     = load(KW_GALLEY,       0, FALSE,  FALSE,  TRUE,  NO_PREC     );
  ForceGalleySym= load(KW_FORCE_GALLEY, 0, FALSE,  FALSE,  TRUE,  NO_PREC     );
  InputSym      = load(KW_INPUT,        0, FALSE,  FALSE,  TRUE,  NO_PREC     );
  PrintSym      = load(KW_PRINT,        0, FALSE,  FALSE,  TRUE,  NO_PREC     );
  FilterInSym   = load(KW_FILTERIN,     0, FALSE,  FALSE,  FALSE, NO_PREC     );
  FilterOutSym  = load(KW_FILTEROUT,    0, FALSE,  FALSE,  FALSE, NO_PREC     );
  FilterErrSym  = load(KW_FILTERERR,    0, FALSE,  FALSE,  FALSE, NO_PREC     );
  OptGallSym    = load(KW_OPTGALL,      0, FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  VerbatimSym   = load(KW_VERBATIM,VERBATIM,FALSE, TRUE,   FALSE, DEFAULT_PREC);
  RawVerbatimSym= load(KW_RAWVERBATIM,RAW_VERBATIM,FALSE,TRUE,FALSE,DEFAULT_PREC);


  load(KW_BEGIN,        BEGIN,          FALSE,  FALSE,  FALSE, BEGIN_PREC  );
  load(KW_END,          END,            FALSE,  FALSE,  FALSE, END_PREC    );
  load(KW_ENV,          ENV,            FALSE,  FALSE,  FALSE, NO_PREC     );
  load(KW_ENVA,         ENVA,           FALSE,  FALSE,  FALSE, NO_PREC     );
  load(KW_ENVB,         ENVB,           FALSE,  FALSE,  FALSE, NO_PREC     );
  load(KW_ENVC,         ENVC,           FALSE,  FALSE,  FALSE, NO_PREC     );
  load(KW_ENVD,         ENVD,           FALSE,  FALSE,  FALSE, NO_PREC     );
  load(KW_CENV,         CENV,           FALSE,  FALSE,  FALSE, NO_PREC     );
  load(KW_CLOS,         CLOS,           FALSE,  FALSE,  FALSE, NO_PREC     );
  load(KW_LVIS,         LVIS,           FALSE,  FALSE,  FALSE, NO_PREC     );
  load(KW_LUSE,         LUSE,           FALSE,  FALSE,  FALSE, NO_PREC     );
  load(KW_LEO,          LEO,            FALSE,  FALSE,  FALSE, NO_PREC     );
  load(KW_LBR,          LBR,            FALSE,  FALSE,  FALSE, LBR_PREC    );
  load(KW_RBR,          RBR,            FALSE,  FALSE,  FALSE, RBR_PREC    );
  load(KW_INCLUDE,      INCLUDE,        FALSE,  FALSE,  FALSE, NO_PREC     );
  load(KW_SYSINCLUDE,   SYS_INCLUDE,    FALSE,  FALSE,  FALSE, NO_PREC     );
  load(KW_PREPEND,      PREPEND,        FALSE,  FALSE,  FALSE, NO_PREC     );
  load(KW_SYSPREPEND,   SYS_PREPEND,    FALSE,  FALSE,  FALSE, NO_PREC     );
  load(KW_DATABASE,     DATABASE,       FALSE,  FALSE,  FALSE, NO_PREC     );
  load(KW_SYSDATABASE,  SYS_DATABASE,   FALSE,  FALSE,  FALSE, NO_PREC     );
  load(KW_USE,          USE,            FALSE,  FALSE,  FALSE, NO_PREC     );
  load(KW_NOT_REVEALED, NOT_REVEALED,   FALSE,  FALSE,  FALSE, NO_PREC     );
  load(KW_CASE,         CASE,           TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_YIELD,        YIELD,          TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_BACKEND,      BACKEND,        FALSE,  FALSE,  FALSE, DEFAULT_PREC);
  load(KW_XCHAR,        XCHAR,          FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_FONT,         FONT,           TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_SPACE,        SPACE,          TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_YUNIT,        YUNIT,          TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_ZUNIT,        ZUNIT,          TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_BREAK,        BREAK,          TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_UNDERLINE,    UNDERLINE,      FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_COLOUR,       COLOUR,         TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_COLOR,        COLOUR,         TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_OUTLINE,      OUTLINE,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_LANGUAGE,     LANGUAGE,       TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_CURR_LANG,    CURR_LANG,      FALSE,  FALSE,  FALSE, DEFAULT_PREC);
  load(KW_CURR_FAMILY,  CURR_FAMILY,    FALSE,  FALSE,  FALSE, DEFAULT_PREC);
  load(KW_CURR_FACE,    CURR_FACE,      FALSE,  FALSE,  FALSE, DEFAULT_PREC);
  load(KW_CURR_YUNIT,   CURR_YUNIT,     FALSE,  FALSE,  FALSE, DEFAULT_PREC);
  load(KW_CURR_ZUNIT,   CURR_ZUNIT,     FALSE,  FALSE,  FALSE, DEFAULT_PREC);
  load(KW_COMMON,       COMMON,         TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_RUMP,         RUMP,           TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_MELD,         MELD,           TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_INSERT,       INSERT,         TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_ONE_OF,       ONE_OF,         FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_NEXT,         NEXT,           FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_PLUS,         PLUS,           TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_MINUS,        MINUS,          TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_OPEN,         OPEN,           TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_TAGGED,       TAGGED,         TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_WIDE,         WIDE,           TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_HIGH,         HIGH,           TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_HSHIFT,       HSHIFT,         TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_VSHIFT,       VSHIFT,         TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_BEGIN_HEADER, BEGIN_HEADER,   TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_END_HEADER,   END_HEADER,     FALSE,  FALSE,  FALSE, DEFAULT_PREC);
  load(KW_SET_HEADER,   SET_HEADER,     TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_CLEAR_HEADER, CLEAR_HEADER,   FALSE,  FALSE,  FALSE, DEFAULT_PREC);
  load(KW_ONE_COL,      ONE_COL,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_ONE_ROW,      ONE_ROW,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_HSCALE,       HSCALE,         FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_VSCALE,       VSCALE,         FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_HCOVER,       HCOVER,         FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_VCOVER,       VCOVER,         FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_KERN_SHRINK,  KERN_SHRINK,    TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_SCALE,        SCALE,          TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_HCONTRACT,    HCONTRACT,      FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_VCONTRACT,    VCONTRACT,      FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_HLIMITED,     HLIMITED,       FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_VLIMITED,     VLIMITED,       FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_HEXPAND,      HEXPAND,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_VEXPAND,      VEXPAND,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_STARTHVSPAN,  START_HVSPAN,   FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_STARTHSPAN,   START_HSPAN,    FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_STARTVSPAN,   START_VSPAN,    FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_HSPAN,        HSPAN,          FALSE,  FALSE,  FALSE, DEFAULT_PREC);
  load(KW_VSPAN,        VSPAN,          FALSE,  FALSE,  FALSE, DEFAULT_PREC);
  load(KW_PADJUST,      PADJUST,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_HADJUST,      HADJUST,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_VADJUST,      VADJUST,        FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_ROTATE,       ROTATE,         TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_BACKGROUND,   BACKGROUND,     TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_INCGRAPHIC,   INCGRAPHIC,     FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_SINCGRAPHIC,  SINCGRAPHIC,    FALSE,  TRUE,   FALSE, DEFAULT_PREC);
  load(KW_PLAINGRAPHIC, PLAIN_GRAPHIC,  TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_GRAPHIC,      GRAPHIC,        TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_LINK_SOURCE,   LINK_SOURCE,     TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_LINK_DEST,    LINK_DEST,      TRUE,   TRUE,   FALSE, DEFAULT_PREC);
  load(KW_CROSS,        CROSS,          TRUE,   TRUE,   FALSE, CROSSOP_PREC);
  load(KW_FORCE_CROSS,  FORCE_CROSS,    TRUE,   TRUE,   FALSE, CROSSOP_PREC);
  load(KW_NULL,         NULL_CLOS,      FALSE,  FALSE,  TRUE,  NO_PREC     );
  load(KW_PAGE_LABEL,   PAGE_LABEL,     FALSE,  TRUE,   TRUE,  DEFAULT_PREC);

#define setcat(s, mk, jn)  has_mark(s)=mk, has_join(s)=jn

  s=load(KW_VCAT_NN, VCAT, TRUE, TRUE, FALSE, VCAT_PREC); setcat(s,FALSE,FALSE);
  s=load(KW_VCAT_MN, VCAT, TRUE, TRUE, FALSE, VCAT_PREC); setcat(s,TRUE, FALSE);
  s=load(KW_VCAT_NJ, VCAT, TRUE, TRUE, FALSE, VCAT_PREC); setcat(s,FALSE,TRUE);
  s=load(KW_VCAT_MJ, VCAT, TRUE, TRUE, FALSE, VCAT_PREC); setcat(s,TRUE, TRUE);
  s=load(KW_HCAT_NN, HCAT, TRUE, TRUE, FALSE, HCAT_PREC); setcat(s,FALSE,FALSE);
  s=load(KW_HCAT_MN, HCAT, TRUE, TRUE, FALSE, HCAT_PREC); setcat(s,TRUE, FALSE);
  s=load(KW_HCAT_NJ, HCAT, TRUE, TRUE, FALSE, HCAT_PREC); setcat(s,FALSE,TRUE);
  s=load(KW_HCAT_MJ, HCAT, TRUE, TRUE, FALSE, HCAT_PREC); setcat(s,TRUE, TRUE);
  s=load(KW_ACAT_NJ, ACAT, TRUE, TRUE, FALSE, ACAT_PREC); setcat(s,FALSE,TRUE);
  s=load(KW_ACAT_MJ, ACAT, TRUE, TRUE, FALSE, ACAT_PREC); setcat(s,TRUE, TRUE);

  /* intialize fonts and load @FontDef symbol */
  FontInit();

  /* intialize current time and load @Moment symbol */
  InitTime();

  /* initialize filter module */
  FilterInit();

  /* initialize enviroment table module */
  EnvInit();

  /* initialise scope chain to <StartSym> */
  PushScope(StartSym, FALSE, FALSE);

  /* initialise lexical analyser */
  LexPush(FirstFile(SOURCE_FILE), 0, SOURCE_FILE, 1, FALSE);

  /* process input files */
  InitParser(cross_db);
  t = NewToken(BEGIN, no_fpos, 0, 0, BEGIN_PREC, StartSym);
  res = Parse(&t, StartSym, TRUE, TRUE);
  debug0(DGT, D, "calling TransferEnd(res) from main()");
  DisposeObject(CommandOptions);
  TransferEnd(res);
  TransferClose();

  /* close various modules */
  BackEnd->PrintAfterLastPage();
  BackEnd->LinkCheck();
  CrossClose();
  CloseFiles();

  /* remove any leftover filter temporary files */
  FilterScavenge(TRUE);

  /* print word count, if required */
  if( seen_wordcount )
    Error(1, 29, "total of all words printed: %d", WARN,no_fpos,TotalWordCount);

  /* check for unbalanced error blocks */
  CheckErrorBlocks();

  /* wrapup */
  ifdebug(DST, DD, CheckSymSpread() );
  ifdebug(ANY, D, DeleteEverySym() );
  debug0(DMA, D, "at end of run:");
  ifdebug(DMA, D, DebugMemory() );
  ifdebug(DPP, D, ProfileOff("main"));
  ifdebug(DPP, D, ProfilePrint());
  ifdebug(DET, D, EnvDebug());

#if LOCALE_ON
  catclose(MsgCat);
#endif

  exit(0);
  return 0;
} /* end main */