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