1 #ifdef RCSID
2 static char RCSid[] =
3 "$Header: d:/cvsroot/tads/tads3/test/test_prs_top.cpp,v 1.1 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: test parsing from the top level
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 
errexit(const char * msg)44 static void errexit(const char *msg)
45 {
46     printf("%s\n", msg);
47     exit(1);
48 }
49 
main(int argc,char ** argv)50 int main(int argc, char **argv)
51 {
52     CResLoader *res_loader;
53     CTcHostIfc *hostifc;
54     int curarg;
55     int fatal_error_count = 0;
56     osfildef *fpout = 0;
57     CVmFile *imgfile = 0;
58     CTcUnasSrcCodeStr *unas_in;
59     CTcUnasOutStdio unas_out;
60     CTPNStmProg *node;
61     const char *image_fname;
62     int success;
63     int unasm = FALSE;
64     uchar xor_mask = 0;
65     char pathbuf[OSFNMAX];
66 
67     /* initialize for testing */
68     test_init();
69 
70     /* create the host interface object */
71     hostifc = new CTcHostIfcStdio();
72 
73     /* create a resource loader */
74     os_get_special_path(pathbuf, sizeof(pathbuf), argv[0], OS_GSP_T3_RES);
75     res_loader = new CResLoader(pathbuf);
76 
77     /* initialize the compiler */
78     CTcMain::init(hostifc, res_loader, "us-ascii");
79 
80     /* use test reporting mode */
81     G_tok->set_test_report_mode(TRUE);
82     G_tcmain->set_test_report_mode(TRUE);
83 
84     /* create the disassembler input stream */
85     unas_in = new CTcUnasSrcCodeStr(G_cs);
86 
87     err_try
88     {
89         static const char tool_data[4] = { 't', 's', 't', 'P' };
90 
91         /* scan options */
92         for (curarg = 1 ; curarg < argc ; ++curarg)
93         {
94             char *p;
95 
96             /* get the argument string for easy reference */
97             p = argv[curarg];
98 
99             /* if it's not an option, we're done */
100             if (*p != '-')
101                 break;
102 
103             /* if it's a -I argument, use it */
104             if (*(p + 1) == 'I')
105             {
106                 char *path;
107 
108                 /*
109                  *   if it's with this argument, read it, otherwise move
110                  *   on to the next argument
111                  */
112                 if (*(p + 2) == '\0')
113                     path = argv[++curarg];
114                 else
115                     path = p + 2;
116 
117                 /* add the directory to the include path list */
118                 G_tok->add_inc_path(path);
119             }
120             else if (*(p + 1) == 'v')
121             {
122                 /* set verbose mode */
123                 G_tcmain->set_verbosity(TRUE);
124             }
125             else if (*(p + 1) == 'u')
126             {
127                 /* note unassembly mode */
128                 unasm = TRUE;
129             }
130             else
131             {
132                 /*
133                  *   invalid usage - consume all the arguments and fall
134                  *   through to the usage checker
135                  */
136                 curarg = argc;
137                 break;
138             }
139         }
140 
141         /* check arguments */
142         if (curarg + 2 != argc)
143         {
144             /* terminate the compiler */
145             CTcMain::terminate();
146 
147             /* delete our objects */
148             delete res_loader;
149 
150             /* exit with an error */
151             errexit("usage: test_prs [options] <source-file> <image-file>\n"
152                     "options:\n"
153                     "   -Idir  - add dir to include path\n"
154                     "   -v     - verbose error messages");
155         }
156 
157         /* add the default system include directory to the include path */
158         os_get_special_path(pathbuf, sizeof(pathbuf), argv[0], OS_GSP_T3_INC);
159         G_tok->add_inc_path(pathbuf);
160 
161         /* set up the tokenizer with the main input file */
162         if (G_tok->set_source(argv[curarg], argv[curarg]))
163             errexit("unable to open source file");
164 
165         /* set up an output file */
166         image_fname = argv[curarg+1];
167         fpout = osfopwb(image_fname, OSFTT3IMG);
168         if (fpout == 0)
169             errexit("unable to open image file");
170         imgfile = new CVmFile();
171         imgfile->set_file(fpout, 0);
172 
173         /* read the first token */
174         G_tok->next();
175 
176         /* parse at the top level */
177         node = G_prs->parse_top();
178 
179         /* if errors occurred during parsing, stop here */
180         if (G_tcmain->get_error_count() != 0 || node == 0)
181             goto done;
182 
183         /* fold symbolic constants for all nodes */
184         node->fold_constants(G_prs->get_global_symtab());
185 
186         /* if errors occurred during constant folding, stop now */
187         if (G_tcmain->get_error_count() != 0)
188             goto done;
189 
190         /* generate code and write the image file */
191         node->build_image(imgfile, xor_mask, tool_data);
192 
193         /* if errors occurred during code generation, stop now */
194         if (G_tcmain->get_error_count() != 0)
195             goto done;
196 
197         /* disassemble the result if desired */
198         if (unasm)
199             CTcT3Unasm::disasm(unas_in, &unas_out);
200 
201     done: ;
202     }
203     err_catch(exc)
204     {
205         /*
206          *   if it's not a general internal or fatal error, log it; don't
207          *   log general errors, since these will have been logged as
208          *   specific internal errors before being thrown
209          */
210         if (exc->get_error_code() != TCERR_INTERNAL_ERROR
211             && exc->get_error_code() != TCERR_FATAL_ERROR)
212             G_tok->log_error(TC_SEV_FATAL, exc->get_error_code());
213 
214         /* count the fatal error */
215         ++fatal_error_count;
216     }
217     err_end;
218 
219     /* report errors */
220     fprintf(stderr,
221             "Warnings: %d\n"
222             "Errors:   %d\n"
223             "Longest string: %d, longest list: %d\n",
224             G_tcmain->get_warning_count(),
225             G_tcmain->get_error_count() + fatal_error_count,
226             G_cg->get_max_str_len(), G_cg->get_max_list_cnt());
227 
228     /*
229      *   note whether or not the compilation was successful - it succeeded
230      *   if we had no errors or fatal errors
231      */
232     success = (G_tcmain->get_error_count() + fatal_error_count == 0);
233 
234     /* delete the image file object (this closes the file) */
235     delete imgfile;
236 
237     /*
238      *   if any errors occurred, delete the image file in the external
239      *   file system - this prevents us from leaving around an incomplete
240      *   or corrupted image file when compilation fails, and helps
241      *   'make'-type tools realize that they must generate the image file
242      *   target again on the next build, even if source files didn't
243      *   change
244      */
245     if (!success)
246         osfdel(image_fname);
247 
248     /* delete the disassembler input object */
249     delete unas_in;
250 
251     /* shut down the compiler */
252     CTcMain::terminate();
253 
254     /* done with the res loader */
255     delete res_loader;
256 
257     /* delete the host interface */
258     delete hostifc;
259 
260     /* show any unfreed memory */
261     t3_list_memory_blocks(0);
262 
263     /*
264      *   terminate - exit with a success indication if we had no errors
265      *   (other than warnings); exit with an error indication otherwise
266      */
267     return (success ? OSEXSUCC : OSEXFAIL);
268 }
269 
270 /*
271  *   dummy 'make' object implementation
272  */
write_build_config_to_sym_file(class CVmFile *)273 void CTcMake::write_build_config_to_sym_file(class CVmFile *)
274 {
275 }
276 
277 /* ------------------------------------------------------------------------ */
278 /*
279  *   dummy implementation of runtime symbol table
280  */
add_sym(const char *,size_t,const vm_val_t *)281 void CVmRuntimeSymbols::add_sym(const char *, size_t,
282                                 const vm_val_t *)
283 {
284 }
285