Ejemplo n.º 1
0
/*
 *   set up the compiler 
 */
CTcMain::CTcMain(CResLoader *res_loader, const char *default_charset)
{
    char csbuf[OSFNMAX];
    
    /* 
     *   if the caller didn't provide a default character set, ask the OS
     *   what we should use
     */
    if (default_charset == 0)
    {
        /* 
         *   ask the OS what to use for file contents, since we use this
         *   character set to translate the text we read from source files 
         */
        os_get_charmap(csbuf, OS_CHARMAP_FILECONTENTS);
        
        /* use our OS-provided character set */
        default_charset = csbuf;
    }

    /* if there's no static console output character map, create one */
    if (console_mapper_ == 0)
    {
        char mapname[32];

        /* get the console character set name */
        os_get_charmap(mapname, OS_CHARMAP_DISPLAY);

        /* create a resource loader for the console character map */
        console_mapper_ = CCharmapToLocal::load(res_loader, mapname);

        /* if that failed, create an ASCII mapper */
        if (console_mapper_ == 0)
            console_mapper_ = CCharmapToLocal::load(res_loader, "us-ascii");
    }
    
    /* remember our resource loader */
    res_loader_ = res_loader;
    
    /* 
     *   set default options - minimum verbosity, no numeric error codes,
     *   show standard warnings but not pedantic warnings, not test mode 
     */
    err_options_ = TCMAIN_ERR_WARNINGS;

    /* we have no warning suppression list yet */
    suppress_list_ = 0;
    suppress_cnt_ = 0;

    /* remember our default character set */
    default_charset_ = lib_copy_str(default_charset);

    /* create the tokenizer */
    G_tok = new CTcTokenizer(res_loader_, default_charset_);
    
    /* 
     *   Create the parser and node memory pool.  Create the memory pool
     *   first, because the parser allocates objects out of the pool. 
     */
    G_prsmem = new CTcPrsMem();
    G_prs = new CTcParser();

    /* create the generator data stream (for constant data) */
    G_ds = new CTcDataStream(TCGEN_DATA_STREAM);

    /* create the primary generator code stream */
    G_cs_main = new CTcCodeStream(TCGEN_CODE_STREAM);

    /* create the static initializer code stream */
    G_cs_static = new CTcCodeStream(TCGEN_STATIC_CODE_STREAM);

    /* make the primary code stream active */
    G_cs = G_cs_main;

    /* create the generator object data stream */
    G_os = new CTcDataStream(TCGEN_OBJECT_STREAM);

    /* create the intrinsic class modifier object data stream */
    G_icmod_stream = new CTcDataStream(TCGEN_ICMOD_STREAM);

    /* create the dictionary object data stream */
    G_dict_stream = new CTcDataStream(TCGEN_DICT_STREAM);

    /* create the grammar-production object data stream */
    G_gramprod_stream = new CTcDataStream(TCGEN_GRAMPROD_STREAM);

    /* create the BigNumber object data stream */
    G_bignum_stream = new CTcDataStream(TCGEN_BIGNUM_STREAM);

    /* create the IntrinsicClass object data stream */
    G_int_class_stream = new CTcDataStream(TCGEN_INTCLASS_STREAM);

    /* create the static initializer identifier stream */
    G_static_init_id_stream = new CTcDataStream(TCGEN_STATIC_INIT_ID_STREAM);

    /* create the target-specific code generator */
    G_cg = new CTcGenTarg();

    /* initialize the parser */
    G_prs->init();

    /* no errors or warnings yet */
    error_count_ = 0;
    warning_count_ = 0;
    first_error_ = 0;
    first_warning_ = 0;

    /* set a fairly liberal maximum error limit */
    max_error_count_ = 100;

    /* there's no disassembly output stream yet */
    G_disasm_out = 0;
}
Ejemplo n.º 2
0
/*
 *   Perform base initialization.  This is an internal routine called only
 *   by higher-level initialization routines; we perform all of the
 *   generic, configuration-independent initialization.
 */
