1 /******************************************************************************
5 * $Date: 2008/08/25 21:02:24 $
9 * Revision 2.4 2008/08/25 21:02:24 hachti
10 * *** empty log message ***
12 * Revision 2.3 2007-05-30 02:51:16 hachti
13 * Changed everything towards LDC2 use.
14 * Worked on the buildlib.sh.
15 * Centralized buildlib.sh to a new lib/common directory.
17 * Revision 2.2 2007-03-26 03:20:31 hachti
18 * *** empty log message ***
20 * Revision 2.1 2007-03-26 01:15:21 hachti
21 * *** empty log message ***
23 * Revision 2.0 2007-03-26 01:00:40 hachti
24 * *** empty log message ***
27 ******************************************************************************/
29 #include <sys/types.h>
41 #include "tape_block.hh"
42 #include "data_block_0.hh"
47 #define BUILD_STAMP ""
54 #define ID_STRING "\n ldc2 - The X16 object tape analyser\n\
55 (C) 2007 Philipp Hachtmann\n\n\
56 Version %s, built %s\n %s\n\n"
58 /******************************************************************************/
60 static FILE * stdwarn
; //! Suppressable warning output file pointer.
61 static vector
<tape_block
*> tape
; //! The whole tape contents.
62 static vector
<vector
<tape_block
*> > objects
; //! Tape content in objects.
64 static int errors
= 0; //! Global error counter.
65 static int warnings
= 0; //! Global warning counter.
66 static int errcode
= 0; //! Error code for error exit routine.
69 /******************************************************************************/
71 *\brief Error exit routine.
73 * This routine tests the global error counter and terminates the program
78 fprintf(stderr
,"Failed. (%i)\n",errcode
);
84 /******************************************************************************/
86 *\brief Read in Tape data and do some checks and messages.
88 * This routine reads in the tape data.
89 * During reading in, checksums are checked and
90 * /da001/ information is generated. No object integrity test.
91 * Tape block object pointers are put into the global vector
96 tape_block
* block
=0; //! Pointer to current block.
97 bool read_ahead
=true; //! Continue scanning for blocks.
98 int read_pointer
=0; //! Read position in input.
99 int block_start
=0; //! Start of block position in input.
100 int block_end
=0; //! End of block position in input.
101 int blocks_read
=0; //! Number of blocks read in.
103 bool spaced
=false; //! Help flag for spaced messages.
105 string message
; //! A warning or help message.
110 bool err_checksum
=false; //! Checksum error flag.
111 bool err_integrity
=false; //! Integrity error flag.
113 bool warning
=false; //! Warning flag.
114 bool error
=false; //! Error flag.
116 // Try to generate block
118 block
=tape_block::gen_from_fd(in_fd
);
121 catch(tape_block::eof_legal_exception
&e
){
122 read_pointer
+=e
.get_consumed();
123 break; // Immediately leave read loop.
126 catch(tape_block::io_error_exception
){
128 fprintf(stderr
,"Error: Could not read from \"%s\"!\n",
131 fprintf(stderr
,"Error: Could not read from stdin!\n");
135 break; // Immediately leave read loop.
138 catch(tape_block::eof_illegal_exception
&e
){
142 if (cfg_ignore_block_errors
){
143 message
="Warning: Block integrity check failed!\n";
146 message
="Error: Block integrity check failed!\n";
152 catch(tape_block::checksum_error_exception
&e
){
155 if (cfg_ignore_checksum_errors
){
156 message
="Warning: Block checksum wrong!\n";
159 message
="Error: Block checksum wrong!\n";
166 // Now let's check for block type
167 if ((!error
)&&(!warning
)&&!block
->has_known_type()){
168 if (cfg_ignore_unknown_block_errors
){
169 message
="Warning: Unknown Block type!";
172 message
="Error: Unknown Block type!";
181 tape
.insert(tape
.end(),block
);
182 block_start
=read_pointer
+block
->get_discarded_bytes();
183 block_end
=block_start
+block
->get_raw_size()-1;
184 read_pointer
=block_end
+1;
187 if (error
) fp
=stderr
;
189 if (cfg_verbose
||error
||warning
){
190 if (!spaced
) fprintf(fp
,"\n");
192 fprintf(fp
,"Block No.%03i: Start:0x%04x End:0x%04x Size:0x%02x\n",
196 block
->get_raw_size());
199 if (error
) fprintf(stderr
,message
.c_str());
200 if (warning
) fprintf(stdwarn
,message
.c_str());
203 dump_vector(block
->get_description());
205 if(cfg_list_contents
){
206 FILE * tmp_fp
=fdopen(out_fd
,"w");
207 dump_vector_fp(block
->get_description(),tmp_fp
);
208 if (!error
&&!warning
) spaced
=false;
212 if (error
||warning
||cfg_verbose
){
217 if (warning
) warnings
++;
221 fprintf(stderr
,"Reading finished.\n");
222 fprintf(stderr
,"Bytes read:%i, Blocks read:%i\n",read_pointer
,blocks_read
);
227 /******************************************************************************/
229 *\brief Do integrity test and object or block dumps.
232 if (cfg_verbose
) fprintf(stdwarn
,"\nProcessing Data.\n");
234 bool in_object
=false;
236 char filename_numbered
[100];
238 int unknown_count
=-1;
239 int fd
=-1, fd_numbered
=-1;
243 for (unsigned int i
=0; i
<tape
.size();i
++){
244 tape_block
* block
=tape
[i
];
246 if (block
->get_type()==tape_block::TBT_EOT
){
249 if (cfg_ignore_object_integrity_errors
){
250 fprintf(stdwarn
,"Warning: Object integrity error!\
251 (Object no %i, Block %i unexpected)\n",obj_no
,i
);
254 fprintf(stderr
,"Error: Object integrity error!\
255 (Object no %i, Block %i unexpected)\n",obj_no
,i
);
262 if (!in_object
){ // object begin
270 vector
<string
>names
=block
->get_exported_symbols();
271 for (unsigned int a
=0; a
<names
.size();a
++){
274 objname
=objname
.substr(0,objname
.find_last_not_of(" ")+1);
280 if (block
->get_type()==tape_block::TBT_EOT
){
284 // Open file for split objects
285 if (cfg_split_objects
&& (block
->get_type()!=tape_block::TBT_EOT
)){
286 if (objname
=="UNKNOWN")snprintf(filename
,99,"UNKNOWN%02i",
288 else snprintf(filename
,99,"%s",objname
.c_str());
289 if (fd
>-1) close (fd
);
290 if (cfg_verbose
) fprintf(stdwarn
,"Writing file: %s\n",filename
);
291 fd
=open(filename
,O_WRONLY
|O_CREAT
|O_TRUNC
,0666);
293 fprintf(stderr
,"Error: could not open file \"%s\" for writing!\n",
301 // Open file for split objects numbered
302 snprintf(filename_numbered
,99,"%03i0-%s",obj_no
,objname
.c_str());
303 if (cfg_split_objects_numbered
){
305 if (cfg_verbose
) fprintf(stdwarn
,"Writing file: %s\n",filename_numbered
);
306 fd_numbered
=open(filename_numbered
,O_WRONLY
|O_CREAT
|O_TRUNC
,0666);
308 fprintf(stderr
,"Error: could not open file \"%s\" for writing!\n",
319 if (cfg_split_objects
){
321 if (block
->get_type()!=tape_block::TBT_EOT
) // Don't want EOT here
322 block
->dump_to_fd(fd
);
324 catch (tape_block::io_error_exception e
){
325 fprintf(stderr
,"Error: could write to file \"%s\"!\n",
331 } // if (cfg_split_objects)
334 if (cfg_split_objects_numbered
){
336 block
->dump_to_fd(fd_numbered
);
338 catch (tape_block::io_error_exception e
){
339 fprintf(stderr
,"Error: could write to file \"%s\"!\n",
345 } // if (cfg_split_objects_numbered)
347 // Output individual block file if desired
348 if (cfg_split_blocks
){
350 snprintf(fname
,99,"%03i0-%s-%03i.block",obj_no
,objname
.c_str(),
352 if (cfg_verbose
) fprintf(stdwarn
,"Writing file: %s\n",fname
);
353 int fd_block
=open(fname
,O_WRONLY
|O_TRUNC
|O_CREAT
,0666);
355 fprintf(stderr
,"Error: could not open file \"%s\" for writing!\n",
364 block
->dump_to_fd(fd_block
);
366 catch (tape_block::io_error_exception e
){
367 fprintf(stderr
,"Error: could write to file \"%s\"!\n",
378 if (block
->is_endblock()||(block
->get_type()==tape_block::TBT_EOT
)) {
386 if (cfg_ignore_object_integrity_errors
){
387 fprintf(stdwarn
,"Warning: Object integrity error! Last object incomplete!\n");
390 fprintf(stdwarn
,"Error: Object integrity error! Last Object incomplete!\n");
393 if (fd
!=-1) close(fd
);
394 if (fd_numbered
!=-1) close(fd_numbered
);
400 /******************************************************************************/
402 *\brief Everything that has to do with symbol listing.
404 void process_symbols(){
405 vector
<string
>exported
;
406 vector
<string
>called
;
407 vector
<string
>unsatisfied
;
409 if (cfg_verbose
) fprintf(stdwarn
,"\nProcessing Symbols.\n");
411 for (unsigned int i
=0; i
<tape
.size();i
++){
412 merge_vector_unique(exported
,tape
[i
]->get_exported_symbols());
413 merge_vector_unique(called
,tape
[i
]->get_called_symbols());
416 for (unsigned int icalled
=0;icalled
<called
.size();icalled
++){
418 for (unsigned int iexported
=0;iexported
<exported
.size();iexported
++){
419 if (exported
[iexported
].compare(called
[icalled
])==0){
426 for (unsigned int i
=0;i
<unsatisfied
.size();i
++){
427 if (unsatisfied
[i
].compare(called
[icalled
])==0){
432 if (!present
) unsatisfied
.insert(unsatisfied
.end(),called
[icalled
]);
436 FILE * outp
=fdopen(out_fd
,"w");
438 if (cfg_output_called
){
439 dump_vector_fp(called
,outp
);
442 if (cfg_output_exported
){
443 dump_vector_fp(exported
,outp
);
446 if (cfg_output_unsatisfied
){
447 dump_vector_fp(unsatisfied
,outp
);
450 } // process_symbols()
452 /******************************************************************************/
454 *\brief The main routine.
457 int main(int argc
, char ** args
){
459 // Do all the configuration stuff
460 do_config(argc
,args
);
462 // Output a version message if desired
464 fprintf(stderr
, ID_STRING
, VERSION
, BUILD_DATE
, BUILD_STAMP
);
468 // Assign warning output according to configuration
469 if (cfg_quiet
) stdwarn
=fopen("/dev/null","w");
472 read_tape(); // Process input to completion.
482 fprintf(stdwarn
,"Warnings:%i\n",warnings
);
485 if (cfg_verbose
) fprintf(stdwarn
,"\nSuccess.\n");
489 * All over this program, no memory is freed. This is not necessary because
490 * everything is allocated once and that's it.
491 * The classes support proper freeing of their internal buffers.
496 /******************************************************************************/