示例#1
0
/*
 *   initialize 
 */
CVmHostIfcStdio::CVmHostIfcStdio(const char *argv0)
{
    char buf[OSFNMAX];

    /* remember the program's argv[0], in case we need it later */
    argv0_ = lib_copy_str(argv0);

    /* 
     *   Create the resource loader for system resources (character mapping
     *   files, etc) in the same directory as the executable. 
     */
    os_get_special_path(buf, sizeof(buf), argv0, OS_GSP_T3_RES);
    sys_res_loader_ = new CResLoader(buf);

    /* set the executable filename in the loader, if available */
    if (os_get_exe_filename(buf, sizeof(buf), argv0))
        sys_res_loader_->set_exe_filename(buf);

    /* 
     *   the default safety level allows reading and writing to the current
     *   directory only 
     */
    io_safety_read_ = VM_IO_SAFETY_READWRITE_CUR;
    io_safety_write_ = VM_IO_SAFETY_READWRITE_CUR;
    net_client_safety_ = VM_NET_SAFETY_LOCALHOST;
    net_server_safety_ = VM_NET_SAFETY_LOCALHOST;
}
示例#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);
}
示例#3
0
int main(int argc, char **argv)
{
    CResLoader *res_loader;
    CTcHostIfc *hostifc;
    int curarg;
    CTcTokFileDesc *desc;
    long linenum;
    int pp_mode = FALSE;
    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");

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

    err_try
    {
        /* add some pre-defined symbols for testing */
        G_tok->add_define("_MSC_VER", "1100");
        G_tok->add_define("_WIN32", "1");
        G_tok->add_define("_M_IX86", "500");
        G_tok->add_define("__STDC__", "0");
        G_tok->add_define("_INTEGRAL_MAX_BITS", "64");
        G_tok->add_define("__cplusplus", "1");
        
        /* 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) == 'P')
            {
                /* set preprocess-only mode */
                G_tok->set_mode_pp_only(TRUE);
                pp_mode = TRUE;
            }
            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 + 1 != argc)
        {
            /* terminate the compiler */
            CTcMain::terminate();
            
            /* delete our objects */
            delete res_loader;
            
            /* exit with an error */
            errexit("usage: test_tok [options] <source-file>\n"
                    "options:\n"
                    "   -Idir   - add dir to include path\n"
                    "   -P      - preprocess to standard output\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");
        
        /* start out with no stream */
        desc = 0;
        linenum = 0;
        
        /* read lines of input */
        for (;;)
        {
            /* read the next line, and stop if we've reached end of file */
            if (G_tok->read_line_pp())
                break;
            
            /* 
             *   If we're in a different stream than for the last line, or
             *   the new line number is more than the last line number plus
             *   1, add a #line directive to the output stream.
             *   
             *   In order to make test log output independent of local path
             *   naming conventions and the local directory structure, use
             *   only the root filename in the #line directive.  
             */
            if (pp_mode
                && (G_tok->get_last_desc() != desc
                    || G_tok->get_last_linenum() != linenum + 1))
                printf("#line %ld %s\n", G_tok->get_last_linenum(),
                       G_tok->get_last_desc()->get_dquoted_rootname());
            
            /* remember the last line we read */
            desc = G_tok->get_last_desc();
            linenum = G_tok->get_last_linenum();
            
            /* show this line */
            printf("%s\n", G_tok->get_cur_line());
        }
        
        /* dump the hash table, to see what it looks like */
        G_tok->get_defines_table()->debug_dump();
    }
    err_catch(exc)
    {
        /* 
         *   if it's not the general internal error, log it; don't log
         *   general internal errors, since these will have been logged as
         *   specific internal errors before being thrown 
         */
        if (exc->get_error_code() != TCERR_INTERNAL_ERROR)
            printf("exception caught: %d\n", exc->get_error_code());
    }
    err_end;

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

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

    /* delete host interface */
    delete hostifc;

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

    /* success */
    return 0;
}
示例#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);
}
示例#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;
}
示例#6
0
int main(int argc, char **argv)
{
    CResLoader *loader;
    CCharmapToLocal *map;
    static wchar_t teststr[] =
    {
        0xA9,                                             /* copyright sign */
        0xA1,                                  /* inverted exclamation mark */
        0xA2,                                                  /* cent sign */
        0xD0,                                                        /* eth */
        0x17A,                                 /* small letter z with acute */
        0x102,                               /* capital letter a with breve */
        0x401,                                /* cyrillic capital letter IO */
        0x622,                                               /* arabic alef */
        0x3B1,                                         /* greek small alpha */
        0x3B2,                                          /* greek small beta */
        0x30,                                                    /* digit 0 */
        0x31,                                                    /* digit 1 */
        0x32,                                                    /* digit 2 */
        0x33,                                                    /* digit 3 */
        0x34,                                                    /* digit 4 */
        0x35,                                                    /* digit 5 */
        0x36,                                                    /* digit 6 */
        0x37,                                                    /* digit 7 */
        0x38,                                                    /* digit 8 */
        0x39,                                                    /* digit 9 */
        0x41,                                                  /* capital A */
        0x42,                                                  /* capital B */
        0x43,                                                  /* capital C */
        0x44,                                                  /* capital D */
        0x45,                                                  /* capital E */
        0x2248,                                        /* almost equal sign */
        0x2264,                               /* less than or equal to sign */
        0
    };
    char buf[256];
    char mapbuf[256];
    utf8_ptr up;
    size_t len;
    size_t i;
    char pathbuf[OSFNMAX];

    /* initialize for testing */
    test_init();

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

    /* create a single-byte translator and load it with DOS code page 437 */
    map = CCharmapToLocal::load(loader, "charmap/cp437");
    if (map == 0)
    {
        printf("unable to load cp437 mapping file\n");
        exit(1);
    }

    /* create a UTF-8 string to map */
    up.set(buf);
    up.setwcharsz(teststr, sizeof(buf));

    /* check how much space we need */
    up.set(buf);
    len = map->map_utf8z(0, 0, up);
    printf("space needed for mapping to cp437: %d\n", len);

    /* map it for real this time */
    map->map_utf8z(mapbuf, sizeof(mapbuf), up);

    /* display the result */
    for (i = 0 ; i < len ; ++i)
        printf("%02x ", (unsigned char)mapbuf[i]);
    printf("\n");

    printf("%s\n", mapbuf);

    /* success */
    exit(0);
}