*** empty log message ***
[h316.git] / pc-tools / ldc2 / src / main.cpp
CommitLineData
798b0c1d 1/* ldc2 preliminary main program */
2
de6b6757 3#include <sys/types.h>
4#include <sys/stat.h>
5#include <fcntl.h>
7880ae2d 6
798b0c1d 7#include <vector>
8#include <string>
f9d603d2 9
ea4c19a4 10#include "config.hh"
11#include "tool.hh"
97b26985 12
13#include "tape_block.hh"
fed2c751 14#include "data_block_0.hh"
15
798b0c1d 16using namespace std;
17
7880ae2d 18#ifndef BUILD_STAMP
19#define BUILD_STAMP ""
20#endif
21
22#ifndef VERSION
23#define VERSION "0.0"
24#endif
25
874a2bd8 26#define ID_STRING "\n ldc2 - The X16 object tape analyser\n\
7880ae2d 27 (C) 2007 Philipp Hachtmann\n\n\
28 Version %s, built %s\n %s\n\n"
29
874a2bd8 30/******************************************************************************/
7880ae2d 31
874a2bd8 32static FILE * stdwarn; //! Suppressable warning output file pointer.
33static vector<tape_block*> tape; //! Represents the whole tape contents.
34static vector<vector<tape_block*> > objects; //! Tape content in objects.
7880ae2d 35
874a2bd8 36static int errors=0;
37static int warnings=0;
38static int errcode=0; //! Variable for error codes.
7880ae2d 39
874a2bd8 40
41void exit_on_error(){
42 if (errors){
43 fprintf(stderr,"Failed. (%i)\n",errcode);
44 exit(errcode);
7880ae2d 45 }
874a2bd8 46}
909d3603 47
874a2bd8 48/******************************************************************************/
49/*!
50 *\brief Read in Tape data and do some checks and messages.
51 *
52 * This routine reads in the tape data.
53 * During reading in, checksums are checked and
54 * /da001/ information is generated. No object integrity test.
55 * Tape block object pointers are put into the global vector
56 * tape.
57 */
58void read_tape(){
59
60 tape_block * block=0; //! Pointer to current block.
61 bool read_ahead=true; //! Continue scanning for blocks.
62 int read_pointer=0; //! Read position in input.
63 int block_start=0; //! Start of block position in input.
64 int block_end=0; //! End of block position in input.
65 int blocks_read=0; //! Number of blocks read in.
ad324d29 66
874a2bd8 67 bool spaced=false; //! Help flag for spaced messages.
68
69 string message; //! A warning or help message.
7880ae2d 70
874a2bd8 71
fed2c751 72 while(read_ahead){
874a2bd8 73
74 bool err_checksum=false;
75 bool err_integrity=false;
76
77 bool warning=false;
78 bool error=false;
79
7880ae2d 80 try{
81 block=tape_block::gen_from_fd(in_fd);
7880ae2d 82 }
83
84 catch(tape_block::eof_legal_exception &e){
85 read_pointer+=e.get_consumed();
86 break; // Immediately leave read loop.
87 }
88
89 catch(tape_block::io_error_exception){
fed2c751 90 if (in_fd){
7880ae2d 91 fprintf(stderr,"Error: Could not read from \"%s\"!\n",cfg_infile.c_str());
fed2c751 92 } else {
7880ae2d 93 fprintf(stderr,"Error: Could not read from stdin!\n");
fed2c751 94 }
874a2bd8 95 error=true;
fed2c751 96 errcode=2;
7880ae2d 97 break; // Immediately leave read loop.
98 }
99
100 catch(tape_block::eof_illegal_exception &e){
101 block=e.get_block();
874a2bd8 102 err_integrity=true;
103 read_ahead=false;
7880ae2d 104 if (cfg_ignore_block_errors){
874a2bd8 105 message="Warning: Block integrity check failed!\n";
106 warning=true;
7880ae2d 107 } else {
874a2bd8 108 message="Error: Block integrity check failed!\n";
109 error=true;
7880ae2d 110 errcode=3;
fed2c751 111 }
7880ae2d 112 }
113
114 catch(tape_block::checksum_error_exception &e){
115 block=e.get_block();
874a2bd8 116 err_checksum=true;
7880ae2d 117 if (cfg_ignore_checksum_errors){
874a2bd8 118 message="Warning: Block checksum wrong!\n";
119 warning=true;
fed2c751 120 } else {
874a2bd8 121 message="Error: Block checksum wrong!\n";
122 error=true;
7880ae2d 123 read_ahead=false;
124 errcode=4;
fed2c751 125 }
7880ae2d 126 }
127
874a2bd8 128 // Now let's check for block type
129 if ((!error)&&(!warning)&&!block->has_known_type()){
130 if (cfg_ignore_unknown_block_errors){
131 message="Warning: Unknown Block type!";
132 warning=true;
133 }else{
134 message="Error: Unknown Block type!";
135 error=true;
136 read_ahead=false;
137 errcode=5;
138 }
139 }
140
141 // Count block.
142 blocks_read++;
143 tape.insert(tape.end(),block);
144 block_start=read_pointer+block->get_discarded_bytes();
145 block_end=block_start+block->get_raw_size()-1;
146 read_pointer=block_end+1;
147
148 FILE * fp=stdwarn;
149 if (error) fp=stderr;
150
151 if (cfg_verbose||error||warning){
152 if (!spaced) fprintf(fp,"\n");
153 spaced=false;
154 fprintf(fp,"Block No.%03i: Start:0x%04x End:0x%04x Size:0x%02x\n",
155 blocks_read-1,
156 block_start,
157 block_end,
158 block->get_raw_size());
159 }
160
161 if (error) fprintf(stderr,message.c_str());
162 if (warning) fprintf(stdwarn,message.c_str());
de6b6757 163
164 if(error||warning){
874a2bd8 165 dump_vector(block->get_description());
de6b6757 166 } else {
167 if(cfg_list_contents){
168 FILE * tmp_fp=fdopen(out_fd,"w");
169 dump_vector_fp(block->get_description(),tmp_fp);
170 if (!error&&!warning) spaced=false;
171 }
874a2bd8 172 }
7880ae2d 173
874a2bd8 174 if (error||warning||cfg_verbose){
175 fprintf(fp,"\n");
176 spaced=true;
177 }
178 if (error) errors++;
179 if (warning) warnings++;
180 } // while....
7880ae2d 181 if (cfg_verbose){
874a2bd8 182 close(in_fd);
183 fprintf(stderr,"Reading finished.\n");
184 fprintf(stderr,"Bytes read:%i, Blocks read:%i\n",read_pointer,blocks_read);
185 }
186} // read_tape()
187
de6b6757 188
874a2bd8 189/******************************************************************************/
de6b6757 190void process_tape(){
191 if (cfg_verbose) fprintf(stdwarn,"Processing Tape.\n");
192
193 bool in_object=false;
194 char filename[100];
195 char filename_numbered[100];
196 string objname;
197 int unknown_count=-1;
198 int fd=-1, fd_numbered=-1;
199 int obj_no=0;
200 int obj_start_block;
201
202 for (unsigned int i=0; i<tape.size();i++){
203 tape_block * block=tape[i];
204
205 if (block->get_type()==tape_block::TBT_EOT){
206 objname="EOT";
207 if (in_object){
208 if (cfg_ignore_object_integrity_errors){
209 fprintf(stdwarn,"Warning: Object integrity error!\n");
210 warnings++;
211 } else {
212 fprintf(stderr,"Error: Object integrity error!\
213 (Object no %i, Block %i unexpected)\n",obj_no,i);
214 errors++;
215 errcode=6;
216 return;
217 }
218 }
219 }
220
221 if (!in_object){ // object begin
222 obj_no++;
223 obj_start_block=i;
224
225 objname="UNKNOWN";
226 unknown_count++;
227
228 vector<string>names=block->get_exported_symbols();
229 for (unsigned int a=0; a<names.size();a++){
230 objname=names[0];
231 if (objname!=" "){
232 objname=objname.substr(0,objname.find_last_not_of(" ")+1);
233 unknown_count--;
234 break;
235
236 }
237 }
238
239 if (block->get_type()==tape_block::TBT_EOT){
240 objname="EOT";
241 }
242
243 // Open file for split objects
244 if (cfg_split_objects && (block->get_type()!=tape_block::TBT_EOT)){
245 if (objname=="UNKNOWN")snprintf(filename,99,"UNKNOWN%02i.obj",unknown_count);
246 else snprintf(filename,99,"%s.obj",objname.c_str());
247 if (fd>-1) close (fd);
248 fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC,0666);
249 printf("opening \"%s\"\n",filename);
250 if (fd<0){
251 fprintf(stderr,"Error: could not open file \"%s\" for writing!\n",
252 filename);
253 exit (1);
254 }
255 }
256
257 // Open file for split objects numbered
258 snprintf(filename_numbered,99,"%03i0-%s.obj",obj_no,objname.c_str());
259 if (cfg_split_objects_numbered){
260 if (fd_numbered>-1) close (fd_numbered);
261 fd_numbered=open(filename_numbered,O_WRONLY|O_CREAT|O_TRUNC,0666);
262 if (fd_numbered<0){
263 fprintf(stderr,"Error: could not open file \"%s\" for writing!\n",
264 filename_numbered);
265 exit (1);
266 }
267 }
268 in_object=true;
269 } // object begin
270
271 // Output block data
272 if (cfg_split_objects){
273 try{
274 if (block->get_type()!=tape_block::TBT_EOT) // Don't want EOT here
275 block->dump_to_fd(fd);
276 }
277 catch (tape_block::io_error_exception e){
278 fprintf(stderr,"Error: could write to file \"%s\"!\n",
279 filename);
280 exit (1);
281 }
282 } // if (cfg_split_objects)
283
284 // Output block data
285 if (cfg_split_objects_numbered){
286 try{
287 block->dump_to_fd(fd_numbered);
288 }
289 catch (tape_block::io_error_exception e){
290 fprintf(stderr,"Error: could write to file \"%s\"!\n",
291 filename_numbered);
292 exit (1);
293 }
294 } // if (cfg_split_objects_numbered)
295
296 // Output individual block file if desired
297 if (cfg_split_blocks){
298 char fname[100];
299 snprintf(fname,99,"%03i0-%s-%03i.block",obj_no,objname.c_str(),i-obj_start_block);
300 int fd_block=open(fname,O_WRONLY|O_TRUNC|O_CREAT,0666);
301 if (fd_block<0){
302 fprintf(stderr,"Error: could not open file \"%s\" for writing!\n",
303 fname);
304 exit (1);
305 }
306 try{
307 block->dump_to_fd(fd_block);
308 }
309 catch (tape_block::io_error_exception e){
310 fprintf(stderr,"Error: could write to file \"%s\"!\n",
311 fname);
312 exit (1);
313 }
314 close(fd_block);
315 }
316
317 if (block->is_endblock()||(block->get_type()==tape_block::TBT_EOT)) {
318 in_object=false;
319 if (fd!=-1) close(fd);
320 if (fd_numbered!=-1) close(fd_numbered);
321 }
322 } // for (...)
323
324 if (in_object){
325 if (cfg_ignore_object_integrity_errors){
326 fprintf(stdwarn,"Warning: Object integrity error!\n");
327 warnings++;
328 } else {
329 fprintf(stdwarn,"Error: Object integrity error!\n");
330 errors++;
331 errcode=6;
332 return;
333 }
334 }
335
874a2bd8 336
de6b6757 337} // process_tape()
874a2bd8 338
de6b6757 339void process_called_imports(){
340 vector<string>exported;
341 vector<string>called;
342 vector <string>unsatisfied;
343
874a2bd8 344 for (unsigned int i=0; i<tape.size();i++){
de6b6757 345 merge_vector_unique(exported,tape[i]->get_exported_symbols());
346 merge_vector_unique(called,tape[i]->get_called_symbols());
347 }
348
349 for (unsigned int icalled=0;icalled<called.size();icalled++){
350 bool found=false;
351 for (unsigned int iexported=0;iexported<exported.size();iexported++){
352 if (exported[iexported].compare(called[icalled])==0){
353 found=true;
354 break;
874a2bd8 355 }
356 }
de6b6757 357 if (!found) {
358 bool present=false;
359 for (unsigned int i=0;i<unsatisfied.size();i++){
360 if (unsatisfied[i].compare(called[icalled])==0){
361 present=true;
362 break;
363 }
364 }
365 if (!present) unsatisfied.insert(unsatisfied.end(),called[icalled]);
366 }
7880ae2d 367 }
de6b6757 368
369 FILE * outp=fdopen(out_fd,"w");
370
371 if (cfg_output_called){
372 dump_vector_fp(called,outp);
373 }
374
375 if (cfg_output_exported){
376 dump_vector_fp(exported,outp);
377 }
378
379 if (cfg_output_unsatisfied){
380 dump_vector_fp(unsatisfied,outp);
381 }
382
383}
ad324d29 384
874a2bd8 385/******************************************************************************/
386/*!
387 *\brief The main routine.
388 */
389int main(int argc, char ** args){
7880ae2d 390
874a2bd8 391 // Do all the configuration stuff
392 do_config(argc,args);
393
394 // Output a version message if desired
395 if (cfg_version){
396 fprintf(stderr, ID_STRING, VERSION, BUILD_DATE, BUILD_STAMP);
397 exit(0);
398 }
399
400 // Assign warning output according to configuration
401 if (cfg_quiet) stdwarn=fopen("/dev/null","w");
402 else stdwarn=stderr;
403
404 read_tape(); // Process input to completion.
405 exit_on_error();
406
de6b6757 407 process_tape();
408 exit_on_error();
409
410 process_called_imports();
411 exit_on_error();
874a2bd8 412
413
de6b6757 414 if (warnings>0){
415 fprintf(stdwarn,"Warnings:%i\n",warnings);
416 return 99;
874a2bd8 417 }
de6b6757 418 if (cfg_verbose) fprintf(stdwarn,"Success.\n");
ad324d29 419 return 0;
420} // main()
798b0c1d 421