Exemple #1
0
/*
 *   open for writing 
 */
void CVmFile::open_write(const char *fname, os_filetype_t typ)
{
    /* try opening the underlying OS file for binary writing */
    fp_ = osfopwb(fname, typ);

    /* if that failed, throw an error */
    if (fp_ == 0)
        err_throw(VMERR_CREATE_FILE);
}
Exemple #2
0
int main(int argc, char **argv)
{
    CResLoader *res_loader;
    CTcHostIfc *hostifc;
    int curarg;
    int fatal_error_count = 0;
    osfildef *fpout = 0;
    int next_local = 0;
    CVmFile *imgfile = 0;
    CVmFile *objfile = 0;
    const char *imgfname;
    int success;
    char pathbuf[OSFNMAX];
    static const char tool_data[4] = { 't', 's', 't', 'L' };

    /* initialize for testing */
    test_init();

    /* create the host interface object */
    hostifc = new CTcHostIfcStdio();

    /* create a resource loader */
    os_get_special_path(pathbuf, sizeof(pathbuf), argv[0], OS_GSP_T3_RES);
    res_loader = new CResLoader(pathbuf);

    /* initialize the compiler */
    CTcMain::init(hostifc, res_loader, 0);

    err_try
    {
        /* scan arguments */
        for (curarg = 1 ; curarg < argc ; ++curarg)
        {
            char *p;

            /* get the argument string for easy reference */
            p = argv[curarg];

            /* if it's not an option, we're done */
            if (*p != '-')
                break;

            if (*(p + 1) == 'v')
            {
                /* set verbose mode */
                G_tcmain->set_verbosity(TRUE);
            }
            else
            {
                /*
                 *   invalid usage - consume all the arguments and fall
                 *   through to the usage checker
                 */
                curarg = argc;
                break;
            }
        }

        /* check arguments */
        if (curarg + 2 > argc)
        {
            /* terminate the compiler */
            CTcMain::terminate();

            /* delete our objects */
            delete res_loader;

            /* exit with an error */
            errexit("usage: test_link [options] obj-file [obj-file [...]] "
                    "image-file\n"
                    "options:\n"
                    "   -v     - verbose error messages");
        }

        /* set up an output file */
        imgfname = argv[argc - 1];
        fpout = osfopwb(imgfname, OSFTT3IMG);
        if (fpout == 0)
            errexit("unable to open image file");
        imgfile = new CVmFile();
        imgfile->set_file(fpout, 0);

        /* read the object files */
        for ( ; curarg < argc - 1 ; ++curarg)
        {
            osfildef *fpobj;

            /* open this object file */
            fpobj = osfoprb(argv[curarg], OSFTT3OBJ);
            if (fpobj == 0)
            {
                printf("unable to open object file \"%s\"\n", argv[curarg]);
                goto done;
            }

            /* note the loading */
            printf("loading %s\n", argv[curarg]);

            /* set up the CVmFile object for it */
            objfile = new CVmFile();
            objfile->set_file(fpobj, 0);

            /* read the object file */
            G_cg->load_object_file(objfile, argv[curarg]);

            /* done with the object file */
            delete objfile;
            objfile = 0;
        }

        /* check for unresolved externals */
        if (G_prs->check_unresolved_externs())
            goto done;

        /* write the image file */
        G_cg->write_to_image(imgfile, 0, tool_data);

done:
        ;
    }
    err_catch(exc)
    {
        /*
         *   if it's not a general internal or fatal error, log it; don't
         *   log general errors, since these will have been logged as
         *   specific internal errors before being thrown
         */
        if (exc->get_error_code() != TCERR_INTERNAL_ERROR
                && exc->get_error_code() != TCERR_FATAL_ERROR)
            G_tok->log_error(TC_SEV_FATAL, exc->get_error_code());

        /* count the fatal error */
        ++fatal_error_count;
    }
    err_end;

    /* report errors */
    fprintf(stderr,
            "Warnings: %d\n"
            "Errors:   %d\n"
            "Longest string: %d, longest list: %d\n",
            G_tcmain->get_warning_count(),
            G_tcmain->get_error_count() + fatal_error_count,
            G_cg->get_max_str_len(), G_cg->get_max_list_cnt());

    /*
     *   note whether or not the compilation was successful - it succeeded
     *   if we had no errors or fatal errors
     */
    success = (G_tcmain->get_error_count() + fatal_error_count == 0);

    /* delete the object file object (this closes the file) */
    delete imgfile;

    /* if we have an open object file, close it */
    if (objfile != 0)
        delete objfile;

    /*
     *   if any errors occurred, delete the object file in the external
     *   file system - this prevents us from leaving around an incomplete
     *   or corrupted image file when compilation fails, and helps
     *   'make'-type tools realize that they must generate the image file
     *   target again on the next build, even if source files didn't
     *   change
     */
    if (!success)
        osfdel(imgfname);

    /* shut down the compiler */
    CTcMain::terminate();

    /* done with the res loader */
    delete res_loader;

    /* delete the host interface */
    delete hostifc;

    /* show any unfreed memory */
    t3_list_memory_blocks(0);

    /*
     *   terminate - exit with a success indication if we had no errors
     *   (other than warnings); exit with an error indication otherwise
     */
    return (success ? OSEXSUCC : OSEXFAIL);
}
Exemple #3
0
/*
 *   Main entrypoint 
 */
