1 /******************************************************************************
5 * $Date: 2007/03/26 01:15:21 $
9 * Revision 2.1 2007/03/26 01:15:21 hachti
10 * *** empty log message ***
12 * Revision 2.0 2007-03-26 01:00:40 hachti
13 * *** empty log message ***
16 ******************************************************************************/
18 #include <sys/types.h>
28 #include "tape_block.hh"
29 #include "data_block_0.hh"
34 #define BUILD_STAMP ""
41 #define ID_STRING "\n ldc2 - The X16 object tape analyser\n\
42 (C) 2007 Philipp Hachtmann\n\n\
43 Version %s, built %s\n %s\n\n"
45 /******************************************************************************/
47 static FILE * stdwarn
; //! Suppressable warning output file pointer.
48 static vector
<tape_block
*> tape
; //! Represents the whole tape contents.
49 static vector
<vector
<tape_block
*> > objects
; //! Tape content in objects.
52 static int warnings
=0;
53 static int errcode
=0; //! Variable for error codes.
55 /******************************************************************************/
57 *\brief Error exit routine.
59 * This routine tests the global error counter and terminates the program
64 fprintf(stderr
,"Failed. (%i)\n",errcode
);
69 /******************************************************************************/
71 *\brief Read in Tape data and do some checks and messages.
73 * This routine reads in the tape data.
74 * During reading in, checksums are checked and
75 * /da001/ information is generated. No object integrity test.
76 * Tape block object pointers are put into the global vector
81 tape_block
* block
=0; //! Pointer to current block.
82 bool read_ahead
=true; //! Continue scanning for blocks.
83 int read_pointer
=0; //! Read position in input.
84 int block_start
=0; //! Start of block position in input.
85 int block_end
=0; //! End of block position in input.
86 int blocks_read
=0; //! Number of blocks read in.
88 bool spaced
=false; //! Help flag for spaced messages.
90 string message
; //! A warning or help message.
95 bool err_checksum
=false;
96 bool err_integrity
=false;
102 block
=tape_block::gen_from_fd(in_fd
);
105 catch(tape_block::eof_legal_exception
&e
){
106 read_pointer
+=e
.get_consumed();
107 break; // Immediately leave read loop.
110 catch(tape_block::io_error_exception
){
112 fprintf(stderr
,"Error: Could not read from \"%s\"!\n",cfg_infile
.c_str());
114 fprintf(stderr
,"Error: Could not read from stdin!\n");
118 break; // Immediately leave read loop.
121 catch(tape_block::eof_illegal_exception
&e
){
125 if (cfg_ignore_block_errors
){
126 message
="Warning: Block integrity check failed!\n";
129 message
="Error: Block integrity check failed!\n";
135 catch(tape_block::checksum_error_exception
&e
){
138 if (cfg_ignore_checksum_errors
){
139 message
="Warning: Block checksum wrong!\n";
142 message
="Error: Block checksum wrong!\n";
149 // Now let's check for block type
150 if ((!error
)&&(!warning
)&&!block
->has_known_type()){
151 if (cfg_ignore_unknown_block_errors
){
152 message
="Warning: Unknown Block type!";
155 message
="Error: Unknown Block type!";
164 tape
.insert(tape
.end(),block
);
165 block_start
=read_pointer
+block
->get_discarded_bytes();
166 block_end
=block_start
+block
->get_raw_size()-1;
167 read_pointer
=block_end
+1;
170 if (error
) fp
=stderr
;
172 if (cfg_verbose
||error
||warning
){
173 if (!spaced
) fprintf(fp
,"\n");
175 fprintf(fp
,"Block No.%03i: Start:0x%04x End:0x%04x Size:0x%02x\n",
179 block
->get_raw_size());
182 if (error
) fprintf(stderr
,message
.c_str());
183 if (warning
) fprintf(stdwarn
,message
.c_str());
186 dump_vector(block
->get_description());
188 if(cfg_list_contents
){
189 FILE * tmp_fp
=fdopen(out_fd
,"w");
190 dump_vector_fp(block
->get_description(),tmp_fp
);
191 if (!error
&&!warning
) spaced
=false;
195 if (error
||warning
||cfg_verbose
){
200 if (warning
) warnings
++;
204 fprintf(stderr
,"Reading finished.\n");
205 fprintf(stderr
,"Bytes read:%i, Blocks read:%i\n",read_pointer
,blocks_read
);
210 /******************************************************************************/
212 if (cfg_verbose
) fprintf(stdwarn
,"Processing Tape.\n");
214 bool in_object
=false;
216 char filename_numbered
[100];
218 int unknown_count
=-1;
219 int fd
=-1, fd_numbered
=-1;
223 for (unsigned int i
=0; i
<tape
.size();i
++){
224 tape_block
* block
=tape
[i
];
226 if (block
->get_type()==tape_block::TBT_EOT
){
229 if (cfg_ignore_object_integrity_errors
){
230 fprintf(stdwarn
,"Warning: Object integrity error!\n");
233 fprintf(stderr
,"Error: Object integrity error!\
234 (Object no %i, Block %i unexpected)\n",obj_no
,i
);
242 if (!in_object
){ // object begin
249 vector
<string
>names
=block
->get_exported_symbols();
250 for (unsigned int a
=0; a
<names
.size();a
++){
253 objname
=objname
.substr(0,objname
.find_last_not_of(" ")+1);
260 if (block
->get_type()==tape_block::TBT_EOT
){
264 // Open file for split objects
265 if (cfg_split_objects
&& (block
->get_type()!=tape_block::TBT_EOT
)){
266 if (objname
=="UNKNOWN")snprintf(filename
,99,"UNKNOWN%02i.obj",unknown_count
);
267 else snprintf(filename
,99,"%s.obj",objname
.c_str());
268 if (fd
>-1) close (fd
);
269 fd
=open(filename
,O_WRONLY
|O_CREAT
|O_TRUNC
,0666);
270 printf("opening \"%s\"\n",filename
);
272 fprintf(stderr
,"Error: could not open file \"%s\" for writing!\n",
280 // Open file for split objects numbered
281 snprintf(filename_numbered
,99,"%03i0-%s.obj",obj_no
,objname
.c_str());
282 if (cfg_split_objects_numbered
){
283 if (fd_numbered
>-1) close (fd_numbered
);
284 fd_numbered
=open(filename_numbered
,O_WRONLY
|O_CREAT
|O_TRUNC
,0666);
286 fprintf(stderr
,"Error: could not open file \"%s\" for writing!\n",
297 if (cfg_split_objects
){
299 if (block
->get_type()!=tape_block::TBT_EOT
) // Don't want EOT here
300 block
->dump_to_fd(fd
);
302 catch (tape_block::io_error_exception e
){
303 fprintf(stderr
,"Error: could write to file \"%s\"!\n",
309 } // if (cfg_split_objects)
312 if (cfg_split_objects_numbered
){
314 block
->dump_to_fd(fd_numbered
);
316 catch (tape_block::io_error_exception e
){
317 fprintf(stderr
,"Error: could write to file \"%s\"!\n",
323 } // if (cfg_split_objects_numbered)
325 // Output individual block file if desired
326 if (cfg_split_blocks
){
328 snprintf(fname
,99,"%03i0-%s-%03i.block",obj_no
,objname
.c_str(),i
-obj_start_block
);
329 int fd_block
=open(fname
,O_WRONLY
|O_TRUNC
|O_CREAT
,0666);
331 fprintf(stderr
,"Error: could not open file \"%s\" for writing!\n",
338 block
->dump_to_fd(fd_block
);
340 catch (tape_block::io_error_exception e
){
341 fprintf(stderr
,"Error: could write to file \"%s\"!\n",
350 if (block
->is_endblock()||(block
->get_type()==tape_block::TBT_EOT
)) {
352 if (fd
!=-1) close(fd
);
353 if (fd_numbered
!=-1) close(fd_numbered
);
358 if (cfg_ignore_object_integrity_errors
){
359 fprintf(stdwarn
,"Warning: Object integrity error!\n");
362 fprintf(stdwarn
,"Error: Object integrity error!\n");
370 /******************************************************************************/
372 *\brief Everything that has to do with symbol listing.
374 void process_called_imports(){
375 vector
<string
>exported
;
376 vector
<string
>called
;
377 vector
<string
>unsatisfied
;
379 for (unsigned int i
=0; i
<tape
.size();i
++){
380 merge_vector_unique(exported
,tape
[i
]->get_exported_symbols());
381 merge_vector_unique(called
,tape
[i
]->get_called_symbols());
384 for (unsigned int icalled
=0;icalled
<called
.size();icalled
++){
386 for (unsigned int iexported
=0;iexported
<exported
.size();iexported
++){
387 if (exported
[iexported
].compare(called
[icalled
])==0){
394 for (unsigned int i
=0;i
<unsatisfied
.size();i
++){
395 if (unsatisfied
[i
].compare(called
[icalled
])==0){
400 if (!present
) unsatisfied
.insert(unsatisfied
.end(),called
[icalled
]);
404 FILE * outp
=fdopen(out_fd
,"w");
406 if (cfg_output_called
){
407 dump_vector_fp(called
,outp
);
410 if (cfg_output_exported
){
411 dump_vector_fp(exported
,outp
);
414 if (cfg_output_unsatisfied
){
415 dump_vector_fp(unsatisfied
,outp
);
420 /******************************************************************************/
422 *\brief The main routine.
425 int main(int argc
, char ** args
){
427 // Do all the configuration stuff
428 do_config(argc
,args
);
430 // Output a version message if desired
432 fprintf(stderr
, ID_STRING
, VERSION
, BUILD_DATE
, BUILD_STAMP
);
436 // Assign warning output according to configuration
437 if (cfg_quiet
) stdwarn
=fopen("/dev/null","w");
440 read_tape(); // Process input to completion.
446 process_called_imports();
451 fprintf(stdwarn
,"Warnings:%i\n",warnings
);
454 if (cfg_verbose
) fprintf(stdwarn
,"Success.\n");