1 /* ldc2 preliminary main program */
13 #include "tape_block.hh"
14 #include "data_block_0.hh"
19 #define BUILD_STAMP ""
26 #define ID_STRING "\n ldc2 - The X16 object tape analyser\n\
27 (C) 2007 Philipp Hachtmann\n\n\
28 Version %s, built %s\n %s\n\n"
30 /******************************************************************************/
32 static FILE * stdwarn
; //! Suppressable warning output file pointer.
33 static vector
<tape_block
*> tape
; //! Represents the whole tape contents.
34 static vector
<vector
<tape_block
*> > objects
; //! Tape content in objects.
37 static int warnings
=0;
38 static int errcode
=0; //! Variable for error codes.
43 fprintf(stderr
,"Failed. (%i)\n",errcode
);
48 /******************************************************************************/
50 *\brief Read in Tape data and do some checks and messages.
52 * This routine reads in the tape data.
53 * During reading in, checksums are checked and
54 * /da001/ information is generated. No object integrity test.
55 * Tape block object pointers are put into the global vector
60 tape_block
* block
=0; //! Pointer to current block.
61 bool read_ahead
=true; //! Continue scanning for blocks.
62 int read_pointer
=0; //! Read position in input.
63 int block_start
=0; //! Start of block position in input.
64 int block_end
=0; //! End of block position in input.
65 int blocks_read
=0; //! Number of blocks read in.
67 bool spaced
=false; //! Help flag for spaced messages.
69 string message
; //! A warning or help message.
74 bool err_checksum
=false;
75 bool err_integrity
=false;
81 block
=tape_block::gen_from_fd(in_fd
);
84 catch(tape_block::eof_legal_exception
&e
){
85 read_pointer
+=e
.get_consumed();
86 break; // Immediately leave read loop.
89 catch(tape_block::io_error_exception
){
91 fprintf(stderr
,"Error: Could not read from \"%s\"!\n",cfg_infile
.c_str());
93 fprintf(stderr
,"Error: Could not read from stdin!\n");
97 break; // Immediately leave read loop.
100 catch(tape_block::eof_illegal_exception
&e
){
104 if (cfg_ignore_block_errors
){
105 message
="Warning: Block integrity check failed!\n";
108 message
="Error: Block integrity check failed!\n";
114 catch(tape_block::checksum_error_exception
&e
){
117 if (cfg_ignore_checksum_errors
){
118 message
="Warning: Block checksum wrong!\n";
121 message
="Error: Block checksum wrong!\n";
128 // Now let's check for block type
129 if ((!error
)&&(!warning
)&&!block
->has_known_type()){
130 if (cfg_ignore_unknown_block_errors
){
131 message
="Warning: Unknown Block type!";
134 message
="Error: Unknown Block type!";
143 tape
.insert(tape
.end(),block
);
144 block_start
=read_pointer
+block
->get_discarded_bytes();
145 block_end
=block_start
+block
->get_raw_size()-1;
146 read_pointer
=block_end
+1;
149 if (error
) fp
=stderr
;
151 if (cfg_verbose
||error
||warning
){
152 if (!spaced
) fprintf(fp
,"\n");
154 fprintf(fp
,"Block No.%03i: Start:0x%04x End:0x%04x Size:0x%02x\n",
158 block
->get_raw_size());
161 if (error
) fprintf(stderr
,message
.c_str());
162 if (warning
) fprintf(stdwarn
,message
.c_str());
165 dump_vector(block
->get_description());
167 if(cfg_list_contents
){
168 FILE * tmp_fp
=fdopen(out_fd
,"w");
169 dump_vector_fp(block
->get_description(),tmp_fp
);
170 if (!error
&&!warning
) spaced
=false;
174 if (error
||warning
||cfg_verbose
){
179 if (warning
) warnings
++;
183 fprintf(stderr
,"Reading finished.\n");
184 fprintf(stderr
,"Bytes read:%i, Blocks read:%i\n",read_pointer
,blocks_read
);
189 /******************************************************************************/
191 if (cfg_verbose
) fprintf(stdwarn
,"Processing Tape.\n");
193 bool in_object
=false;
195 char filename_numbered
[100];
197 int unknown_count
=-1;
198 int fd
=-1, fd_numbered
=-1;
202 for (unsigned int i
=0; i
<tape
.size();i
++){
203 tape_block
* block
=tape
[i
];
205 if (block
->get_type()==tape_block::TBT_EOT
){
208 if (cfg_ignore_object_integrity_errors
){
209 fprintf(stdwarn
,"Warning: Object integrity error!\n");
212 fprintf(stderr
,"Error: Object integrity error!\
213 (Object no %i, Block %i unexpected)\n",obj_no
,i
);
221 if (!in_object
){ // object begin
228 vector
<string
>names
=block
->get_exported_symbols();
229 for (unsigned int a
=0; a
<names
.size();a
++){
232 objname
=objname
.substr(0,objname
.find_last_not_of(" ")+1);
239 if (block
->get_type()==tape_block::TBT_EOT
){
243 // Open file for split objects
244 if (cfg_split_objects
&& (block
->get_type()!=tape_block::TBT_EOT
)){
245 if (objname
=="UNKNOWN")snprintf(filename
,99,"UNKNOWN%02i.obj",unknown_count
);
246 else snprintf(filename
,99,"%s.obj",objname
.c_str());
247 if (fd
>-1) close (fd
);
248 fd
=open(filename
,O_WRONLY
|O_CREAT
|O_TRUNC
,0666);
249 printf("opening \"%s\"\n",filename
);
251 fprintf(stderr
,"Error: could not open file \"%s\" for writing!\n",
257 // Open file for split objects numbered
258 snprintf(filename_numbered
,99,"%03i0-%s.obj",obj_no
,objname
.c_str());
259 if (cfg_split_objects_numbered
){
260 if (fd_numbered
>-1) close (fd_numbered
);
261 fd_numbered
=open(filename_numbered
,O_WRONLY
|O_CREAT
|O_TRUNC
,0666);
263 fprintf(stderr
,"Error: could not open file \"%s\" for writing!\n",
272 if (cfg_split_objects
){
274 if (block
->get_type()!=tape_block::TBT_EOT
) // Don't want EOT here
275 block
->dump_to_fd(fd
);
277 catch (tape_block::io_error_exception e
){
278 fprintf(stderr
,"Error: could write to file \"%s\"!\n",
282 } // if (cfg_split_objects)
285 if (cfg_split_objects_numbered
){
287 block
->dump_to_fd(fd_numbered
);
289 catch (tape_block::io_error_exception e
){
290 fprintf(stderr
,"Error: could write to file \"%s\"!\n",
294 } // if (cfg_split_objects_numbered)
296 // Output individual block file if desired
297 if (cfg_split_blocks
){
299 snprintf(fname
,99,"%03i0-%s-%03i.block",obj_no
,objname
.c_str(),i
-obj_start_block
);
300 int fd_block
=open(fname
,O_WRONLY
|O_TRUNC
|O_CREAT
,0666);
302 fprintf(stderr
,"Error: could not open file \"%s\" for writing!\n",
307 block
->dump_to_fd(fd_block
);
309 catch (tape_block::io_error_exception e
){
310 fprintf(stderr
,"Error: could write to file \"%s\"!\n",
317 if (block
->is_endblock()||(block
->get_type()==tape_block::TBT_EOT
)) {
319 if (fd
!=-1) close(fd
);
320 if (fd_numbered
!=-1) close(fd_numbered
);
325 if (cfg_ignore_object_integrity_errors
){
326 fprintf(stdwarn
,"Warning: Object integrity error!\n");
329 fprintf(stdwarn
,"Error: Object integrity error!\n");
339 void process_called_imports(){
340 vector
<string
>exported
;
341 vector
<string
>called
;
342 vector
<string
>unsatisfied
;
344 for (unsigned int i
=0; i
<tape
.size();i
++){
345 merge_vector_unique(exported
,tape
[i
]->get_exported_symbols());
346 merge_vector_unique(called
,tape
[i
]->get_called_symbols());
349 for (unsigned int icalled
=0;icalled
<called
.size();icalled
++){
351 for (unsigned int iexported
=0;iexported
<exported
.size();iexported
++){
352 if (exported
[iexported
].compare(called
[icalled
])==0){
359 for (unsigned int i
=0;i
<unsatisfied
.size();i
++){
360 if (unsatisfied
[i
].compare(called
[icalled
])==0){
365 if (!present
) unsatisfied
.insert(unsatisfied
.end(),called
[icalled
]);
369 FILE * outp
=fdopen(out_fd
,"w");
371 if (cfg_output_called
){
372 dump_vector_fp(called
,outp
);
375 if (cfg_output_exported
){
376 dump_vector_fp(exported
,outp
);
379 if (cfg_output_unsatisfied
){
380 dump_vector_fp(unsatisfied
,outp
);
385 /******************************************************************************/
387 *\brief The main routine.
389 int main(int argc
, char ** args
){
391 // Do all the configuration stuff
392 do_config(argc
,args
);
394 // Output a version message if desired
396 fprintf(stderr
, ID_STRING
, VERSION
, BUILD_DATE
, BUILD_STAMP
);
400 // Assign warning output according to configuration
401 if (cfg_quiet
) stdwarn
=fopen("/dev/null","w");
404 read_tape(); // Process input to completion.
410 process_called_imports();
415 fprintf(stdwarn
,"Warnings:%i\n",warnings
);
418 if (cfg_verbose
) fprintf(stdwarn
,"Success.\n");