~ubuntu-branches/ubuntu/wily/gargoyle-free/wily-proposed

« back to all changes in this revision

Viewing changes to tads/tads3/test/test_prs.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Sylvain Beucler
  • Date: 2009-09-11 20:09:43 UTC
  • Revision ID: james.westby@ubuntu.com-20090911200943-idgzoyupq6650zpn
Tags: upstream-2009-08-25
ImportĀ upstreamĀ versionĀ 2009-08-25

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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