cfad47cfa3/t3compiler/tads3/test/test_prs.cpp

4b825dc642cb6eb9a060e54bf8d69288fbee4904cfad47cfa334b206c65f22086bcc5d63e6f70944
1
#ifdef RCSID
2
static char RCSid[] =
3
"$Header: d:/cvsroot/tads/tads3/test/TEST_PRS.CPP,v 1.4 1999/07/11 00:47:03 MJRoberts Exp $";
4
#endif
5
6
/* 
7
 *   Copyright (c) 1999, 2002 Michael J. Roberts.  All Rights Reserved.
8
 *   
9
 *   Please see the accompanying license file, LICENSE.TXT, for information
10
 *   on using and copying this software.  
11
 */
12
/*
13
Name
14
  test_prs.cpp - parser test
15
Function
16
  
17
Notes
18
  
19
Modified
20
  05/01/99 MJRoberts  - Creation
21
*/
22
23
#include <stdlib.h>
24
#include <stdio.h>
25
26
#include "os.h"
27
#include "t3std.h"
28
#include "tctok.h"
29
#include "resload.h"
30
#include "tcmain.h"
31
#include "tchostsi.h"
32
#include "tcglob.h"
33
#include "tcprs.h"
34
#include "tctarg.h"
35
#include "vmfile.h"
36
#include "tcunas.h"
37
#include "tct3unas.h"
38
#include "tcmake.h"
39
#include "vmimage.h"
40
#include "vmrunsym.h"
41
#include "t3test.h"
42
43
44
static void errexit(const char *msg)
45
{
46
    printf("%s\n", msg);
47
    exit(1);
48
}
49
50
static void show_const(int level, CTcPrsNode *result)
51
{
52
    CTPNListEle *ele;
53
    int i;
54
    
55
    for (i = level*3 ; i != 0 ; --i)
56
        printf(" ");
57
    
58
    if (result == 0)
59
    {
60
        printf("no value\n");
61
    }
62
    else if (result->is_const())
63
    {
64
        switch(result->get_const_val()->get_type())
65
        {
66
        case TC_CVT_UNK:
67
            printf("unknown\n");
68
            break;
69
70
        case TC_CVT_NIL:
71
            printf("nil\n");
72
            break;
73
74
        case TC_CVT_TRUE:
75
            printf("true\n");
76
            break;
77
78
        case TC_CVT_INT:
79
            printf("int = %ld\n",
80
                   result->get_const_val()->get_val_int());
81
            break;
82
83
        case TC_CVT_SSTR:
84
            printf("sstr = %.*s\n",
85
                   (int)result->get_const_val()->get_val_str_len(),
86
                   result->get_const_val()->get_val_str());
87
            break;
88
89
        case TC_CVT_LIST:
90
            printf("list: %d elements\n",
91
                   result->get_const_val()->get_val_list()
92
                   ->get_count());
93
            for (ele = result->get_const_val()->get_val_list()->get_head() ;
94
                 ele != 0 ; ele = ele->get_next())
95
                show_const(level + 1, ele->get_expr());
96
            break;
97
98
        case TC_CVT_OBJ:
99
            printf("object: %ld\n", result->get_const_val()->get_val_obj());
100
            break;
101
102
        case TC_CVT_PROP:
103
            printf("property id: %d\n",
104
                   result->get_const_val()->get_val_prop());
105
            break;
106
107
        case TC_CVT_FUNCPTR:
108
            printf("function pointer: %.*s\n",
109
                   (int)result->get_const_val()->get_val_funcptr_sym()
110
                   ->get_sym_len(),
111
                   result->get_const_val()->get_val_funcptr_sym()
112
                   ->get_sym());
113
            break;
114
115
        case TC_CVT_ANONFUNCPTR:
116
            printf("anonymous function pointer\n");
117
            break;
118
119
        default:
120
            break;
121
        }
122
    }
123
    else
124
        printf("Non-constant value\n");
125
}
126
127
/*
128
 *   node list entry 
129
 */
