1 #ifdef RCSID
2 static char RCSid[] =
3 "$Header: d:/cvsroot/tads/tads3/test/test_comp_obj.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_link.cpp - parser test: link object files to image file
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 "tcmake.h"
37 #include "vmimage.h"
38 #include "vmrunsym.h"
39 #include "t3test.h"
40 
41 
errexit(const char * msg)42 static void errexit(const char *msg)
43 {
44     printf("%s\n", msg);
45     exit(1);
46 }
47 
main(int argc,char ** argv)48 int main(int argc, char **argv)
49 {
50     CResLoader *res_loader;
51     CTcHostIfc *hostifc;
52     int curarg;
53     int fatal_error_count = 0;
54     osfildef *fpout = 0;
55     int next_local = 0;
56     CVmFile *imgfile = 0;
57     CVmFile *objfile = 0;
58     const char *imgfname;
59     int success;
60     char pathbuf[OSFNMAX];
61     static const char tool_data[4] = { 't', 's', 't', 'L' };
62 
63     /* initialize for testing */
64     test_init();
65 
66     /* create the host interface object */
67     hostifc = new CTcHostIfcStdio();
68 
69     /* create a resource loader */
70     os_get_special_path(pathbuf, sizeof(pathbuf), argv[0], OS_GSP_T3_RES);
71     res_loader = new CResLoader(pathbuf);
72 
73     /* initialize the compiler */
74     CTcMain::init(hostifc, res_loader, 0);
75 
76     err_try
77     {
78         /* scan arguments */
79         for (curarg = 1 ; curarg < argc ; ++curarg)
80         {
81             char *p;
82 
83             /* get the argument string for easy reference */
84             p = argv[curarg];
85 
86             /* if it's not an option, we're done */
87             if (*p != '-')
88                 break;
89 
90             if (*(p + 1) == 'v')
91             {
92                 /* set verbose mode */
93                 G_tcmain->set_verbosity(TRUE);
94             }
95             else
96             {
97                 /*
98                  *   invalid usage - consume all the arguments and fall
99                  *   through to the usage checker
100                  */
101                 curarg = argc;
102                 break;
103             }
104         }
105 
106         /* check arguments */
107         if (curarg + 2 > argc)
108         {
109             /* terminate the compiler */
110             CTcMain::terminate();
111 
112             /* delete our objects */
113             delete res_loader;
114 
115             /* exit with an error */
116             errexit("usage: test_link [options] obj-file [obj-file [...]] "
117                     "image-file\n"
118                     "options:\n"
119                     "   -v     - verbose error messages");
120         }
121 
122         /* set up an output file */
123         imgfname = argv[argc - 1];
124         fpout = osfopwb(imgfname, OSFTT3IMG);
125         if (fpout == 0)
126             errexit("unable to open image file");
127         imgfile = new CVmFile();
128         imgfile->set_file(fpout, 0);
129 
130         /* read the object files */
131         for ( ; curarg < argc - 1 ; ++curarg)
132         {
133             osfildef *fpobj;
134 
135             /* open this object file */
136             fpobj = osfoprb(argv[curarg], OSFTT3OBJ);
137             if (fpobj == 0)
138             {
139                 printf("unable to open object file \"%s\"\n", argv[curarg]);
140                 goto done;
141             }
142 
143             /* note the loading */
144             printf("loading %s\n", argv[curarg]);
145 
146             /* set up the CVmFile object for it */
147             objfile = new CVmFile();
148             objfile->set_file(fpobj, 0);
149 
150             /* read the object file */
151             G_cg->load_object_file(objfile, argv[curarg]);
152 
153             /* done with the object file */
154             delete objfile;
155             objfile = 0;
156         }
157 
158         /* check for unresolved externals */
159         if (G_prs->check_unresolved_externs())
160             goto done;
161 
162         /* write the image file */
163         G_cg->write_to_image(imgfile, 0, tool_data);
164 
165     done: ;
166     }
167     err_catch(exc)
168     {
169         /*
170          *   if it's not a general internal or fatal error, log it; don't
171          *   log general errors, since these will have been logged as
172          *   specific internal errors before being thrown
173          */
174         if (exc->get_error_code() != TCERR_INTERNAL_ERROR
175             && exc->get_error_code() != TCERR_FATAL_ERROR)
176             G_tok->log_error(TC_SEV_FATAL, exc->get_error_code());
177 
178         /* count the fatal error */
179         ++fatal_error_count;
180     }
181     err_end;
182 
183     /* report errors */
184     fprintf(stderr,
185             "Warnings: %d\n"
186             "Errors:   %d\n"
187             "Longest string: %d, longest list: %d\n",
188             G_tcmain->get_warning_count(),
189             G_tcmain->get_error_count() + fatal_error_count,
190             G_cg->get_max_str_len(), G_cg->get_max_list_cnt());
191 
192     /*
193      *   note whether or not the compilation was successful - it succeeded
194      *   if we had no errors or fatal errors
195      */
196     success = (G_tcmain->get_error_count() + fatal_error_count == 0);
197 
198     /* delete the object file object (this closes the file) */
199     delete imgfile;
200 
201     /* if we have an open object file, close it */
202     if (objfile != 0)
203         delete objfile;
204 
205     /*
206      *   if any errors occurred, delete the object file in the external
207      *   file system - this prevents us from leaving around an incomplete
208      *   or corrupted image file when compilation fails, and helps
209      *   'make'-type tools realize that they must generate the image file
210      *   target again on the next build, even if source files didn't
211      *   change
212      */
213     if (!success)
214         osfdel(imgfname);
215 
216     /* shut down the compiler */
217     CTcMain::terminate();
218 
219     /* done with the res loader */
220     delete res_loader;
221 
222     /* delete the host interface */
223     delete hostifc;
224 
225     /* show any unfreed memory */
226     t3_list_memory_blocks(0);
227 
228     /*
229      *   terminate - exit with a success indication if we had no errors
230      *   (other than warnings); exit with an error indication otherwise
231      */
232     return (success ? OSEXSUCC : OSEXFAIL);
233 }
234 
235 /*
236  *   dummy 'make' object implementation
237  */
write_build_config_to_sym_file(class CVmFile *)238 void CTcMake::write_build_config_to_sym_file(class CVmFile *)
239 {
240 }
241 
242 /* ------------------------------------------------------------------------ */
243 /*
244  *   dummy implementation of runtime symbol table
245  */
add_sym(const char *,size_t,const vm_val_t *)246 void CVmRuntimeSymbols::add_sym(const char *, size_t,
247                                 const vm_val_t *)
248 {
249 }
250