1 /******************************************************************************
5 * $Date: 2008/10/01 13:30:14 $
9 * Revision 2.5 2008/10/01 13:30:14 hachti
12 * Revision 2.4 2008-08-25 21:02:24 hachti
13 * *** empty log message ***
15 * Revision 2.3 2007-05-30 02:51:16 hachti
16 * Changed everything towards LDC2 use.
17 * Worked on the buildlib.sh.
18 * Centralized buildlib.sh to a new lib/common directory.
20 * Revision 2.2 2007-03-26 03:20:31 hachti
21 * *** empty log message ***
23 * Revision 2.1 2007-03-26 01:15:21 hachti
24 * *** empty log message ***
26 * Revision 2.0 2007-03-26 01:00:40 hachti
27 * *** empty log message ***
30 ******************************************************************************/
32 #include <sys/types.h>
47 #include "tape_block.hh"
48 #include "data_block_0.hh"
53 #define BUILD_STAMP ""
60 #define ID_STRING "\n ldc2 - The X16 object tape analyser\n\
61 (C) 2007 Philipp Hachtmann\n\n\
62 Version %s, built %s\n %s\n\n"
64 /******************************************************************************/
66 static FILE * stdwarn
; //! Suppressable warning output file pointer.
67 static vector
<tape_block
*> tape
; //! The whole tape contents.
68 static vector
<vector
<tape_block
*> > objects
; //! Tape content in objects.
70 static int errors
= 0; //! Global error counter.
71 static int warnings
= 0; //! Global warning counter.
72 static int errcode
= 0; //! Error code for error exit routine.
75 /******************************************************************************/
77 *\brief Error exit routine.
79 * This routine tests the global error counter and terminates the program
84 fprintf(stderr
,"Failed. (%i)\n",errcode
);
90 /******************************************************************************/
92 *\brief Read in Tape data and do some checks and messages.
94 * This routine reads in the tape data.
95 * During reading in, checksums are checked and
96 * /da001/ information is generated. No object integrity test.
97 * Tape block object pointers are put into the global vector
102 tape_block
* block
=0; //! Pointer to current block.
103 bool read_ahead
=true; //! Continue scanning for blocks.
104 int read_pointer
=0; //! Read position in input.
105 int block_start
=0; //! Start of block position in input.
106 int block_end
=0; //! End of block position in input.
107 int blocks_read
=0; //! Number of blocks read in.
109 bool spaced
=false; //! Help flag for spaced messages.
111 string message
; //! A warning or help message.
116 bool err_checksum
=false; //! Checksum error flag.
117 bool err_integrity
=false; //! Integrity error flag.
119 bool warning
=false; //! Warning flag.
120 bool error
=false; //! Error flag.
122 // Try to generate block
124 block
=tape_block::gen_from_fd(in_fd
);
127 catch(tape_block::eof_legal_exception
&e
){
128 read_pointer
+=e
.get_consumed();
129 break; // Immediately leave read loop.
132 catch(tape_block::io_error_exception
){
134 fprintf(stderr
,"Error: Could not read from \"%s\"!\n",
137 fprintf(stderr
,"Error: Could not read from stdin!\n");
141 break; // Immediately leave read loop.
144 catch(tape_block::eof_illegal_exception
&e
){
148 if (cfg_ignore_block_errors
){
149 message
="Warning: Block integrity check failed!\n";
152 message
="Error: Block integrity check failed!\n";
158 catch(tape_block::checksum_error_exception
&e
){
161 if (cfg_ignore_checksum_errors
){
162 message
="Warning: Block checksum wrong!\n";
165 message
="Error: Block checksum wrong!\n";
172 // Now let's check for block type
173 if ((!error
)&&(!warning
)&&!block
->has_known_type()){
174 if (cfg_ignore_unknown_block_errors
){
175 message
="Warning: Unknown Block type!";
178 message
="Error: Unknown Block type!";
187 tape
.insert(tape
.end(),block
);
188 block_start
=read_pointer
+block
->get_discarded_bytes();
189 block_end
=block_start
+block
->get_raw_size()-1;
190 read_pointer
=block_end
+1;
193 if (error
) fp
=stderr
;
195 if (cfg_verbose
||error
||warning
){
196 if (!spaced
) fprintf(fp
,"\n");
198 fprintf(fp
,"Block No.%03i: Start:0x%04x End:0x%04x Size:0x%02x\n",
202 block
->get_raw_size());
205 if (error
) fprintf(stderr
,message
.c_str());
206 if (warning
) fprintf(stdwarn
,message
.c_str());
209 dump_vector(block
->get_description());
211 if(cfg_list_contents
){
212 FILE * tmp_fp
=fdopen(out_fd
,"w");
213 dump_vector_fp(block
->get_description(),tmp_fp
);
214 if (!error
&&!warning
) spaced
=false;
218 if (error
||warning
||cfg_verbose
){
223 if (warning
) warnings
++;
227 fprintf(stderr
,"Reading finished.\n");
228 fprintf(stderr
,"Bytes read:%i, Blocks read:%i\n",read_pointer
,blocks_read
);
233 /******************************************************************************/
235 *\brief Do integrity test and object or block dumps.
238 if (cfg_verbose
) fprintf(stdwarn
,"\nProcessing Data.\n");
240 bool in_object
=false;
242 char filename_numbered
[100];
244 int unknown_count
=-1;
245 int fd
=-1, fd_numbered
=-1;
249 for (unsigned int i
=0; i
<tape
.size();i
++){
250 tape_block
* block
=tape
[i
];
252 if (block
->get_type()==tape_block::TBT_EOT
){
255 if (cfg_ignore_object_integrity_errors
){
256 fprintf(stdwarn
,"Warning: Object integrity error!\
257 (Object no %i, Block %i unexpected)\n",obj_no
,i
);
260 fprintf(stderr
,"Error: Object integrity error!\
261 (Object no %i, Block %i unexpected)\n",obj_no
,i
);
268 if (!in_object
){ // object begin
276 vector
<string
>names
=block
->get_exported_symbols();
277 for (unsigned int a
=0; a
<names
.size();a
++){
280 objname
=objname
.substr(0,objname
.find_last_not_of(" ")+1);
286 if (block
->get_type()==tape_block::TBT_EOT
){
290 // Open file for split objects
291 if (cfg_split_objects
&& (block
->get_type()!=tape_block::TBT_EOT
)){
292 if (objname
=="UNKNOWN")snprintf(filename
,99,"UNKNOWN%02i",
294 else snprintf(filename
,99,"%s",objname
.c_str());
295 if (fd
>-1) close (fd
);
296 if (cfg_verbose
) fprintf(stdwarn
,"Writing file: %s\n",filename
);
297 fd
=open(filename
,O_WRONLY
|O_CREAT
|O_TRUNC
,0666);
299 fprintf(stderr
,"Error: could not open file \"%s\" for writing!\n",
307 // Open file for split objects numbered
308 snprintf(filename_numbered
,99,"%03i0-%s",obj_no
,objname
.c_str());
309 if (cfg_split_objects_numbered
){
311 if (cfg_verbose
) fprintf(stdwarn
,"Writing file: %s\n",filename_numbered
);
312 fd_numbered
=open(filename_numbered
,O_WRONLY
|O_CREAT
|O_TRUNC
,0666);
314 fprintf(stderr
,"Error: could not open file \"%s\" for writing!\n",
325 if (cfg_split_objects
){
327 if (block
->get_type()!=tape_block::TBT_EOT
) // Don't want EOT here
328 block
->dump_to_fd(fd
);
330 catch (tape_block::io_error_exception e
){
331 fprintf(stderr
,"Error: could write to file \"%s\"!\n",
337 } // if (cfg_split_objects)
340 if (cfg_split_objects_numbered
){
342 block
->dump_to_fd(fd_numbered
);
344 catch (tape_block::io_error_exception e
){
345 fprintf(stderr
,"Error: could write to file \"%s\"!\n",
351 } // if (cfg_split_objects_numbered)
353 // Output individual block file if desired
354 if (cfg_split_blocks
){
356 snprintf(fname
,99,"%03i0-%s-%03i.block",obj_no
,objname
.c_str(),
358 if (cfg_verbose
) fprintf(stdwarn
,"Writing file: %s\n",fname
);
359 int fd_block
=open(fname
,O_WRONLY
|O_TRUNC
|O_CREAT
,0666);
361 fprintf(stderr
,"Error: could not open file \"%s\" for writing!\n",
370 block
->dump_to_fd(fd_block
);
372 catch (tape_block::io_error_exception e
){
373 fprintf(stderr
,"Error: could write to file \"%s\"!\n",
384 if (block
->is_endblock()||(block
->get_type()==tape_block::TBT_EOT
)) {
392 if (cfg_ignore_object_integrity_errors
){
393 fprintf(stdwarn
,"Warning: Object integrity error! Last object incomplete!\n");
396 fprintf(stdwarn
,"Error: Object integrity error! Last Object incomplete!\n");
399 if (fd
!=-1) close(fd
);
400 if (fd_numbered
!=-1) close(fd_numbered
);
406 /******************************************************************************/
408 *\brief Everything that has to do with symbol listing.
410 void process_symbols(){
411 vector
<string
>exported
;
412 vector
<string
>called
;
413 vector
<string
>unsatisfied
;
415 if (cfg_verbose
) fprintf(stdwarn
,"\nProcessing Symbols.\n");
417 for (unsigned int i
=0; i
<tape
.size();i
++){
418 merge_vector_unique(exported
,tape
[i
]->get_exported_symbols());
419 merge_vector_unique(called
,tape
[i
]->get_called_symbols());
422 for (unsigned int icalled
=0;icalled
<called
.size();icalled
++){
424 for (unsigned int iexported
=0;iexported
<exported
.size();iexported
++){
425 if (exported
[iexported
].compare(called
[icalled
])==0){
432 for (unsigned int i
=0;i
<unsatisfied
.size();i
++){
433 if (unsatisfied
[i
].compare(called
[icalled
])==0){
438 if (!present
) unsatisfied
.insert(unsatisfied
.end(),called
[icalled
]);
442 FILE * outp
=fdopen(out_fd
,"w");
444 if (cfg_output_called
){
445 dump_vector_fp(called
,outp
);
448 if (cfg_output_exported
){
449 dump_vector_fp(exported
,outp
);
452 if (cfg_output_unsatisfied
){
453 dump_vector_fp(unsatisfied
,outp
);
456 } // process_symbols()
458 /******************************************************************************/
460 *\brief The main routine.
463 int main(int argc
, char ** args
){
465 // Do all the configuration stuff
466 do_config(argc
,args
);
468 // Output a version message if desired
470 fprintf(stderr
, ID_STRING
, VERSION
, BUILD_DATE
, BUILD_STAMP
);
474 // Assign warning output according to configuration
475 if (cfg_quiet
) stdwarn
=fopen("/dev/null","w");
478 read_tape(); // Process input to completion.
488 fprintf(stdwarn
,"Warnings:%i\n",warnings
);
491 if (cfg_verbose
) fprintf(stdwarn
,"\nSuccess.\n");
495 * All over this program, no memory is freed. This is not necessary because
496 * everything is allocated once and that's it.
497 * The classes support proper freeing of their internal buffers.
502 /******************************************************************************/