130
struct node_entry
131
{
132
    node_entry(CTcPrsNode *n, CTcTokFileDesc *d, long l)
133
    {
134
        node = n;
135
        desc = d;
136
        linenum = l;
137
    }
138
    
139
    /* top-level parse node for this line */
140
    CTcPrsNode *node;
141
142
    /* file and line of source where node started */
143
    CTcTokFileDesc *desc;
144
    long linenum;
145
146
    /* next entry in list */
147
    node_entry *nxt;
148
};
149
150
int main(int argc, char **argv)
151
{
152
    CResLoader *res_loader;
153
    CTcHostIfc *hostifc;
154
    int curarg;
155
    int fatal_error_count = 0;
156
    node_entry *node_head = 0;
157
    node_entry *node_tail = 0;
158
    osfildef *fpout = 0;
159
    CVmFile *imgfile = 0;
160
    ulong next_obj_id = 1;
161
    uint next_prop_id = 1;
162
    int next_local = 0;
163
    CTcTokFileDesc *desc;
164
    long linenum;
165
    CTcUnasSrcCodeStr *unas_in;
166
    CTcUnasOutStdio unas_out;
167
    char pathbuf[OSFNMAX];
168
169
    /* initialize for testing */
170
    test_init();
171
172
    /* create the host interface object */
173
    hostifc = new CTcHostIfcStdio();
174
175
    /* create a resource loader */
176
    os_get_special_path(pathbuf, sizeof(pathbuf), argv[0], OS_GSP_T3_RES);
177
    res_loader = new CResLoader(pathbuf);
178
179
    /* initialize the compiler */
180
    CTcMain::init(hostifc, res_loader, 0);
181
182
    /* create the disassembler input stream */
183
    unas_in = new CTcUnasSrcCodeStr(G_cs);
184
185
    err_try
186
    {
187
        /* scan -I arguments */
188
        for (curarg = 1 ; curarg < argc ; ++curarg)
189
        {
190
            char *p;
191
            
192
            /* get the argument string for easy reference */
193
            p = argv[curarg];
194
            
195
            /* if it's not an option, we're done */
196
            if (*p != '-')
197
                break;
198
            
199
            /* if it's a -I argument, use it */
200
            if (*(p + 1) == 'I')
201
            {
202
                char *path;
203
                
204
                /* 
205
                 *   if it's with this argument, read it, otherwise move
206
                 *   on to the next argument 
207
                 */
208
                if (*(p + 2) == '\0')
209
                    path = argv[++curarg];
210
                else
211
                    path = p + 2;
212
                
213
                /* add the directory to the include path list */
214
                G_tok->add_inc_path(path);
215
            }
216
            else if (*(p + 1) == 'v')
217
            {
218
                /* set verbose mode */
219
                G_tcmain->set_verbosity(TRUE);
220
            }
221
            else
222
            {
223
                /* 
224
                 *   invalid usage - consume all the arguments and fall
225
                 *   through to the usage checker 
226
                 */
227
                curarg = argc;
228
                break;
229
            }
230
        }
231
        
232
        /* check arguments */
233
        if (curarg + 2 != argc)
234
        {
235
            /* terminate the compiler */
236
            CTcMain::terminate();
237
            
238
            /* delete our objects */
239
            delete res_loader;
240
            
241
            /* exit with an error */
242
            errexit("usage: test_prs [options] <source-file> <image-file>\n"
243
                    "options:\n"
244
                    "   -Idir  - add dir to include path\n"
245
                    "   -v     - verbose error messages");
246
        }
247
        
248
        /* set up the tokenizer with the main input file */
249
        if (G_tok->set_source(argv[curarg], argv[curarg]))
250
            errexit("unable to open source file");
251
252
        /* set up an output file */
253
        fpout = osfopwb(argv[curarg+1], OSFTT3IMG);
254
        if (fpout == 0)
255
            errexit("unable to open image file");
256
        imgfile = new CVmFile();
257
        imgfile->set_file(fpout, 0);
258
259
        /* read the first token */
260
        G_tok->next();
261
        
262
        /* parse expressions */
263
        for (;;)
264
        {
265
            CTcPrsNode *result;
266
            CTcSymbol *entry;
267
268
            /* if we're at end of file, we're done */
269
            if (G_tok->getcur()->gettyp() == TOKT_EOF)
270
                break;
271
272
            /* check for our fake declarations */
273
            switch(G_tok->getcur()->gettyp())
274
            {
275
            case TOKT_OBJECT:
276
                /* add an object symbol */
277
                G_tok->next();
278
                entry = new CTcSymObj(G_tok->getcur()->get_text(),
279
                                      G_tok->getcur()->get_text_len(),
280
                                      FALSE, next_obj_id++, FALSE,
281
                                      TC_META_TADSOBJ, 0);
282
                G_prs->get_global_symtab()->add_entry(entry);
283
284
                /* skip the object name */
285
                G_tok->next();
286
                break;
287
288
            case TOKT_FUNCTION:
289
                /* add a function symbol */
290
                G_tok->next();
291
                entry = new CTcSymFunc(G_tok->getcur()->get_text(),
292
                                       G_tok->getcur()->get_text_len(),
293
                                       FALSE, 0, FALSE, TRUE,
294
                                       FALSE, FALSE, FALSE);
295
                G_prs->get_global_symtab()->add_entry(entry);
296
297
                /* skip the function name */
298
                G_tok->next();
299
                break;
300
301
            case TOKT_LOCAL:
302
                /* add a local variable symbol */
303
                G_tok->next();
304
                entry = new CTcSymLocal(G_tok->getcur()->get_text(),
305
                                        G_tok->getcur()->get_text_len(),
306
                                        FALSE, FALSE, next_local++);
307
                G_prs->get_global_symtab()->add_entry(entry);
308
309
                /* skip the function name */
310
                G_tok->next();
311
                break;
312
                
313
            default:
314
                /* note the starting line */
315
                desc = G_tok->get_last_desc();
316
                linenum = G_tok->get_last_linenum();
317
                
318
                /* parse an expression */
319
                result = G_prs->parse_expr();
320
                
321
                /* add it to our list */
322
                if (result != 0)
323
                {
324
                    node_entry *cur;
325
                    
326
                    /* create a new list entry */
327
                    cur = new node_entry(result, desc, linenum);
328
                    
329
                    /* link it at the end of our list */
330
                    cur->nxt = 0;
331
                    if (node_tail != 0)
332
                        node_tail->nxt = cur;
333
                    else
334
                        node_head = cur;
335
                    node_tail = cur;
336
                }
337
            }
338
339
            /* parse a semicolon */
340
            if (G_prs->parse_req_sem())
341
                break;
342
        }
343
344
        /* 
345
         *   if there were no parse errors, run through our node list and
346
         *   generate code 
347
         */
348
        if (G_tcmain->get_error_count() == 0)
349
        {
350
            /* 
351
             *   loop through our node list; generate code and then delete
352
             *   each list entry 
353
             */
354
            while (node_head != 0)
355
            {
356
                node_entry *nxt;
357
358
                /* remember the next entry */
359
                nxt = node_head->nxt;
360
361
                /* 
362
                 *   set this line's descriptor as current, for error
363
                 *   reporting purposes 
364
                 */
365
                G_tok->set_line_info(node_head->desc, node_head->linenum);
366
367
                /* fold symbolic constants */
368
                node_head->node =
369
                    node_head->node
370
                    ->fold_constants(G_prs->get_global_symtab());
371
372
                /* if it's a constant value, display it */
373
                show_const(0, node_head->node);
374
375
                /* 
376
                 *   generate code; for testing purposes, don't discard
377
                 *   anything, to ensure we perform all generation 
378
                 */
379
                node_head->node->gen_code(FALSE, FALSE);
380
381
                /* disassemble this much */
382
                unas_out.print("// line %lu\n", node_head->linenum);
383
                CTcT3Unasm::disasm(unas_in, &unas_out);
384
385
                /* delete this entry */
386
                delete node_head;
387
388
                /* move on to the next entry */
389
                node_head = nxt;
390
            }
391
        }
392
    }
393
    err_catch(exc)
394
    {
395
        /* 
396
         *   if it's not a general internal or fatal error, log it; don't
397
         *   log general errors, since these will have been logged as
398
         *   specific internal errors before being thrown 
399
         */
400
        if (exc->get_error_code() != TCERR_INTERNAL_ERROR
401
            && exc->get_error_code() != TCERR_FATAL_ERROR)
402
            G_tok->log_error(TC_SEV_FATAL, exc->get_error_code());
403
404
        /* count the fatal error */
405
        ++fatal_error_count;
406
    }
407
    err_end;
408
409
    /* report errors */
410
    fprintf(stderr,
411
            "Warnings: %d\n"
412
            "Errors:   %d\n"
413
            "Longest string: %d, longest list: %d\n",
414
            G_tcmain->get_warning_count(),
415
            G_tcmain->get_error_count() + fatal_error_count,
416
            G_cg->get_max_str_len(), G_cg->get_max_list_cnt());
417
418
    /* delete the disassembler input object */
419
    delete unas_in;
420
421
    /* shut down the compiler */
422
    CTcMain::terminate();
423
424
    /* done with the res loader */
425
    delete res_loader;
426
427
    /* delete the image file */
428
    delete imgfile;
429
430
    /* delete the host interface */
431
    delete hostifc;
432
433
    /* show any unfreed memory */
434
    t3_list_memory_blocks(0);
435
436
    /* success */
437
    return 0;
438
}
439
440
/*
441
 *   dummy 'make' object implementation
442
 */
443
void CTcMake::write_build_config_to_sym_file(class CVmFile *)
444
{
445
}
446
447
448
449
/* ------------------------------------------------------------------------ */
450
/*
451
 *   dummy implementation of runtime symbol table 
452
 */
453
void CVmRuntimeSymbols::add_sym(const char *, size_t,
454
                                const vm_val_t *)
455
{
456
}
457