void vm_init_base(vm_globals **vmg, const vm_init_options *opts)
{
    vm_globals *vmg__;
    char disp_mapname[32];
    char filename_mapname[32];
    char filecont_mapname[32];
    CResLoader *map_loader;
    int disp_map_err;
    const char *charset = opts->charset;
    
    /* 
     *   Allocate globals according to build-time configuration, then
     *   assign the global pointer to a local named vmg__.  This will
     *   ensure that the globals are accessible for all of the different
     *   build-time configurations.  
     */
    vmg__ = *vmg = vmglob_alloc();

    /* initialize the error stack */
    err_init(VM_ERR_STACK_BYTES);

    /* get the character map loader from the host interface */
    map_loader = opts->hostifc->get_cmap_res_loader();

    /* if an external message set hasn't been loaded, try loading one */
    if (!err_is_message_file_loaded() && map_loader != 0)
    {
        osfildef *fp;
        
        /* try finding a message file */
        fp = map_loader->open_res_file(VM_ERR_MSG_FNAME, 0,
                                       VM_ERR_MSG_RESTYPE);
        if (fp != 0)
        {
            /* 
             *   try loading it - if that fails, we'll just be left with
             *   the built-in messages, so we won't have lost anything for
             *   trying 
             */
            err_load_vm_message_file(fp);
            
            /* we're done with the file */
            osfcls(fp);
        }
    }

    /* remember the host interface */
    G_host_ifc = opts->hostifc;

    /* initialize the system debug log file name */
    char path[OSFNMAX];
    opts->hostifc->get_special_file_path(path, sizeof(path), OS_GSP_LOGFILE);
    os_build_full_path(G_syslogfile, sizeof(G_syslogfile),
                       path, "tadslog.txt");

    /* we don't have a resource loader for program resources yet */
    G_res_loader = 0;

    /* create the object table */
    VM_IF_ALLOC_PRE_GLOBAL(G_obj_table = new CVmObjTable());
    G_obj_table->init(vmg0_);

    /* 
     *   Create the memory manager.  Empirically, our hybrid heap allocator
     *   is faster than the standard C++ run-time library's allocator on many
     *   platforms, so use it instead of hte basic 'malloc' allocator. 
     */
    G_varheap = new CVmVarHeapHybrid(G_obj_table);
    // G_varheap = new CVmVarHeapMalloc(); to use the system 'malloc' instead
    G_mem = new CVmMemory(vmg_ G_varheap);

    /* create the undo manager */
    G_undo = new CVmUndo(VM_UNDO_MAX_RECORDS, VM_UNDO_MAX_SAVEPTS);

    /* create the metafile and function set tables */
    G_meta_table = new CVmMetaTable(5);
    G_bif_table = new CVmBifTable(5);

    /* initialize the metaclass registration tables */
    vm_register_metaclasses();

    /* initialize the TadsObject class */
    CVmObjTads::class_init(vmg0_);

    /* create the byte-code interpreter */
    VM_IFELSE_ALLOC_PRE_GLOBAL(
        G_interpreter = new CVmRun(VM_STACK_SIZE, vm_init_stack_reserve()),
        G_interpreter->init());

    /* presume we won't create debugger information */
    G_debugger = 0;
    G_srcf_table = 0;

    /* presume we don't have a network configuration */
    G_net_config = 0;

    /* initialize the debugger if present */
    vm_init_debugger(vmg0_);

    /* create the source file table */
    G_srcf_table = new CVmSrcfTable();

    /* create the pre-defined object mapper */
    VM_IFELSE_ALLOC_PRE_GLOBAL(G_predef = new CVmPredef, G_predef->reset());

    /* presume we're in normal execution mode (not preinit) */
    G_preinit_mode = FALSE;

    /* allocate the TADS intrinsic function set's globals */
    G_bif_tads_globals = new CVmBifTADSGlobals(vmg0_);

    /* allocate the BigNumber register cache */
    G_bignum_cache = new CVmBigNumCache(32);

    /* no image loader yet */
    G_image_loader = 0;

    /*
     *   If the caller explicitly specified a character set, use it.
     *   Otherwise, ask the OS layer for the default character set we
     *   should use. 
     */
    if (charset == 0)
    {
        /* the user did not specify a mapping - ask the OS for the default */
        os_get_charmap(disp_mapname, OS_CHARMAP_DISPLAY);

        /* use the name we got from the OS */
        charset = disp_mapname;

        /* there's no explicit global character set name setting to store */
        G_disp_cset_name = 0;
    }
    else
    {
        /* save the global character set name */
        G_disp_cset_name = lib_copy_str(charset);
    }

    /* create the display character maps */
    G_cmap_from_ui = CCharmapToUni::load(map_loader, charset);
    G_cmap_to_ui = CCharmapToLocal::load(map_loader, charset);

    /* create the filename character maps */
    os_get_charmap(filename_mapname, OS_CHARMAP_FILENAME);
    G_cmap_from_fname = CCharmapToUni::load(map_loader, filename_mapname);
    G_cmap_to_fname = CCharmapToLocal::load(map_loader, filename_mapname);

    /* create the file-contents character maps */
    os_get_charmap(filecont_mapname, OS_CHARMAP_FILECONTENTS);
    G_cmap_from_file = CCharmapToUni::load(map_loader, filecont_mapname);
    G_cmap_to_file = CCharmapToLocal::load(map_loader, filecont_mapname);

    /* 
     *   If the caller specified a separate log-file character set, create
     *   the mapping.  Otherwise, just use the to-file mapper for log files.
     */
    if (opts->log_charset != 0)
    {
        /* load the specified log file output mapping */
        G_cmap_to_log = CCharmapToLocal::load(map_loader, opts->log_charset);
    }
    else
    {
        /* no log file mapping is specified, so use the generic file map */
        if ((G_cmap_to_log = G_cmap_to_file) != 0)
            G_cmap_to_log->add_ref();
    }

    /* make a note of whether we had any problems loading the maps */
    disp_map_err = (G_cmap_from_ui == 0 || G_cmap_to_ui == 0);

    /* if we failed to create any of the maps, load defaults */
    if (G_cmap_from_ui == 0)
        G_cmap_from_ui = CCharmapToUni::load(map_loader, "us-ascii");
    if (G_cmap_to_ui == 0)
        G_cmap_to_ui = CCharmapToLocal::load(map_loader, "us-ascii");
    if (G_cmap_from_fname == 0)
        G_cmap_from_fname = CCharmapToUni::load(map_loader, "us-ascii");
    if (G_cmap_to_fname == 0)
        G_cmap_to_fname = CCharmapToLocal::load(map_loader, "us-ascii");
    if (G_cmap_from_file == 0)
        G_cmap_from_file = CCharmapToUni::load(map_loader, "us-ascii");
    if (G_cmap_to_file == 0)
        G_cmap_to_file = CCharmapToLocal::load(map_loader, "us-ascii");
    if (G_cmap_to_log == 0)
        G_cmap_to_log = CCharmapToLocal::load(map_loader, "us-ascii");

    /* create the primary console */
    G_console = opts->clientifc->create_console(VMGLOB_ADDR);

    /* 
     *   if we had any trouble opening the display character mapping file,
     *   make a note that we are using a default mapping 
     */
    if (disp_map_err)
    {
        const char *msg;
        char buf[256];

        /* get the message */
        msg = err_get_msg(vm_messages, vm_message_count,
                          VMERR_NO_CHARMAP_FILE, TRUE);

        /* format it */
        sprintf(buf, msg, charset);

        /* display it */
        opts->clientifc->display_error(VMGLOB_ADDR, 0, buf, TRUE);
    }
}