1 /******************************************************************************
5 * $Date: 2007/03/26 01:00:40 $
9 * Revision 2.0 2007/03/26 01:00:40 hachti
10 * *** empty log message ***
13 ******************************************************************************/
15 /* ldc2 preliminary main program */
17 #include <sys/types.h>
27 #include "tape_block.hh"
28 #include "data_block_0.hh"
33 #define BUILD_STAMP ""
40 #define ID_STRING "\n ldc2 - The X16 object tape analyser\n\
41 (C) 2007 Philipp Hachtmann\n\n\
42 Version %s, built %s\n %s\n\n"
44 /******************************************************************************/
46 static FILE * stdwarn
; //! Suppressable warning output file pointer.
47 static vector
<tape_block
*> tape
; //! Represents the whole tape contents.
48 static vector
<vector
<tape_block
*> > objects
; //! Tape content in objects.
51 static int warnings
=0;
52 static int errcode
=0; //! Variable for error codes.
57 fprintf(stderr
,"Failed. (%i)\n",errcode
);
62 /******************************************************************************/
64 *\brief Read in Tape data and do some checks and messages.
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
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.
81 bool spaced
=false; //! Help flag for spaced messages.
83 string message
; //! A warning or help message.
88 bool err_checksum
=false;
89 bool err_integrity
=false;
95 block
=tape_block::gen_from_fd(in_fd
);
98 catch(tape_block::eof_legal_exception
&e
){
99 read_pointer
+=e
.get_consumed();
100 break; // Immediately leave read loop.
103 catch(tape_block::io_error_exception
){
105 fprintf(stderr
,"Error: Could not read from \"%s\"!\n",cfg_infile
.c_str());
107 fprintf(stderr
,"Error: Could not read from stdin!\n");
111 break; // Immediately leave read loop.
114 catch(tape_block::eof_illegal_exception
&e
){
118 if (cfg_ignore_block_errors
){
119 message
="Warning: Block integrity check failed!\n";
122 message
="Error: Block integrity check failed!\n";
128 catch(tape_block::checksum_error_exception
&e
){
131 if (cfg_ignore_checksum_errors
){
132 message
="Warning: Block checksum wrong!\n";
135 message
="Error: Block checksum wrong!\n";
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!";
148 message
="Error: Unknown Block type!";
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;
163 if (error
) fp
=stderr
;
165 if (cfg_verbose
||error
||warning
){
166 if (!spaced
) fprintf(fp
,"\n");
168 fprintf(fp
,"Block No.%03i: Start:0x%04x End:0x%04x Size:0x%02x\n",
172 block
->get_raw_size());
175 if (error
) fprintf(stderr
,message
.c_str());
176 if (warning
) fprintf(stdwarn
,message
.c_str());
179 dump_vector(block
->get_description());
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;
188 if (error
||warning
||cfg_verbose
){
193 if (warning
) warnings
++;
197 fprintf(stderr
,"Reading finished.\n");
198 fprintf(stderr
,"Bytes read:%i, Blocks read:%i\n",read_pointer
,blocks_read
);
203 /******************************************************************************/
205 if (cfg_verbose
) fprintf(stdwarn
,"Processing Tape.\n");
207 bool in_object
=false;
209 char filename_numbered
[100];
211 int unknown_count
=-1;
212 int fd
=-1, fd_numbered
=-1;
216 for (unsigned int i
=0; i
<tape
.size();i
++){
217 tape_block
* block
=tape
[i
];
219 if (block
->get_type()==tape_block::TBT_EOT
){
222 if (cfg_ignore_object_integrity_errors
){
223 fprintf(stdwarn
,"Warning: Object integrity error!\n");
226 fprintf(stderr
,"Error: Object integrity error!\
227 (Object no %i, Block %i unexpected)\n",obj_no
,i
);
235 if (!in_object
){ // object begin
242 vector
<string
>names
=block
->get_exported_symbols();
243 for (unsigned int a
=0; a
<names
.size();a
++){
246 objname
=objname
.substr(0,objname
.find_last_not_of(" ")+1);
253 if (block
->get_type()==tape_block::TBT_EOT
){
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
);
265 fprintf(stderr
,"Error: could not open file \"%s\" for writing!\n",
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);
277 fprintf(stderr
,"Error: could not open file \"%s\" for writing!\n",
286 if (cfg_split_objects
){
288 if (block
->get_type()!=tape_block::TBT_EOT
) // Don't want EOT here
289 block
->dump_to_fd(fd
);
291 catch (tape_block::io_error_exception e
){
292 fprintf(stderr
,"Error: could write to file \"%s\"!\n",
296 } // if (cfg_split_objects)
299 if (cfg_split_objects_numbered
){
301 block
->dump_to_fd(fd_numbered
);
303 catch (tape_block::io_error_exception e
){
304 fprintf(stderr
,"Error: could write to file \"%s\"!\n",
308 } // if (cfg_split_objects_numbered)
310 // Output individual block file if desired
311 if (cfg_split_blocks
){
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);
316 fprintf(stderr
,"Error: could not open file \"%s\" for writing!\n",
321 block
->dump_to_fd(fd_block
);
323 catch (tape_block::io_error_exception e
){
324 fprintf(stderr
,"Error: could write to file \"%s\"!\n",
331 if (block
->is_endblock()||(block
->get_type()==tape_block::TBT_EOT
)) {
333 if (fd
!=-1) close(fd
);
334 if (fd_numbered
!=-1) close(fd_numbered
);
339 if (cfg_ignore_object_integrity_errors
){
340 fprintf(stdwarn
,"Warning: Object integrity error!\n");
343 fprintf(stdwarn
,"Error: Object integrity error!\n");
353 void process_called_imports(){
354 vector
<string
>exported
;
355 vector
<string
>called
;
356 vector
<string
>unsatisfied
;
358 for (unsigned int i
=0; i
<tape
.size();i
++){
359 merge_vector_unique(exported
,tape
[i
]->get_exported_symbols());
360 merge_vector_unique(called
,tape
[i
]->get_called_symbols());
363 for (unsigned int icalled
=0;icalled
<called
.size();icalled
++){
365 for (unsigned int iexported
=0;iexported
<exported
.size();iexported
++){
366 if (exported
[iexported
].compare(called
[icalled
])==0){
373 for (unsigned int i
=0;i
<unsatisfied
.size();i
++){
374 if (unsatisfied
[i
].compare(called
[icalled
])==0){
379 if (!present
) unsatisfied
.insert(unsatisfied
.end(),called
[icalled
]);
383 FILE * outp
=fdopen(out_fd
,"w");
385 if (cfg_output_called
){
386 dump_vector_fp(called
,outp
);
389 if (cfg_output_exported
){
390 dump_vector_fp(exported
,outp
);
393 if (cfg_output_unsatisfied
){
394 dump_vector_fp(unsatisfied
,outp
);
399 /******************************************************************************/
401 *\brief The main routine.
403 int main(int argc
, char ** args
){
405 // Do all the configuration stuff
406 do_config(argc
,args
);
408 // Output a version message if desired
410 fprintf(stderr
, ID_STRING
, VERSION
, BUILD_DATE
, BUILD_STAMP
);
414 // Assign warning output according to configuration
415 if (cfg_quiet
) stdwarn
=fopen("/dev/null","w");
418 read_tape(); // Process input to completion.
424 process_called_imports();
429 fprintf(stdwarn
,"Warnings:%i\n",warnings
);
432 if (cfg_verbose
) fprintf(stdwarn
,"Success.\n");