int main(int argc, char **argv)
{
    int curarg;
    unsigned char input_map[256];
    unsigned char output_map[256];
    unsigned char input_map_set[256];
    unsigned char output_map_set[256];
    unsigned char *p;
    int i;
    osfildef *fp;
    char *infile;
    char *outfile;
    int linenum;
    static char sig[] = CMAP_SIG_S100;
    int strict_mode = FALSE;
    char id[5];
    char ldesc[CMAP_LDESC_MAX_LEN + 1];
    size_t len;
    unsigned char lenbuf[2];
    char *sys_info;
    entity_map_t *entity_first;
    entity_map_t *entity_last;

    /* no parameters have been specified yet */
    memset(id, 0, sizeof(id));
    ldesc[0] = '\0';
    sys_info = 0;

    /* we have no entities in our entity mapping list yet */
    entity_first = entity_last = 0;

    /* scan options */
    for (curarg = 1 ; curarg < argc && argv[curarg][0] == '-' ; ++curarg)
    {
        if (!stricmp(argv[curarg], "-strict"))
        {
            /* they want extra warnings */
            strict_mode = TRUE;
        }
        else
        {
            /* consume all remaining options so we get a usage message */
            curarg = argc;
            break;
        }
    }

    /* check for required arguments */
    if (curarg + 1 >= argc)
    {
        printf("usage: mkchrtab [options] <source> <dest>\n"
               "  <source> is the input file\n"
               "  <dest> is the output file\n"
               "Options:\n"
               "  -strict   warn if any codes 128-255 are unassigned\n");
#if 0
/* 
 *   The information about what goes in the file made the message way too
 *   long, so this has been removed.  Users will want to the documentation
 *   instead of the usage message for information this detailed, so it
 *   didn't seem useful to keep it in here.  
 */
        printf("\n"
               "The source file contains one entry per line, as follows:\n"
               "\n"
               "Set the internal character set identifier, which can be up "
               "to four letters long\n"
               "(note that the mapping file MUST contain an ID entry):\n"
               "   ID = id\n"
               "\n");
        printf("Set the internal character set's full display name:\n"
               "   LDESC = full name of character set\n"
               "\n"
               "Set system-dependent extra information (the meaning varies "
               "by system):\n"
               "   EXTRA_SYSTEM_INFO = info-string\n"
               "\n"
               "Set the native default character:\n"
               "   NATIVE_DEFAULT = charval\n"
               "Set the internal default character:\n"
               "   INTERNAL_DEFAULT = charval\n");
        printf("Load Unicode mapping files:\n"
               "   UNICODE NATIVE=native-mapping INTERNAL=internal-mapping\n"
               "\n"
               "Reversibly map a native character code to an internal code:\n"
               "   native <-> internal\n"
               "\n"
               "Map a native code to an internal code, and map the internal "
               "code back\nto a different native code:\n"
               "   native -> internal -> native\n"
               "\n"
               "Map a native code to an internal code, where the internal "
               "code is already\nmapped to a native code by a previous line:\n"
               "   native -> internal\n"
               "\n");
        printf("Map an internal code to a native code, where the native "
               "code is already\nmapped to an internal code by a previous "
               "line:\n"
               "   native <- internal\n"
               "\n"
               "Map an HTML entity name to a native code or string:\n"
               "   &entity = internal-code [internal-code ...]\n"
               "\n"
               "Numbers can be specified in decimal (default), octal (by "
               "prefixing the number\nwith a zero, as in '037'), or hex (by "
               "prefixing the number with '0x', as in\n'0xb2').  A number "
               "can also be entered as a character by enclosing the\n"
               "character in single quotes.\n"
               "\n"
               "Blank lines and lines starting with a pound sign ('#') are "
               "ignored.\n");
#endif /* 0 */
        os_term(OSEXFAIL);
    }

    /* get the input and output filenames */
    infile = argv[curarg];
    outfile = argv[curarg + 1];

    /* 
     *   initialize the tables - by default, a character code in one
     *   character set maps to the same code in the other character set 
     */
    for (p = input_map, i = 0 ; i < sizeof(input_map)/sizeof(input_map[0]) ;
         ++i, ++p)
        *p = (unsigned char)i;

    for (p = output_map, i = 0 ;
         i < sizeof(output_map)/sizeof(output_map[0]) ; ++i, ++p)
        *p = (unsigned char)i;

    /* 
     *   initialize the "set" flags all to false, since we haven't set any
     *   of the values yet -- we'll use these flags to detect when the
     *   user attempts to set the same value more than once, so that we
     *   can issue a warning (multiple mappings are almost certainly in
     *   error) 
     */
    for (i = 0 ; i < sizeof(input_map_set)/sizeof(input_map_set[0]) ; ++i)
        input_map_set[i] = output_map_set[i] = FALSE;

    /* open the input file */
    fp = osfoprs(infile, OSFTTEXT);
    if (fp == 0)
    {
        printf("error: unable to open input file \"%s\"\n", infile);
        os_term(OSEXFAIL);
    }

    /* parse the input file */
    for (linenum = 1 ; ; ++linenum)
    {
        char buf[256];
        char *p;
        unsigned int n1, n2, n3;
        int set_input;
        int set_output;

        /* presume we're going to set both values */
        set_input = set_output = TRUE;

        /* read the next line */
        if (osfgets(buf, sizeof(buf), fp) == 0)
            break;

        /* scan off leading spaces */
        for (p = buf ; isspace(*p) ; ++p) ;

        /* if this line is blank, or starts with a '#', ignore it */
        if (*p == '\0' || *p == '\n' || *p == '\r' || *p == '#')
            continue;

        /* check for special directives */
        if (isalpha(*p) || *p == '_')
        {
            char *sp;
            char *val;
            size_t vallen;
            size_t idlen;
            
            /* find the end of the directive name */
            for (sp = p ; isalpha(*sp) || *sp == '_' ; ++sp) ;
            idlen = sp - p;

            /* find the equals sign, if present */
            for (val = sp ; isspace(*val) ; ++val) ;
            if (*val == '=')
            {
                /* skip the '=' and any spaces that follow */
                for (++val ; isspace(*val) ; ++val) ;

                /* find the end of the value */
                for (sp = val ; *sp != '\n' && *sp != '\r' && *sp != '\0' ;
                     ++sp) ;

                /* note its length */
                vallen = sp - val;
            }
            else
            {
                /* there's no value */
                val = 0;
            }

            /* see what we have */
            if (id_matches(p, idlen, "id"))
            {
                /* this directive requires a value */
                if (val == 0)
                    goto val_required;

                /* ID's can never be more than four characters long */
                if (vallen > 4)
                {
                    printf("%s: line %d: ID too long - no more than four "
                           "characters are allowed\n", infile, linenum);
                }
                else
                {
                    /* remember the ID */
                    memcpy(id, val, vallen);
                    id[vallen] = '\0';
                }
            }
            else if (id_matches(p, idlen, "ldesc"))
            {
                /* this directive requires a value */
                if (val == 0)
                    goto val_required;

                /* make sure it fits */
                if (vallen > sizeof(ldesc) - 1)
                {
                    printf("%s: line %d: LDESC too long - no more than %u "
                           "characters are allowed\n", infile, linenum,
                           sizeof(ldesc) - 1);
                }
                else
                {
                    /* remember the ldesc */
                    memcpy(ldesc, val, vallen);
                    ldesc[vallen] = '\0';
                }
            }
            else if (id_matches(p, idlen, "extra_system_info"))
            {
                /* this directive requires a value */
                if (val == 0)
                    goto val_required;

                /* allocate space for it */
                sys_info = (char *)malloc(vallen + 1);
                memcpy(sys_info, val, vallen);
                sys_info[vallen] = '\0';
            }
            else if (id_matches(p, idlen, "native_default"))
            {
                unsigned int nval;
                int i;

                /* this directive requires a value */
                if (val == 0)
                    goto val_required;

                /* parse the character value */
                if (read_number(&nval, &val, infile, linenum, TRUE))
                    continue;

                /* apply the default */
                for (i = 128 ; i < 256 ; ++i)
                {
                    /* set the default only if we haven't mapped this one */
                    if (!output_map_set[i])
                        output_map[i] = nval;
                }
            }
            else if (id_matches(p, idlen, "internal_default"))
            {
                unsigned int nval;
                int i;

                /* this directive requires a value */
                if (val == 0)
                    goto val_required;

                /* parse the character value */
                if (read_number(&nval, &val, infile, linenum, TRUE))
                    continue;

                /* apply the default */
                for (i = 128 ; i < 256 ; ++i)
                {
                    /* apply the default only if we haven't set this one */
                    if (!input_map_set[i])
                        input_map[i] = nval;
                }
            }
            else if (id_matches(p, idlen, "unicode"))
            {
                /* skip the 'unicode' string and any intervening spaces */
                for (p += idlen ; isspace(*p) ; ++p) ;

                /* parse the unicode files */
                parse_unicode_files(p, strlen(p), infile, linenum,
                                    input_map, input_map_set,
                                    output_map, output_map_set,
                                    &entity_first, &entity_last);
            }
            else
            {
                /* unknown directive */
                printf("%s: line %d: invalid directive '%.*s'\n",
                       infile, linenum, idlen, p);
            }

            /* done processing this line */
            continue;

            /* come here if the directive needs a value and there isn't one */
        val_required:
            printf("%s: line %d: '=' required with directive '%.*s'\n",
                   infile, linenum, idlen, p);
            continue;
        }

        /* check for an entity name */
        if (*p == '&')
        {
            entity_map_t *mapp;

            /* skip the '&' */
            ++p;

            /* 
             *   parse the entity - if it succeeds, link the resulting
             *   mapping entry into our list 
             */
            mapp = parse_entity(p, infile, linenum);
            if (mapp != 0)
            {
                if (entity_last == 0)
                    entity_first = mapp;
                else
                    entity_last->nxt = mapp;
                entity_last = mapp;
            }

            /* done */
            continue;
        }

        /* read the first number */
        if (read_number(&n1, &p, infile, linenum, TRUE))
            continue;

        /* determine which operator we have */
        if (*p == '<')
        {
            /* make sure it's "<->" or "<-" */
            if (*(p+1) == '-' && *(p+2) != '>')
            {
                /* skip the operator */
                p += 2;

                /* 
                 *   This is a "from" translation - it only affects the
                 *   output mapping from the internal character set to the
                 *   native character set.  Read the second number.  There
                 *   is no third number, since we don't want to change the
                 *   input mapping.
                 */
                if (read_number(&n2, &p, infile, linenum, TRUE))
                    continue;

                /* 
                 *   The forward translation is not affected; set only the
                 *   output translation.  Note that the first number was
                 *   the output (native) value for the internal index in
                 *   the second number, so move the first value to n3.  
                 */
                n3 = n1;
                set_input = FALSE;
            }
            else if (*(p+1) == '-' && *(p+2) == '>')
            {
                /* skip it */
                p += 3;

                /* 
                 *   this is a reversible translation, so we only need one
                 *   more number - the third number is implicitly the same
                 *   as the first 
                 */
                n3 = n1;
                if (read_number(&n2, &p, infile, linenum, TRUE))
                    continue;
            }
            else
            {
                printf("%s: line %d: invalid operator - expected <->\n",
                       infile, linenum);
                continue;
            }
        }
        else if (*p == '-')
        {
            /* make sure it's "->" */
            if (*(p+1) != '>')
            {
                printf("%s: line %d: invalid operator - expected ->\n",
                       infile, linenum);
                continue;
            }

            /* skip it */
            p += 2;

            /* get the next number */
            if (read_number(&n2, &p, infile, linenum, TRUE))
                continue;

            /* 
             *   we may or may not have a third number - if we have
             *   another -> operator, read the third number; if we don't,
             *   the reverse translation is not affected by this entry 
             */
            if (*p == '-')
            {
                /* make sure it's "->" */
                if (*(p+1) != '>')
                {
                    printf("%s: line %d: invalid operator - expected ->\n",
                           infile, linenum);
                    continue;
                }

                /* skip it */
                p += 2;

                /* read the third number */
                if (read_number(&n3, &p, infile, linenum, TRUE))
                    continue;
            }
            else
            {
                /*
                 *   There's no third number - the reverse translation is
                 *   not affected by this line.  
                 */
                set_output = FALSE;
            }
        }
        else
        {
            printf("%s: line %d: invalid operator - expected "
                   "-> or <-> or <-\n",
                   infile, linenum);
            continue;
        }

        /* make sure we're at the end of the line, and warn if not */
        if (*p != '\0' && *p != '\n' && *p != '\r' && *p != '#')
            printf("%s: line %d: extra characters at end of line ignored\n",
                   infile, linenum);

        /* set the input mapping, if necessary */
        if (set_input)
        {
            /* warn the user if this value has already been set before */
            if (input_map_set[n1])
                printf("%s: line %d: warning - native character %u has "
                       "already been\n    mapped to internal value %u\n",
                       infile, linenum, n1, input_map[n1]);
            
            /* set it */
            input_map[n1] = n2;

            /* note that it's been set */
            input_map_set[n1] = TRUE;
        }

        /* set the output mapping, if necessary */
        if (set_output)
        {
            /* warn the user if this value has already been set before */
            if (output_map_set[n2])
                printf("%s: line %d: warning - internal character %u has "
                       "already been\n    mapped to native value %u\n",
                       infile, linenum, n2, input_map[n2]);

            /* set it */
            output_map[n2] = n3;

            /* note that it's been set */
            output_map_set[n2] = TRUE;
        }
    }

    /* we're done with the input file */
    osfcls(fp);

    /*
     *   It's an error if we didn't get an ID or LDESC 
     */
    if (id[0] == '\0')
    {
        printf("Error: No ID was specified.  An ID is required.\n");
        os_term(OSEXFAIL);
    }
    else if (ldesc[0] == '\0')
    {
        printf("Error: No LDESC was specified.  An LDESC is required.\n");
        os_term(OSEXFAIL);
    }

    /* open the output file */
    fp = osfopwb(outfile, OSFTCMAP);
    if (fp == 0)
    {
        printf("error: unable to open output file \"%s\"\n", outfile);
        os_term(OSEXFAIL);
    }

    /* write our signature */
    if (osfwb(fp, sig, sizeof(sig)))
        printf("error writing signature to output file\n");

    /* write the ID and LDESC */
    len = strlen(ldesc) + 1;
    oswp2(lenbuf, len);
    if (osfwb(fp, id, 4)
        || osfwb(fp, lenbuf, 2)
        || osfwb(fp, ldesc, len))
        printf("error writing ID information to output file\n");

    /* write the mapping tables */
    if (osfwb(fp, input_map, sizeof(input_map))
        || osfwb(fp, output_map, sizeof(output_map)))
        printf("error writing character maps to output file\n");

    /* write the extra system information if present */
    if (sys_info != 0)
    {
        /* write it out, with the "SYSI" flag so we know it's there */
        len = strlen(sys_info) + 1;
        oswp2(lenbuf, len);
        if (osfwb(fp, "SYSI", 4)
            || osfwb(fp, lenbuf, 2)
            || osfwb(fp, sys_info, len))
            printf("error writing EXTRA_SYSTEM_INFO to output file\n");

        /* we're done with the allocated buffer now */
        free(sys_info);
    }

    /*
     *   Write the entity mapping list, if we have any entities 
     */
    if (entity_first != 0)
    {
        entity_map_t *entp;
        entity_map_t *next_entity;
        char lenbuf[2];
        char cvalbuf[2];

        /* write out the entity list header */
        if (osfwb(fp, "ENTY", 4))
            printf("error writing entity marker to output file\n");

        /* run through the list, writing out each entry */
        for (entp = entity_first ; entp != 0 ; entp = next_entity)
        {
            /* write out this entity */
            oswp2(lenbuf, entp->exp_len);
            oswp2(cvalbuf, entp->html_char);
            if (osfwb(fp, lenbuf, 2)
                || osfwb(fp, cvalbuf, 2)
                || osfwb(fp, entp->expansion, entp->exp_len))
            {
                printf("error writing entity mapping to output file\n");
                break;
            }

            /* remember the next entity before we delete this one */
            next_entity = entp->nxt;

            /* we're done with this entity, so we can delete it now */
            free(entp);
        }

        /* 
         *   write out the end marker, which is just a length marker and
         *   character marker of zero 
         */
        oswp2(lenbuf, 0);
        oswp2(cvalbuf, 0);
        if (osfwb(fp, lenbuf, 2)
            || osfwb(fp, cvalbuf, 2))
            printf("error writing entity list end marker to output file\n");
    }

    /* write the end-of-file marker */
    if (osfwb(fp, "$EOF", 4))
        printf("error writing end-of-file marker to output file\n");

    /* done with the output file */
    osfcls(fp);

    /* if we're in strict mode, check for unassigned mappings */
    if (strict_mode)
    {
        int in_cnt, out_cnt;
        int cnt;

        /* count unassigned characters */
        for (i = 128, in_cnt = out_cnt = 0 ; i < 256 ; ++i)
        {
            if (!input_map_set[i])
                ++in_cnt;
            if (!output_map_set[i])
                ++out_cnt;
        }

        /* if we have any unassigned native characters, list them */
        if (in_cnt != 0)
        {
            printf("\nUnassigned native -> internal mappings:\n    ");
            for (i = 128, cnt = 0 ; i < 256 ; ++i)
            {
                if (!input_map_set[i])
                {
                    /* go to a new line if necessary */
                    if (cnt >= 16)
                    {
                        printf("\n    ");
                        cnt = 0;
                    }

                    /* display this item */
                    printf("%3d ", i);
                    ++cnt;
                }
            }
            printf("\n");
        }

        /* list unassigned internal characters */
        if (out_cnt != 0)
        {
            printf("\nUnassigned internal -> native mappings:\n    ");
            for (i = 128, cnt = 0 ; i < 256 ; ++i)
            {
                if (!output_map_set[i])
                {
                    /* go to a new line if necessary */
                    if (cnt >= 16)
                    {
                        printf("\n    ");
                        cnt = 0;
                    }

                    /* display this item */
                    printf("%3d ", i);
                    ++cnt;
                }
            }
            printf("\n");
        }
    }

    /* success */
    os_term(OSEXSUCC);
    return OSEXSUCC;
}
Exemple #4
0
int main(int argc, char **argv)
{
    CResLoader *res_loader;
    CTcHostIfc *hostifc;
    int curarg;
    int fatal_error_count = 0;
    osfildef *fpout = 0;
    CVmFile *imgfile = 0;
    CTcUnasSrcCodeStr *unas_in;
    CTcUnasOutStdio unas_out;
    CTPNStmProg *node;
    const char *image_fname;
    int success;
    int unasm = FALSE;
    uchar xor_mask = 0;
    char pathbuf[OSFNMAX];

    /* initialize for testing */
    test_init();

    /* create the host interface object */
    hostifc = new CTcHostIfcStdio();

    /* create a resource loader */
    os_get_special_path(pathbuf, sizeof(pathbuf), argv[0], OS_GSP_T3_RES);
    res_loader = new CResLoader(pathbuf);

    /* initialize the compiler */
    CTcMain::init(hostifc, res_loader, "us-ascii");

    /* use test reporting mode */
    G_tok->set_test_report_mode(TRUE);
    G_tcmain->set_test_report_mode(TRUE);

    /* create the disassembler input stream */
    unas_in = new CTcUnasSrcCodeStr(G_cs);

    err_try
    {
        static const char tool_data[4] = { 't', 's', 't', 'P' };
            
        /* scan options */
        for (curarg = 1 ; curarg < argc ; ++curarg)
        {
            char *p;
            
            /* get the argument string for easy reference */
            p = argv[curarg];
            
            /* if it's not an option, we're done */
            if (*p != '-')
                break;
            
            /* if it's a -I argument, use it */
            if (*(p + 1) == 'I')
            {
                char *path;
                
                /* 
                 *   if it's with this argument, read it, otherwise move
                 *   on to the next argument 
                 */
                if (*(p + 2) == '\0')
                    path = argv[++curarg];
                else
                    path = p + 2;
                
                /* add the directory to the include path list */
                G_tok->add_inc_path(path);
            }
            else if (*(p + 1) == 'v')
            {
                /* set verbose mode */
                G_tcmain->set_verbosity(TRUE);
            }
            else if (*(p + 1) == 'u')
            {
                /* note unassembly mode */
                unasm = TRUE;
            }
            else
            {
                /* 
                 *   invalid usage - consume all the arguments and fall
                 *   through to the usage checker 
                 */
                curarg = argc;
                break;
            }
        }
        
        /* check arguments */
        if (curarg + 2 != argc)
        {
            /* terminate the compiler */
            CTcMain::terminate();
            
            /* delete our objects */
            delete res_loader;
            
            /* exit with an error */
            errexit("usage: test_prs [options] <source-file> <image-file>\n"
                    "options:\n"
                    "   -Idir  - add dir to include path\n"
                    "   -v     - verbose error messages");
        }

        /* add the default system include directory to the include path */
        os_get_special_path(pathbuf, sizeof(pathbuf), argv[0], OS_GSP_T3_INC);
        G_tok->add_inc_path(pathbuf);
        
        /* set up the tokenizer with the main input file */
        if (G_tok->set_source(argv[curarg], argv[curarg]))
            errexit("unable to open source file");

        /* set up an output file */
        image_fname = argv[curarg+1];
        fpout = osfopwb(image_fname, OSFTT3IMG);
        if (fpout == 0)
            errexit("unable to open image file");
        imgfile = new CVmFile();
        imgfile->set_file(fpout, 0);

        /* read the first token */
        G_tok->next();
        
        /* parse at the top level */
        node = G_prs->parse_top();

        /* if errors occurred during parsing, stop here */
        if (G_tcmain->get_error_count() != 0 || node == 0)
            goto done;
        
        /* fold symbolic constants for all nodes */
        node->fold_constants(G_prs->get_global_symtab());

        /* if errors occurred during constant folding, stop now */
        if (G_tcmain->get_error_count() != 0)
            goto done;

        /* generate code and write the image file */
        node->build_image(imgfile, xor_mask, tool_data);
            
        /* if errors occurred during code generation, stop now */
        if (G_tcmain->get_error_count() != 0)
            goto done;

        /* disassemble the result if desired */
        if (unasm)
            CTcT3Unasm::disasm(unas_in, &unas_out);

    done: ;
    }
    err_catch(exc)
    {
        /* 
         *   if it's not a general internal or fatal error, log it; don't
         *   log general errors, since these will have been logged as
         *   specific internal errors before being thrown 
         */
        if (exc->get_error_code() != TCERR_INTERNAL_ERROR
            && exc->get_error_code() != TCERR_FATAL_ERROR)
            G_tok->log_error(TC_SEV_FATAL, exc->get_error_code());

        /* count the fatal error */
        ++fatal_error_count;
    }
    err_end;

    /* report errors */
    fprintf(stderr,
            "Warnings: %d\n"
            "Errors:   %d\n"
            "Longest string: %d, longest list: %d\n",
            G_tcmain->get_warning_count(),
            G_tcmain->get_error_count() + fatal_error_count,
            G_cg->get_max_str_len(), G_cg->get_max_list_cnt());

    /* 
     *   note whether or not the compilation was successful - it succeeded
     *   if we had no errors or fatal errors 
     */
    success = (G_tcmain->get_error_count() + fatal_error_count == 0);

    /* delete the image file object (this closes the file) */
    delete imgfile;

    /* 
     *   if any errors occurred, delete the image file in the external
     *   file system - this prevents us from leaving around an incomplete
     *   or corrupted image file when compilation fails, and helps
     *   'make'-type tools realize that they must generate the image file
     *   target again on the next build, even if source files didn't
     *   change 
     */
    if (!success)
        osfdel(image_fname);

    /* delete the disassembler input object */
    delete unas_in;

    /* shut down the compiler */
    CTcMain::terminate();

    /* done with the res loader */
    delete res_loader;

    /* delete the host interface */
    delete hostifc;

    /* show any unfreed memory */
    t3_list_memory_blocks(0);

    /* 
     *   terminate - exit with a success indication if we had no errors
     *   (other than warnings); exit with an error indication otherwise 
     */
    return (success ? OSEXSUCC : OSEXFAIL);
}
Exemple #5
0
int main(int argc, char **argv)
{
    CResLoader *res_loader;
    CTcHostIfc *hostifc;
    int curarg;
    int fatal_error_count = 0;
    node_entry *node_head = 0;
    node_entry *node_tail = 0;
    osfildef *fpout = 0;
    CVmFile *imgfile = 0;
    ulong next_obj_id = 1;
    uint next_prop_id = 1;
    int next_local = 0;
    CTcTokFileDesc *desc;
    long linenum;
    CTcUnasSrcCodeStr *unas_in;
    CTcUnasOutStdio unas_out;
    char pathbuf[OSFNMAX];

    /* initialize for testing */
    test_init();

    /* create the host interface object */
    hostifc = new CTcHostIfcStdio();

    /* create a resource loader */
    os_get_special_path(pathbuf, sizeof(pathbuf), argv[0], OS_GSP_T3_RES);
    res_loader = new CResLoader(pathbuf);

    /* initialize the compiler */
    CTcMain::init(hostifc, res_loader, 0);

    /* create the disassembler input stream */
    unas_in = new CTcUnasSrcCodeStr(G_cs);

    err_try
    {
        /* scan -I arguments */
        for (curarg = 1 ; curarg < argc ; ++curarg)
        {
            char *p;
            
            /* get the argument string for easy reference */
            p = argv[curarg];
            
            /* if it's not an option, we're done */
            if (*p != '-')
                break;
            
            /* if it's a -I argument, use it */
            if (*(p + 1) == 'I')
            {
                char *path;
                
                /* 
                 *   if it's with this argument, read it, otherwise move
                 *   on to the next argument 
                 */
                if (*(p + 2) == '\0')
                    path = argv[++curarg];
                else
                    path = p + 2;
                
                /* add the directory to the include path list */
                G_tok->add_inc_path(path);
            }
            else if (*(p + 1) == 'v')
            {
                /* set verbose mode */
                G_tcmain->set_verbosity(TRUE);
            }
            else
            {
                /* 
                 *   invalid usage - consume all the arguments and fall
                 *   through to the usage checker 
                 */
                curarg = argc;
                break;
            }
        }
        
        /* check arguments */
        if (curarg + 2 != argc)
        {
            /* terminate the compiler */
            CTcMain::terminate();
            
            /* delete our objects */
            delete res_loader;
            
            /* exit with an error */
            errexit("usage: test_prs [options] <source-file> <image-file>\n"
                    "options:\n"
                    "   -Idir  - add dir to include path\n"
                    "   -v     - verbose error messages");
        }
        
        /* set up the tokenizer with the main input file */
        if (G_tok->set_source(argv[curarg], argv[curarg]))
            errexit("unable to open source file");

        /* set up an output file */
        fpout = osfopwb(argv[curarg+1], OSFTT3IMG);
        if (fpout == 0)
            errexit("unable to open image file");
        imgfile = new CVmFile();
        imgfile->set_file(fpout, 0);

        /* read the first token */
        G_tok->next();
        
        /* parse expressions */
        for (;;)
        {
            CTcPrsNode *result;
            CTcSymbol *entry;

            /* if we're at end of file, we're done */
            if (G_tok->getcur()->gettyp() == TOKT_EOF)
                break;

            /* check for our fake declarations */
            switch(G_tok->getcur()->gettyp())
            {
            case TOKT_OBJECT:
                /* add an object symbol */
                G_tok->next();
                entry = new CTcSymObj(G_tok->getcur()->get_text(),
                                      G_tok->getcur()->get_text_len(),
                                      FALSE, next_obj_id++, FALSE,
                                      TC_META_TADSOBJ, 0);
                G_prs->get_global_symtab()->add_entry(entry);

                /* skip the object name */
                G_tok->next();
                break;

            case TOKT_FUNCTION:
                /* add a function symbol */
                G_tok->next();
                entry = new CTcSymFunc(G_tok->getcur()->get_text(),
                                       G_tok->getcur()->get_text_len(),
                                       FALSE, 0, 0, FALSE, TRUE,
                                       FALSE, FALSE, FALSE);
                G_prs->get_global_symtab()->add_entry(entry);

                /* skip the function name */
                G_tok->next();
                break;

            case TOKT_LOCAL:
                /* add a local variable symbol */
                G_tok->next();
                entry = new CTcSymLocal(G_tok->getcur()->get_text(),
                                        G_tok->getcur()->get_text_len(),
                                        FALSE, FALSE, next_local++);
                G_prs->get_global_symtab()->add_entry(entry);

                /* skip the function name */
                G_tok->next();
                break;
                
            default:
                /* note the starting line */
                desc = G_tok->get_last_desc();
                linenum = G_tok->get_last_linenum();
                
                /* parse an expression */
                result = G_prs->parse_expr();
                
                /* add it to our list */
                if (result != 0)
                {
                    node_entry *cur;
                    
                    /* create a new list entry */
                    cur = new node_entry(result, desc, linenum);
                    
                    /* link it at the end of our list */
                    cur->nxt = 0;
                    if (node_tail != 0)
                        node_tail->nxt = cur;
                    else
                        node_head = cur;
                    node_tail = cur;
                }
            }

            /* parse a semicolon */
            if (G_prs->parse_req_sem())
                break;
        }

        /* 
         *   if there were no parse errors, run through our node list and
         *   generate code 
         */
        if (G_tcmain->get_error_count() == 0)
        {
            /* 
             *   loop through our node list; generate code and then delete
             *   each list entry 
             */
            while (node_head != 0)
            {
                node_entry *nxt;

                /* remember the next entry */
                nxt = node_head->nxt;

                /* 
                 *   set this line's descriptor as current, for error
                 *   reporting purposes 
                 */
                G_tok->set_line_info(node_head->desc, node_head->linenum);

                /* fold symbolic constants */
                node_head->node =
                    node_head->node
                    ->fold_constants(G_prs->get_global_symtab());

                /* if it's a constant value, display it */
                show_const(0, node_head->node);

                /* 
                 *   generate code; for testing purposes, don't discard
                 *   anything, to ensure we perform all generation 
                 */
                node_head->node->gen_code(FALSE, FALSE);

                /* disassemble this much */
                unas_out.print("// line %lu\n", node_head->linenum);
                CTcT3Unasm::disasm(unas_in, &unas_out);

                /* delete this entry */
                delete node_head;

                /* move on to the next entry */
                node_head = nxt;
            }
        }
    }
    err_catch(exc)
    {
        /* 
         *   if it's not a general internal or fatal error, log it; don't
         *   log general errors, since these will have been logged as
         *   specific internal errors before being thrown 
         */
        if (exc->get_error_code() != TCERR_INTERNAL_ERROR
            && exc->get_error_code() != TCERR_FATAL_ERROR)
            G_tok->log_error(TC_SEV_FATAL, exc->get_error_code());

        /* count the fatal error */
        ++fatal_error_count;
    }
    err_end;

    /* report errors */
    fprintf(stderr,
            "Warnings: %d\n"
            "Errors:   %d\n"
            "Longest string: %d, longest list: %d\n",
            G_tcmain->get_warning_count(),
            G_tcmain->get_error_count() + fatal_error_count,
            G_cg->get_max_str_len(), G_cg->get_max_list_cnt());

    /* delete the disassembler input object */
    delete unas_in;

    /* shut down the compiler */
    CTcMain::terminate();

    /* done with the res loader */
    delete res_loader;

    /* delete the image file */
    delete imgfile;

    /* delete the host interface */
    delete hostifc;

    /* show any unfreed memory */
    t3_list_memory_blocks(0);

    /* success */
    return 0;
}
int main(int argc, char **argv)
{
    osfildef *fpin;
    osfildef *fpout;
    CVmFile *file_in;
    CVmFile *file_out;
    int status;
    CVmHostIfc *hostifc;
    CVmMainClientConsole clientifc;
    int curarg;

    /* initialize for testing */
    test_init();

    /* initialize the error stack */
    err_init(1024);
    
    /* start at the first argument */
    curarg = 1;

    /* check usage */
    if (curarg + 2 > argc)
    {
        printf("usage: t3pre <original-image> <new-image> [program-args]\n"
               "\n"
               "Runs preinitialization on the image file, writing a new "
               "image file\n"
               "with the state of the program after preinitialization.\n");
        return OSEXFAIL;
    }

    /* open the files */
    if ((fpin = osfoprb(argv[curarg], OSFTT3IMG)) == 0)
    {
        printf("Error opening original image file \"%s\"\n", argv[1]);
        return OSEXFAIL;
    }

    if ((fpout = osfopwb(argv[curarg + 1], OSFTT3IMG)) == 0)
    {
        printf("Error opening new image file \"%s\"\n", argv[2]);
        return OSEXFAIL;
    }

    /* create the CVmFile objects */
    file_in = new CVmFile();
    file_in->set_file(fpin, 0);
    file_out = new CVmFile();
    file_out->set_file(fpout, 0);

    /* create our host interface */
    hostifc = new CVmHostIfcStdio(argv[0]);

    /* run preinit and write the new image file */
    err_try
    {
        /* load, run, and write */
        vm_run_preinit(file_in, argv[1], file_out, hostifc, &clientifc,
                       argv + curarg + 1, argc - curarg - 1, 0);
        
        /* note the success status */
        status = OSEXSUCC;
    }
    err_catch(exc)
    {
        const char *msg;
        char buf[128];

        /* look up the message */
        msg = err_get_msg(vm_messages, vm_message_count,
                          exc->get_error_code(), FALSE);

        /* if that failed, just show the error number */
        if (msg == 0)
        {
            sprintf(buf, "[no message: code %d]", exc->get_error_code());
            msg = buf;
        }

        /* show the message */
        printf("VM Error: %s\n", msg);

        /* note the failure status */
        status = OSEXFAIL;
    }
    err_end;

    /* delete the file objects, which will close the files */
    delete file_in;
    delete file_out;

    /* terminate the error mechanism */
    err_terminate();

    /* delete our host interface object */
    delete hostifc;

    /* log any memory leaks */
    t3_list_memory_blocks(0);

    /* exit with appropriate results */
    return status;
}
int main(int argc, char **argv)
{
    int       curarg;
    osfildef *fpin;
    osfildef *fpout;
    char      tmpfile[OSFNMAX + 1];
    char      inbuf[OSFNMAX + 1];
    char     *p;
    char     *infile;
    char      buf[128];
    opdef    *oplist = (opdef *)0;
    opctxdef  opctx;
    int       do_create = FALSE;

    /* print main banner */
    rscptf("TADS Resource Manager version 2.2.4\n");
    rscptf("Copyright (c) 1992, 1999 by Michael J. Roberts.  ");
    rscptf("All Rights Reserved.\n");
    if (argc < 2) usage();

    /* set default parsing options */
    opctx.restype = RESTYPE_DFLT;
    opctx.flag = OPFADD | OPFDEL;
    opctx.doing_type = FALSE;

    /* scan file options (these come before the filename) */
    for (curarg = 1 ; curarg < argc ; ++curarg)
    {
        /* check if it's an option - if not, stop looking */
        if (argv[curarg][0] != '-')
            break;
        
        /* check the option */
        if (!stricmp(argv[curarg], "-create"))
        {
            /* note that we want to create the file */
            do_create = TRUE;
        }
        else
        {
            rscptf("unrecognized file option \"%s\"", argv[curarg]);
            errexit("", 1);
        }
    }
    
    /* get the file name */
    infile = argv[curarg++];
    strcpy(inbuf, infile);
    os_defext(inbuf, "gam");

    /* open the file for reading, unless we're creating a new file */
    if (do_create)
    {
        /* creating - we have no input file */
        fpin = 0;
    }
    else if ((fpin = osfoprb(inbuf, OSFTGAME)) == 0)
    {
        /* 
         *   not creating, so the file must already exist - it doesn't, so
         *   issue an error and quit 
         */
        errexit("unable to open resource file", 1);
    }

    /* 
     *   if no operations are desired, and we're not creating a new file,
     *   just list the existing file's contents and quit 
     */
    if (curarg == argc && fpin != 0)
    {
        rscproc(fpin, (osfildef *)0, 0);
        osfcls(fpin);
        os_term(OSEXSUCC);
    }

    /*
     *   Create an output file.  If we're creating a new file, create the
     *   file named on the command line; otherwise, create a temporary
     *   file that we'll write to while working and then rename to the
     *   original input filename after we've finished with the original
     *   input file.  
     */
    if (do_create)
    {
        /* create the new file */
        if ((fpout = osfopwb(inbuf, OSFTGAME)) == 0)
            errexit("unable to create file", 1);

        /* report the creation */
        rscptf("\nFile created.\n");
    }
    else
    {
        /* generate a temporary filename */
        strcpy(tmpfile, inbuf);
        for (p = tmpfile + strlen(tmpfile) ; p > tmpfile &&
                 *(p-1) != ':' && *(p-1) != '\\' && *(p-1) != '/' ; --p);
        strcpy(p, "$TADSRSC.TMP");

        /* open the temporary file */
        if ((fpout = osfopwb(tmpfile, OSFTGAME)) == 0)
            errexit("unable to create temporary file", 1);
    }

    /* see if we need to read a response file */
    if (curarg < argc && argv[curarg][0] == '@')
    {
        osfildef *argfp;
        int       l;
        char     *p;
        
        if (!(argfp = osfoprt(argv[curarg]+1, OSFTTEXT)))
            errexit("unable to open response file", 1);
        
        for (;;)
        {
            if (!osfgets(buf, sizeof(buf), argfp)) break;
            l = strlen(buf);
            if (l && buf[l-1] == '\n') buf[--l] = '\0';
            for (p = buf ; t_isspace(*p) ; ++p);
            if (!*p) continue;
            oplist = addop(oplist, p, &opctx);
        }
        osfcls(argfp);
    }
    else
    {
        for ( ; curarg < argc ; ++curarg)
            oplist = addop(oplist, argv[curarg], &opctx);
    }

    /* process the resources */
    oplist = rscproc(fpin, fpout, oplist);

    /* make sure they all got processed */
    for ( ; oplist != 0 ; oplist = oplist->opnxt)
    {
        if (!(oplist->opflag & OPFDONE))
            rscptf("warning: resource \"%s\" not found\n", oplist->opres);
    }
    
    /* close files */
    if (fpin != 0)
        osfcls(fpin);
    if (fpout != 0)
        osfcls(fpout);
    
    /* 
     *   if we didn't create a new file, remove the original input file
     *   and rename the temp file to the original file name 
     */
    if (!do_create)
    {
        /* remove the original input file */
        if (remove(inbuf))
            errexit("error deleting input file", 1);

        /* rename the temp file to the output file */
        if (rename(tmpfile, inbuf))
            errexit("error renaming temporary file", 1);
    }

    /* success */
    os_term(OSEXSUCC);
    return OSEXSUCC;
}