1 /******************************************************************************
5 * $Date: 2010/01/04 02:10:59 $
9 * Revision 2.6 2010/01/04 02:10:59 hachti
10 * *** empty log message ***
12 * Revision 2.5 2008-10-01 13:30:14 hachti
15 * Revision 2.4 2008-08-25 21:02:24 hachti
16 * *** empty log message ***
18 * Revision 2.3 2007-05-30 02:51:16 hachti
19 * Changed everything towards LDC2 use.
20 * Worked on the buildlib.sh.
21 * Centralized buildlib.sh to a new lib/common directory.
23 * Revision 2.2 2007-03-26 03:20:31 hachti
24 * *** empty log message ***
26 * Revision 2.1 2007-03-26 01:15:21 hachti
27 * *** empty log message ***
29 * Revision 2.0 2007-03-26 01:00:40 hachti
30 * *** empty log message ***
33 ******************************************************************************/
35 #include <sys/types.h>
50 #include "tape_block.hh"
51 #include "data_block_0.hh"
56 #define BUILD_STAMP ""
63 #define ID_STRING "\n ldc2 - The X16 object tape analyser\n\
64 (C) 2007 Philipp Hachtmann\n\n\
65 Version %s, built %s\n %s\n\n"
67 /******************************************************************************/
69 static FILE * stdwarn
; //! Suppressable warning output file pointer.
70 static vector
<tape_block
*> tape
; //! The whole tape contents.
71 static vector
<vector
<tape_block
*> > objects
; //! Tape content in objects.
73 static int errors
= 0; //! Global error counter.
74 static int warnings
= 0; //! Global warning counter.
75 static int errcode
= 0; //! Error code for error exit routine.
78 /******************************************************************************/
80 *\brief Error exit routine.
82 * This routine tests the global error counter and terminates the program
87 fprintf(stderr
,"Failed. (%i)\n",errcode
);
93 /******************************************************************************/
95 *\brief Read in Tape data and do some checks and messages.
97 * This routine reads in the tape data.
98 * During reading in, checksums are checked and
99 * /da001/ information is generated. No object integrity test.
100 * Tape block object pointers are put into the global vector
105 tape_block
* block
=0; //! Pointer to current block.
106 bool read_ahead
=true; //! Continue scanning for blocks.
107 int read_pointer
=0; //! Read position in input.
108 int block_start
=0; //! Start of block position in input.
109 int block_end
=0; //! End of block position in input.
110 int blocks_read
=0; //! Number of blocks read in.
112 bool spaced
=false; //! Help flag for spaced messages.
114 string message
; //! A warning or help message.
119 // bool err_checksum=false; //! Checksum error flag.
120 // bool err_integrity=false; //! Integrity error flag.
122 bool warning
=false; //! Warning flag.
123 bool error
=false; //! Error flag.
125 // Try to generate block
127 block
=tape_block::gen_from_fd(in_fd
);
130 catch(tape_block::eof_legal_exception
&e
){
131 read_pointer
+=e
.get_consumed();
132 break; // Immediately leave read loop.
135 catch(tape_block::io_error_exception
){
137 fprintf(stderr
,"Error: Could not read from \"%s\"!\n",
140 fprintf(stderr
,"Error: Could not read from stdin!\n");
144 break; // Immediately leave read loop.
147 catch(tape_block::eof_illegal_exception
&e
){
149 // err_integrity=true;
151 if (cfg_ignore_block_errors
){
152 message
="Warning: Block integrity check failed!\n";
155 message
="Error: Block integrity check failed!\n";
161 catch(tape_block::checksum_error_exception
&e
){
163 // err_checksum=true;
164 if (cfg_ignore_checksum_errors
){
165 message
="Warning: Block checksum wrong!\n";
168 message
="Error: Block checksum wrong!\n";
175 // Now let's check for block type
176 if ((!error
)&&(!warning
)&&!block
->has_known_type()){
177 if (cfg_ignore_unknown_block_errors
){
178 message
="Warning: Unknown Block type!";
181 message
="Error: Unknown Block type!";
190 tape
.insert(tape
.end(),block
);
191 block_start
=read_pointer
+block
->get_discarded_bytes();
192 block_end
=block_start
+block
->get_raw_size()-1;
193 read_pointer
=block_end
+1;
196 if (error
) fp
=stderr
;
198 if (cfg_verbose
||error
||warning
){
199 if (!spaced
) fprintf(fp
,"\n");
201 fprintf(fp
,"Block No.%03i: Start:0x%04x End:0x%04x Size:0x%02x\n",
205 block
->get_raw_size());
208 if (error
) fprintf(stderr
,message
.c_str());
209 if (warning
) fprintf(stdwarn
,message
.c_str());
212 dump_vector(block
->get_description());
214 if(cfg_list_contents
){
215 FILE * tmp_fp
=fdopen(out_fd
,"w");
216 dump_vector_fp(block
->get_description(),tmp_fp
);
217 if (!error
&&!warning
) spaced
=false;
221 if (error
||warning
||cfg_verbose
){
226 if (warning
) warnings
++;
230 fprintf(stderr
,"Reading finished.\n");
231 fprintf(stderr
,"Bytes read:%i, Blocks read:%i\n",read_pointer
,blocks_read
);
236 /******************************************************************************/
238 *\brief Do integrity test and object or block dumps.
241 if (cfg_verbose
) fprintf(stdwarn
,"\nProcessing Data.\n");
243 bool in_object
=false;
245 char filename_numbered
[100];
247 int unknown_count
=-1;
248 int fd
=-1, fd_numbered
=-1;
252 for (unsigned int i
=0; i
<tape
.size();i
++){
253 tape_block
* block
=tape
[i
];
255 if (block
->get_type()==tape_block::TBT_EOT
){
258 if (cfg_ignore_object_integrity_errors
){
259 fprintf(stdwarn
,"Warning: Object integrity error!\
260 (Object no %i, Block %i unexpected)\n",obj_no
,i
);
263 fprintf(stderr
,"Error: Object integrity error!\
264 (Object no %i, Block %i unexpected)\n",obj_no
,i
);
271 if (!in_object
){ // object begin
279 vector
<string
>names
=block
->get_exported_symbols();
280 for (unsigned int a
=0; a
<names
.size();a
++){
283 objname
=objname
.substr(0,objname
.find_last_not_of(" ")+1);
289 if (block
->get_type()==tape_block::TBT_EOT
){
293 // Open file for split objects
294 if (cfg_split_objects
&& (block
->get_type()!=tape_block::TBT_EOT
)){
295 if (objname
=="UNKNOWN")snprintf(filename
,99,"UNKNOWN%02i",
297 else snprintf(filename
,99,"%s",objname
.c_str());
298 if (fd
>-1) close (fd
);
299 if (cfg_verbose
) fprintf(stdwarn
,"Writing file: %s\n",filename
);
300 fd
=open(filename
,O_WRONLY
|O_CREAT
|O_TRUNC
,0666);
302 fprintf(stderr
,"Error: could not open file \"%s\" for writing!\n",
310 // Open file for split objects numbered
311 snprintf(filename_numbered
,99,"%03i0-%s",obj_no
,objname
.c_str());
312 if (cfg_split_objects_numbered
){
314 if (cfg_verbose
) fprintf(stdwarn
,"Writing file: %s\n",filename_numbered
);
315 fd_numbered
=open(filename_numbered
,O_WRONLY
|O_CREAT
|O_TRUNC
,0666);
317 fprintf(stderr
,"Error: could not open file \"%s\" for writing!\n",
328 if (cfg_split_objects
){
330 if (block
->get_type()!=tape_block::TBT_EOT
) // Don't want EOT here
331 block
->dump_to_fd(fd
);
333 catch (tape_block::io_error_exception e
){
334 fprintf(stderr
,"Error: could write to file \"%s\"!\n",
340 } // if (cfg_split_objects)
343 if (cfg_split_objects_numbered
){
345 block
->dump_to_fd(fd_numbered
);
347 catch (tape_block::io_error_exception e
){
348 fprintf(stderr
,"Error: could write to file \"%s\"!\n",
354 } // if (cfg_split_objects_numbered)
356 // Output individual block file if desired
357 if (cfg_split_blocks
){
359 snprintf(fname
,99,"%03i0-%s-%03i.block",obj_no
,objname
.c_str(),
361 if (cfg_verbose
) fprintf(stdwarn
,"Writing file: %s\n",fname
);
362 int fd_block
=open(fname
,O_WRONLY
|O_TRUNC
|O_CREAT
,0666);
364 fprintf(stderr
,"Error: could not open file \"%s\" for writing!\n",
373 block
->dump_to_fd(fd_block
);
375 catch (tape_block::io_error_exception e
){
376 fprintf(stderr
,"Error: could write to file \"%s\"!\n",
387 if (block
->is_endblock()||(block
->get_type()==tape_block::TBT_EOT
)) {
395 if (cfg_ignore_object_integrity_errors
){
396 fprintf(stdwarn
,"Warning: Object integrity error! Last object incomplete!\n");
399 fprintf(stdwarn
,"Error: Object integrity error! Last Object incomplete!\n");
402 if (fd
!=-1) close(fd
);
403 if (fd_numbered
!=-1) close(fd_numbered
);
409 /******************************************************************************/
411 *\brief Everything that has to do with symbol listing.
413 void process_symbols(){
414 vector
<string
>exported
;
415 vector
<string
>called
;
416 vector
<string
>unsatisfied
;
418 if (cfg_verbose
) fprintf(stdwarn
,"\nProcessing Symbols.\n");
420 for (unsigned int i
=0; i
<tape
.size();i
++){
421 merge_vector_unique(exported
,tape
[i
]->get_exported_symbols());
422 merge_vector_unique(called
,tape
[i
]->get_called_symbols());
425 for (unsigned int icalled
=0;icalled
<called
.size();icalled
++){
427 for (unsigned int iexported
=0;iexported
<exported
.size();iexported
++){
428 if (exported
[iexported
].compare(called
[icalled
])==0){
435 for (unsigned int i
=0;i
<unsatisfied
.size();i
++){
436 if (unsatisfied
[i
].compare(called
[icalled
])==0){
441 if (!present
) unsatisfied
.insert(unsatisfied
.end(),called
[icalled
]);
445 FILE * outp
=fdopen(out_fd
,"w");
447 if (cfg_output_called
){
448 dump_vector_fp(called
,outp
);
451 if (cfg_output_exported
){
452 dump_vector_fp(exported
,outp
);
455 if (cfg_output_unsatisfied
){
456 dump_vector_fp(unsatisfied
,outp
);
459 } // process_symbols()
461 /******************************************************************************/
463 *\brief The main routine.
466 int main(int argc
, char ** args
){
468 // Do all the configuration stuff
469 do_config(argc
,args
);
471 // Output a version message if desired
473 fprintf(stderr
, ID_STRING
, VERSION
, BUILD_DATE
, BUILD_STAMP
);
477 // Assign warning output according to configuration
478 if (cfg_quiet
) stdwarn
=fopen("/dev/null","w");
481 read_tape(); // Process input to completion.
491 fprintf(stdwarn
,"Warnings:%i\n",warnings
);
494 if (cfg_verbose
) fprintf(stdwarn
,"\nSuccess.\n");
498 * All over this program, no memory is freed. This is not necessary because
499 * everything is allocated once and that's it.
500 * The classes support proper freeing of their internal buffers.
505 /******************************************************************************/