798b0c1d |
1 | /* ldc2 preliminary main program */ |
2 | |
7880ae2d |
3 | |
798b0c1d |
4 | #include <vector> |
5 | #include <string> |
f9d603d2 |
6 | |
ea4c19a4 |
7 | #include "config.hh" |
8 | #include "tool.hh" |
97b26985 |
9 | |
10 | #include "tape_block.hh" |
fed2c751 |
11 | #include "data_block_0.hh" |
12 | |
798b0c1d |
13 | using namespace std; |
14 | |
7880ae2d |
15 | #ifndef BUILD_STAMP |
16 | #define BUILD_STAMP "" |
17 | #endif |
18 | |
19 | #ifndef VERSION |
20 | #define VERSION "0.0" |
21 | #endif |
22 | |
874a2bd8 |
23 | #define ID_STRING "\n ldc2 - The X16 object tape analyser\n\ |
7880ae2d |
24 | (C) 2007 Philipp Hachtmann\n\n\ |
25 | Version %s, built %s\n %s\n\n" |
26 | |
874a2bd8 |
27 | /******************************************************************************/ |
7880ae2d |
28 | |
874a2bd8 |
29 | static FILE * stdwarn; //! Suppressable warning output file pointer. |
30 | static vector<tape_block*> tape; //! Represents the whole tape contents. |
31 | static vector<vector<tape_block*> > objects; //! Tape content in objects. |
7880ae2d |
32 | |
874a2bd8 |
33 | static int errors=0; |
34 | static int warnings=0; |
35 | static int errcode=0; //! Variable for error codes. |
7880ae2d |
36 | |
874a2bd8 |
37 | |
38 | void exit_on_error(){ |
39 | if (errors){ |
40 | fprintf(stderr,"Failed. (%i)\n",errcode); |
41 | exit(errcode); |
7880ae2d |
42 | } |
874a2bd8 |
43 | } |
909d3603 |
44 | |
874a2bd8 |
45 | /******************************************************************************/ |
46 | /*! |
47 | *\brief Read in Tape data and do some checks and messages. |
48 | * |
49 | * This routine reads in the tape data. |
50 | * During reading in, checksums are checked and |
51 | * /da001/ information is generated. No object integrity test. |
52 | * Tape block object pointers are put into the global vector |
53 | * tape. |
54 | */ |
55 | void read_tape(){ |
56 | |
57 | tape_block * block=0; //! Pointer to current block. |
58 | bool read_ahead=true; //! Continue scanning for blocks. |
59 | int read_pointer=0; //! Read position in input. |
60 | int block_start=0; //! Start of block position in input. |
61 | int block_end=0; //! End of block position in input. |
62 | int blocks_read=0; //! Number of blocks read in. |
ad324d29 |
63 | |
874a2bd8 |
64 | bool spaced=false; //! Help flag for spaced messages. |
65 | |
66 | string message; //! A warning or help message. |
7880ae2d |
67 | |
874a2bd8 |
68 | |
fed2c751 |
69 | while(read_ahead){ |
874a2bd8 |
70 | |
71 | bool err_checksum=false; |
72 | bool err_integrity=false; |
73 | |
74 | bool warning=false; |
75 | bool error=false; |
76 | |
7880ae2d |
77 | try{ |
78 | block=tape_block::gen_from_fd(in_fd); |
7880ae2d |
79 | } |
80 | |
81 | catch(tape_block::eof_legal_exception &e){ |
82 | read_pointer+=e.get_consumed(); |
83 | break; // Immediately leave read loop. |
84 | } |
85 | |
86 | catch(tape_block::io_error_exception){ |
fed2c751 |
87 | if (in_fd){ |
7880ae2d |
88 | fprintf(stderr,"Error: Could not read from \"%s\"!\n",cfg_infile.c_str()); |
fed2c751 |
89 | } else { |
7880ae2d |
90 | fprintf(stderr,"Error: Could not read from stdin!\n"); |
fed2c751 |
91 | } |
874a2bd8 |
92 | error=true; |
fed2c751 |
93 | errcode=2; |
7880ae2d |
94 | break; // Immediately leave read loop. |
95 | } |
96 | |
97 | catch(tape_block::eof_illegal_exception &e){ |
98 | block=e.get_block(); |
874a2bd8 |
99 | err_integrity=true; |
100 | read_ahead=false; |
7880ae2d |
101 | if (cfg_ignore_block_errors){ |
874a2bd8 |
102 | message="Warning: Block integrity check failed!\n"; |
103 | warning=true; |
7880ae2d |
104 | } else { |
874a2bd8 |
105 | message="Error: Block integrity check failed!\n"; |
106 | error=true; |
7880ae2d |
107 | errcode=3; |
fed2c751 |
108 | } |
7880ae2d |
109 | } |
110 | |
111 | catch(tape_block::checksum_error_exception &e){ |
112 | block=e.get_block(); |
874a2bd8 |
113 | err_checksum=true; |
7880ae2d |
114 | if (cfg_ignore_checksum_errors){ |
874a2bd8 |
115 | message="Warning: Block checksum wrong!\n"; |
116 | warning=true; |
fed2c751 |
117 | } else { |
874a2bd8 |
118 | message="Error: Block checksum wrong!\n"; |
119 | error=true; |
7880ae2d |
120 | read_ahead=false; |
121 | errcode=4; |
fed2c751 |
122 | } |
7880ae2d |
123 | } |
124 | |
874a2bd8 |
125 | // Now let's check for block type |
126 | if ((!error)&&(!warning)&&!block->has_known_type()){ |
127 | if (cfg_ignore_unknown_block_errors){ |
128 | message="Warning: Unknown Block type!"; |
129 | warning=true; |
130 | }else{ |
131 | message="Error: Unknown Block type!"; |
132 | error=true; |
133 | read_ahead=false; |
134 | errcode=5; |
135 | } |
136 | } |
137 | |
138 | // Count block. |
139 | blocks_read++; |
140 | tape.insert(tape.end(),block); |
141 | block_start=read_pointer+block->get_discarded_bytes(); |
142 | block_end=block_start+block->get_raw_size()-1; |
143 | read_pointer=block_end+1; |
144 | |
145 | FILE * fp=stdwarn; |
146 | if (error) fp=stderr; |
147 | |
148 | if (cfg_verbose||error||warning){ |
149 | if (!spaced) fprintf(fp,"\n"); |
150 | spaced=false; |
151 | fprintf(fp,"Block No.%03i: Start:0x%04x End:0x%04x Size:0x%02x\n", |
152 | blocks_read-1, |
153 | block_start, |
154 | block_end, |
155 | block->get_raw_size()); |
156 | } |
157 | |
158 | if (error) fprintf(stderr,message.c_str()); |
159 | if (warning) fprintf(stdwarn,message.c_str()); |
160 | |
161 | if(cfg_list_contents){ |
162 | dump_vector(block->get_description()); |
163 | if (!error&&!warning) spaced=false; |
164 | } |
7880ae2d |
165 | |
874a2bd8 |
166 | if (error||warning||cfg_verbose){ |
167 | fprintf(fp,"\n"); |
168 | spaced=true; |
169 | } |
170 | if (error) errors++; |
171 | if (warning) warnings++; |
172 | } // while.... |
7880ae2d |
173 | if (cfg_verbose){ |
874a2bd8 |
174 | close(in_fd); |
175 | fprintf(stderr,"Reading finished.\n"); |
176 | fprintf(stderr,"Bytes read:%i, Blocks read:%i\n",read_pointer,blocks_read); |
177 | } |
178 | } // read_tape() |
179 | |
180 | /******************************************************************************/ |
181 | |
182 | void type_check(){ |
183 | bool warning=false; |
184 | bool error=false; |
185 | |
186 | for (unsigned int i=0; i<tape.size();i++){ |
187 | bool spaced=false; |
188 | if (!tape[i]->has_known_type()){ |
189 | FILE * fp; |
190 | if (cfg_ignore_unknown_block_errors){ |
191 | fp=stdwarn; |
192 | warning=true; |
193 | } else { |
194 | fp=stderr; |
195 | error=true; |
196 | } |
197 | if (!spaced) { |
198 | spaced=false;fprintf(fp,"\n"); |
199 | fprintf(fp,"Warning: Unknown Block type! Block No.%i\n",i); |
200 | dump_vector_fp(tape[i]->get_description(),fp); |
201 | fprintf(fp,"\n"); |
202 | spaced=true; |
203 | } |
204 | if (!cfg_ignore_unknown_block_errors){ |
205 | int errcode=5; |
206 | fprintf(stdwarn,"Failed. (%i)\n",errcode); |
207 | exit(errcode); |
208 | } |
209 | } |
7880ae2d |
210 | } |
874a2bd8 |
211 | } // type_check() |
ad324d29 |
212 | |
874a2bd8 |
213 | /******************************************************************************/ |
214 | /*! |
215 | *\brief The main routine. |
216 | */ |
217 | int main(int argc, char ** args){ |
7880ae2d |
218 | |
219 | |
874a2bd8 |
220 | // Do all the configuration stuff |
221 | do_config(argc,args); |
222 | |
223 | // Output a version message if desired |
224 | if (cfg_version){ |
225 | fprintf(stderr, ID_STRING, VERSION, BUILD_DATE, BUILD_STAMP); |
226 | exit(0); |
227 | } |
228 | |
229 | // Assign warning output according to configuration |
230 | if (cfg_quiet) stdwarn=fopen("/dev/null","w"); |
231 | else stdwarn=stderr; |
232 | |
233 | read_tape(); // Process input to completion. |
234 | exit_on_error(); |
235 | |
236 | |
237 | |
238 | if (cfg_split_objects){ |
239 | for (unsigned int i=0; i<tape.size();i++){ |
240 | tape[i]->dump_to_fd(out_fd); |
241 | } |
242 | } |
7880ae2d |
243 | |
fed2c751 |
244 | |
ad324d29 |
245 | return 0; |
246 | } // main() |
798b0c1d |
247 | |