Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1186 | savelij | 1 | /* p2bin.c */ |
2 | /*****************************************************************************/ |
||
3 | /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */ |
||
4 | /* */ |
||
5 | /* AS-Portierung */ |
||
6 | /* */ |
||
7 | /* Umwandlung von AS-Codefiles in Binaerfiles */ |
||
8 | /* */ |
||
9 | /*****************************************************************************/ |
||
10 | |||
11 | #include "stdinc.h" |
||
12 | #include <string.h> |
||
13 | #include <ctype.h> |
||
14 | |||
15 | #include "version.h" |
||
16 | #include "be_le.h" |
||
17 | #include "bpemu.h" |
||
18 | #include "strutil.h" |
||
19 | #include "nls.h" |
||
20 | #include "nlmessages.h" |
||
21 | #include "p2bin.rsc" |
||
22 | #ifdef _USE_MSH |
||
23 | # include "p2bin.msh" |
||
24 | #endif |
||
25 | #include "ioerrs.h" |
||
26 | #include "chunks.h" |
||
27 | #include "stringlists.h" |
||
28 | #include "cmdarg.h" |
||
29 | #include "msg_level.h" |
||
30 | #include "toolutils.h" |
||
31 | |||
32 | #define BinSuffix ".bin" |
||
33 | |||
34 | |||
35 | typedef void (*ProcessProc)( |
||
36 | #ifdef __PROTOS__ |
||
37 | const char *FileName, LongWord Offset |
||
38 | #endif |
||
39 | ); |
||
40 | |||
41 | |||
42 | static FILE *TargFile; |
||
43 | static String TargName; |
||
44 | |||
45 | static LongWord StartAdr, StopAdr, EntryAdr, RealFileLen; |
||
46 | static LongWord MaxGran, Dummy; |
||
47 | static Boolean StartAuto, StopAuto, AutoErase, EntryAdrPresent, last_byte_no_pad; |
||
48 | |||
49 | static Byte FillVal, ValidSegment; |
||
50 | static Boolean DoCheckSum; |
||
51 | |||
52 | static Byte SizeDiv; |
||
53 | static LongWord ANDMask, ANDEq; |
||
54 | static ShortInt StartHeader; |
||
55 | |||
56 | static ChunkList UsedList; |
||
57 | |||
58 | |||
59 | #ifdef DEBUG |
||
60 | #define ChkIO(s) ChkIO_L(s, __LINE__) |
||
61 | |||
62 | static void ChkIO_L(char *s, int line) |
||
63 | { |
||
64 | if (errno != 0) |
||
65 | { |
||
66 | fprintf(stderr, "%s %d\n", s, line); |
||
67 | exit(3); |
||
68 | } |
||
69 | } |
||
70 | #endif |
||
71 | |||
72 | static void ParamError(Boolean InEnv, char *Arg) |
||
73 | { |
||
74 | fprintf(stderr, "%s%s\n%s\n", |
||
75 | getmessage(InEnv ? Num_ErrMsgInvEnvParam:Num_ErrMsgInvParam), |
||
76 | Arg, getmessage(Num_ErrMsgProgTerm)); |
||
77 | } |
||
78 | |||
79 | #define BufferSize 4096 |
||
80 | static Byte Buffer[BufferSize]; |
||
81 | |||
82 | static void OpenTarget(void) |
||
83 | { |
||
84 | LongWord Rest, Trans, AHeader; |
||
85 | |||
86 | TargFile = fopen(TargName, OPENWRMODE); |
||
87 | if (!TargFile) |
||
88 | ChkIO(TargName); |
||
89 | RealFileLen = ((StopAdr - StartAdr + 1) * MaxGran) / SizeDiv; |
||
90 | |||
91 | AHeader = abs(StartHeader); |
||
92 | if (StartHeader != 0) |
||
93 | { |
||
94 | memset(Buffer, 0, AHeader); |
||
95 | if (fwrite(Buffer, 1, abs(StartHeader), TargFile) != AHeader) |
||
96 | ChkIO(TargName); |
||
97 | } |
||
98 | |||
99 | memset(Buffer, FillVal, BufferSize); |
||
100 | |||
101 | Rest = RealFileLen; |
||
102 | while (Rest != 0) |
||
103 | { |
||
104 | Trans = min(Rest, BufferSize); |
||
105 | if (fwrite(Buffer, 1, Trans, TargFile) != Trans) |
||
106 | ChkIO(TargName); |
||
107 | Rest -= Trans; |
||
108 | } |
||
109 | } |
||
110 | |||
111 | static void CloseTarget(void) |
||
112 | { |
||
113 | LongWord z, AHeader; |
||
114 | |||
115 | AHeader = abs(StartHeader); |
||
116 | |||
117 | /* write entry address to file? */ |
||
118 | |||
119 | if (EntryAdrPresent && (StartHeader != 0)) |
||
120 | { |
||
121 | LongWord bpos; |
||
122 | |||
123 | rewind(TargFile); |
||
124 | bpos = ((StartHeader > 0) ? 0 : -1 - StartHeader) << 3; |
||
125 | for (z = 0; z < AHeader; z++) |
||
126 | { |
||
127 | Buffer[z] = (EntryAdr >> bpos) & 0xff; |
||
128 | bpos += (StartHeader > 0) ? 8 : -8; |
||
129 | } |
||
130 | if (fwrite(Buffer, 1, AHeader, TargFile) != AHeader) |
||
131 | ChkIO(TargName); |
||
132 | } |
||
133 | |||
134 | if (EOF == fclose(TargFile)) |
||
135 | ChkIO(TargName); |
||
136 | |||
137 | /* compute checksum over file? */ |
||
138 | |||
139 | if (DoCheckSum) |
||
140 | { |
||
141 | LongWord Sum, Size, Rest, Trans, Read; |
||
142 | |||
143 | if (last_byte_no_pad) |
||
144 | chkio_printf(TargName, "%s\n", getmessage(Num_WarnMessChecksumOverlaysData)); |
||
145 | |||
146 | TargFile = fopen(TargName, OPENUPMODE); |
||
147 | if (!TargFile) |
||
148 | ChkIO(TargName); |
||
149 | if (fseek(TargFile, AHeader, SEEK_SET) == -1) |
||
150 | ChkIO(TargName); |
||
151 | Size = Rest = FileSize(TargFile) - AHeader - 1; |
||
152 | |||
153 | Sum = 0; |
||
154 | while (Rest > 0) |
||
155 | { |
||
156 | Trans = min(Rest, BufferSize); |
||
157 | Rest -= Trans; |
||
158 | Read = fread(Buffer, 1, Trans, TargFile); |
||
159 | if (Read != Trans) |
||
160 | chk_wr_read_error(TargName); |
||
161 | for (z = 0; z < Trans; Sum += Buffer[z++]); |
||
162 | } |
||
163 | chkio_printf(TargName, "%s%08lX\n", getmessage(Num_InfoMessChecksum), LoDWord(Sum)); |
||
164 | Buffer[0] = 0x100 - (Sum & 0xff); |
||
165 | |||
166 | /* Some systems require fflush() between read & write operations. And |
||
167 | some other systems again garble the file pointer upon an fflush(): */ |
||
168 | |||
169 | fflush(TargFile); |
||
170 | if (fseek(TargFile, AHeader + Size, SEEK_SET) == -1) |
||
171 | ChkIO(TargName); |
||
172 | if (fwrite(Buffer, 1, 1, TargFile) != 1) |
||
173 | ChkIO(TargName); |
||
174 | fflush(TargFile); |
||
175 | |||
176 | if (fclose(TargFile) == EOF) |
||
177 | ChkIO(TargName); |
||
178 | } |
||
179 | |||
180 | if (Magic != 0) |
||
181 | unlink(TargName); |
||
182 | } |
||
183 | |||
184 | static void ProcessFile(const char *FileName, LongWord Offset) |
||
185 | { |
||
186 | FILE *SrcFile; |
||
187 | Word TestID; |
||
188 | Byte InpHeader, InpCPU, InpSegment; |
||
189 | LongWord InpStart, SumLen; |
||
190 | Word InpLen, TransLen, ResLen; |
||
191 | Boolean doit; |
||
192 | LongWord ErgStart, ErgStop; |
||
193 | LongInt NextPos; |
||
194 | Word ErgLen = 0; |
||
195 | Byte Gran; |
||
196 | |||
197 | SrcFile = fopen(FileName, OPENRDMODE); |
||
198 | if (!SrcFile) |
||
199 | ChkIO(FileName); |
||
200 | |||
201 | if (!Read2(SrcFile, &TestID)) |
||
202 | chk_wr_read_error(FileName); |
||
203 | if (TestID != FileID) |
||
204 | FormatError(FileName, getmessage(Num_FormatInvHeaderMsg)); |
||
205 | |||
206 | if (msg_level >= e_msg_level_normal) |
||
207 | chkio_printf(OutName, "%s==>>%s", FileName, TargName); |
||
208 | |||
209 | SumLen = 0; |
||
210 | |||
211 | do |
||
212 | { |
||
213 | ReadRecordHeader(&InpHeader, &InpCPU, &InpSegment, &Gran, FileName, SrcFile); |
||
214 | |||
215 | if (InpHeader == FileHeaderStartAdr) |
||
216 | { |
||
217 | if (!Read4(SrcFile, &ErgStart)) |
||
218 | chk_wr_read_error(FileName); |
||
219 | if (!EntryAdrPresent) |
||
220 | { |
||
221 | EntryAdr = ErgStart; |
||
222 | EntryAdrPresent = True; |
||
223 | } |
||
224 | } |
||
225 | |||
226 | else if (InpHeader == FileHeaderDataRec) |
||
227 | { |
||
228 | if (!Read4(SrcFile, &InpStart)) |
||
229 | chk_wr_read_error(FileName); |
||
230 | if (!Read2(SrcFile, &InpLen)) |
||
231 | chk_wr_read_error(FileName); |
||
232 | |||
233 | NextPos = ftell(SrcFile) + InpLen; |
||
234 | if (NextPos >= FileSize(SrcFile) - 1) |
||
235 | FormatError(FileName, getmessage(Num_FormatInvRecordLenMsg)); |
||
236 | |||
237 | doit = (FilterOK(InpHeader) && (InpSegment == ValidSegment)); |
||
238 | |||
239 | if (doit) |
||
240 | { |
||
241 | InpStart += Offset; |
||
242 | ErgStart = max(StartAdr, InpStart); |
||
243 | ErgStop = min(StopAdr, InpStart + (InpLen/Gran) - 1); |
||
244 | if (ErgStop == StopAdr) |
||
245 | last_byte_no_pad = True; |
||
246 | doit = (ErgStop >= ErgStart); |
||
247 | if (doit) |
||
248 | { |
||
249 | ErgLen = (ErgStop + 1 - ErgStart) * Gran; |
||
250 | if (AddChunk(&UsedList, ErgStart, ErgStop - ErgStart + 1, True)) |
||
251 | chkio_fprintf(stderr, OutName, " %s\n", getmessage(Num_ErrMsgOverlap)); |
||
252 | } |
||
253 | } |
||
254 | |||
255 | if (doit) |
||
256 | { |
||
257 | /* an Anfang interessierender Daten */ |
||
258 | |||
259 | if (fseek(SrcFile, (ErgStart - InpStart) * Gran, SEEK_CUR) == -1) |
||
260 | ChkIO(FileName); |
||
261 | |||
262 | /* in Zieldatei an passende Stelle */ |
||
263 | |||
264 | if (fseek(TargFile, (((ErgStart - StartAdr) * Gran)/SizeDiv) + abs(StartHeader), SEEK_SET) == -1) |
||
265 | ChkIO(TargName); |
||
266 | |||
267 | /* umkopieren */ |
||
268 | |||
269 | while (ErgLen > 0) |
||
270 | { |
||
271 | TransLen = min(BufferSize, ErgLen); |
||
272 | if (fread(Buffer, 1, TransLen, SrcFile) != TransLen) |
||
273 | chk_wr_read_error(FileName); |
||
274 | if (SizeDiv == 1) ResLen = TransLen; |
||
275 | else |
||
276 | { |
||
277 | LongWord Addr; |
||
278 | |||
279 | ResLen = 0; |
||
280 | for (Addr = 0; Addr < (LongWord)TransLen; Addr++) |
||
281 | if (((ErgStart * Gran + Addr) & ANDMask) == ANDEq) |
||
282 | Buffer[ResLen++] = Buffer[Addr]; |
||
283 | } |
||
284 | if (fwrite(Buffer, 1, ResLen, TargFile) != ResLen) |
||
285 | ChkIO(TargName); |
||
286 | ErgLen -= TransLen; |
||
287 | ErgStart += TransLen; |
||
288 | SumLen += ResLen; |
||
289 | } |
||
290 | } |
||
291 | if (fseek(SrcFile, NextPos, SEEK_SET) == -1) |
||
292 | ChkIO(FileName); |
||
293 | } |
||
294 | else |
||
295 | SkipRecord(InpHeader, FileName, SrcFile); |
||
296 | } |
||
297 | while (InpHeader != 0); |
||
298 | |||
299 | if (msg_level >= e_msg_level_normal) |
||
300 | { |
||
301 | chkio_printf(OutName, " ("); |
||
302 | chkio_printf(OutName, Integ32Format, SumLen); |
||
303 | chkio_printf(OutName, " %s)\n", getmessage((SumLen == 1) ? Num_Byte : Num_Bytes)); |
||
304 | } |
||
305 | if (!SumLen) |
||
306 | { |
||
307 | if (EOF == fputs(getmessage(Num_WarnEmptyFile), stdout)) |
||
308 | ChkIO(OutName); |
||
309 | } |
||
310 | |||
311 | if (fclose(SrcFile) == EOF) |
||
312 | ChkIO(FileName); |
||
313 | } |
||
314 | |||
315 | static ProcessProc CurrProcessor; |
||
316 | static LongWord CurrOffset; |
||
317 | |||
318 | static void Callback(char *Name) |
||
319 | { |
||
320 | CurrProcessor(Name, CurrOffset); |
||
321 | } |
||
322 | |||
323 | static void ProcessGroup(const char *GroupName_O, ProcessProc Processor) |
||
324 | { |
||
325 | String Ext, GroupName; |
||
326 | |||
327 | CurrProcessor = Processor; |
||
328 | strmaxcpy(GroupName, GroupName_O, STRINGSIZE); |
||
329 | strmaxcpy(Ext, GroupName, STRINGSIZE); |
||
330 | if (!RemoveOffset(GroupName, &CurrOffset)) |
||
331 | { |
||
332 | ParamError(False, Ext); |
||
333 | exit(1); |
||
334 | } |
||
335 | AddSuffix(GroupName, STRINGSIZE, getmessage(Num_Suffix)); |
||
336 | |||
337 | if (!DirScan(GroupName, Callback)) |
||
338 | fprintf(stderr, "%s%s%s\n", getmessage(Num_ErrMsgNullMaskA), GroupName, getmessage(Num_ErrMsgNullMaskB)); |
||
339 | } |
||
340 | |||
341 | static void MeasureFile(const char *FileName, LongWord Offset) |
||
342 | { |
||
343 | FILE *f; |
||
344 | Byte Header, CPU, Gran, Segment; |
||
345 | Word Length, TestID; |
||
346 | LongWord Adr, EndAdr; |
||
347 | LongInt NextPos; |
||
348 | |||
349 | f = fopen(FileName, OPENRDMODE); |
||
350 | if (!f) |
||
351 | ChkIO(FileName); |
||
352 | |||
353 | if (!Read2(f, &TestID)) |
||
354 | chk_wr_read_error(FileName); |
||
355 | if (TestID != FileMagic) |
||
356 | FormatError(FileName, getmessage(Num_FormatInvHeaderMsg)); |
||
357 | |||
358 | do |
||
359 | { |
||
360 | ReadRecordHeader(&Header, &CPU, &Segment, &Gran, FileName, f); |
||
361 | |||
362 | if (Header == FileHeaderDataRec) |
||
363 | { |
||
364 | if (!Read4(f, &Adr)) |
||
365 | chk_wr_read_error(FileName); |
||
366 | if (!Read2(f, &Length)) |
||
367 | chk_wr_read_error(FileName); |
||
368 | NextPos = ftell(f) + Length; |
||
369 | if (NextPos > FileSize(f)) |
||
370 | FormatError(FileName, getmessage(Num_FormatInvRecordLenMsg)); |
||
371 | |||
372 | if (FilterOK(Header) && (Segment == ValidSegment)) |
||
373 | { |
||
374 | Adr += Offset; |
||
375 | EndAdr = Adr + (Length/Gran)-1; |
||
376 | if (Gran > MaxGran) |
||
377 | MaxGran = Gran; |
||
378 | if (StartAuto) |
||
379 | if (StartAdr > Adr) |
||
380 | StartAdr = Adr; |
||
381 | if (StopAuto) |
||
382 | if (EndAdr > StopAdr) |
||
383 | StopAdr = EndAdr; |
||
384 | } |
||
385 | |||
386 | fseek(f, NextPos, SEEK_SET); |
||
387 | } |
||
388 | else |
||
389 | SkipRecord(Header, FileName, f); |
||
390 | } |
||
391 | while (Header != 0); |
||
392 | |||
393 | if (fclose(f) == EOF) |
||
394 | ChkIO(FileName); |
||
395 | } |
||
396 | |||
397 | /* --------------------------------------------- */ |
||
398 | |||
399 | static as_cmd_result_t CMD_AdrRange(Boolean Negate, const char *Arg) |
||
400 | { |
||
401 | if (Negate) |
||
402 | { |
||
403 | StartAdr = 0; StopAdr = 0x7fff; |
||
404 | return e_cmd_ok; |
||
405 | } |
||
406 | else |
||
407 | return CMD_Range(&StartAdr, &StopAdr, |
||
408 | &StartAuto, &StopAuto, Arg); |
||
409 | } |
||
410 | |||
411 | static as_cmd_result_t CMD_ByteMode(Boolean Negate, const char *pArg) |
||
412 | { |
||
413 | #define ByteModeCnt 9 |
||
414 | static const char *ByteModeStrings[ByteModeCnt] = |
||
415 | { |
||
416 | "ALL", "EVEN", "ODD", "BYTE0", "BYTE1", "BYTE2", "BYTE3", "WORD0", "WORD1" |
||
417 | }; |
||
418 | static Byte ByteModeDivs[ByteModeCnt] = |
||
419 | { |
||
420 | 1, 2, 2, 4, 4, 4, 4, 2, 2 |
||
421 | }; |
||
422 | static Byte ByteModeMasks[ByteModeCnt] = |
||
423 | { |
||
424 | 0, 1, 1, 3, 3, 3, 3, 2, 2 |
||
425 | }; |
||
426 | static Byte ByteModeEqs[ByteModeCnt] = |
||
427 | { |
||
428 | 0, 0, 1, 0, 1, 2, 3, 0, 2 |
||
429 | }; |
||
430 | |||
431 | int z; |
||
432 | UNUSED(Negate); |
||
433 | |||
434 | if (*pArg == '\0') |
||
435 | { |
||
436 | SizeDiv = 1; |
||
437 | ANDEq = 0; |
||
438 | ANDMask = 0; |
||
439 | return e_cmd_ok; |
||
440 | } |
||
441 | else |
||
442 | { |
||
443 | String Arg; |
||
444 | |||
445 | strmaxcpy(Arg, pArg, STRINGSIZE); |
||
446 | NLS_UpString(Arg); |
||
447 | ANDEq = 0xff; |
||
448 | for (z = 0; z < ByteModeCnt; z++) |
||
449 | if (strcmp(Arg, ByteModeStrings[z]) == 0) |
||
450 | { |
||
451 | SizeDiv = ByteModeDivs[z]; |
||
452 | ANDMask = ByteModeMasks[z]; |
||
453 | ANDEq = ByteModeEqs[z]; |
||
454 | } |
||
455 | if (ANDEq == 0xff) |
||
456 | return e_cmd_err; |
||
457 | else |
||
458 | return e_cmd_arg; |
||
459 | } |
||
460 | } |
||
461 | |||
462 | static as_cmd_result_t CMD_StartHeader(Boolean Negate, const char *Arg) |
||
463 | { |
||
464 | Boolean err; |
||
465 | ShortInt Sgn; |
||
466 | |||
467 | if (Negate) |
||
468 | { |
||
469 | StartHeader = 0; |
||
470 | return e_cmd_ok; |
||
471 | } |
||
472 | else |
||
473 | { |
||
474 | Sgn = 1; |
||
475 | if (*Arg == '\0') |
||
476 | return e_cmd_err; |
||
477 | switch (as_toupper(*Arg)) |
||
478 | { |
||
479 | case 'B': |
||
480 | Sgn = -1; |
||
481 | /* fall-through */ |
||
482 | case 'L': |
||
483 | Arg++; |
||
484 | } |
||
485 | StartHeader = ConstLongInt(Arg, &err, 10); |
||
486 | if ((!err) || (StartHeader > 4)) |
||
487 | return e_cmd_err; |
||
488 | StartHeader *= Sgn; |
||
489 | return e_cmd_arg; |
||
490 | } |
||
491 | } |
||
492 | |||
493 | static as_cmd_result_t CMD_EntryAdr(Boolean Negate, const char *Arg) |
||
494 | { |
||
495 | Boolean err; |
||
496 | |||
497 | if (Negate) |
||
498 | { |
||
499 | EntryAdrPresent = False; |
||
500 | return e_cmd_ok; |
||
501 | } |
||
502 | else |
||
503 | { |
||
504 | EntryAdr = ConstLongInt(Arg, &err, 10); |
||
505 | if (err) |
||
506 | EntryAdrPresent = True; |
||
507 | return (err) ? e_cmd_arg : e_cmd_err; |
||
508 | } |
||
509 | } |
||
510 | |||
511 | static as_cmd_result_t CMD_FillVal(Boolean Negate, const char *Arg) |
||
512 | { |
||
513 | Boolean err; |
||
514 | UNUSED(Negate); |
||
515 | |||
516 | FillVal = ConstLongInt(Arg, &err, 10); |
||
517 | return err ? e_cmd_arg : e_cmd_err; |
||
518 | } |
||
519 | |||
520 | static as_cmd_result_t CMD_CheckSum(Boolean Negate, const char *Arg) |
||
521 | { |
||
522 | UNUSED(Arg); |
||
523 | |||
524 | DoCheckSum = !Negate; |
||
525 | return e_cmd_ok; |
||
526 | } |
||
527 | |||
528 | static as_cmd_result_t CMD_AutoErase(Boolean Negate, const char *Arg) |
||
529 | { |
||
530 | UNUSED(Arg); |
||
531 | |||
532 | AutoErase = !Negate; |
||
533 | return e_cmd_ok; |
||
534 | } |
||
535 | |||
536 | static as_cmd_result_t CMD_ForceSegment(Boolean Negate, const char *Arg) |
||
537 | { |
||
538 | int z = addrspace_lookup(Arg); |
||
539 | |||
540 | if (z >= SegCount) |
||
541 | return e_cmd_err; |
||
542 | |||
543 | if (!Negate) |
||
544 | ValidSegment = z; |
||
545 | else if (ValidSegment == z) |
||
546 | ValidSegment = SegCode; |
||
547 | |||
548 | return e_cmd_arg; |
||
549 | } |
||
550 | |||
551 | static as_cmd_rec_t P2BINParams[] = |
||
552 | { |
||
553 | { "f" , CMD_FilterList }, |
||
554 | { "r" , CMD_AdrRange }, |
||
555 | { "s" , CMD_CheckSum }, |
||
556 | { "m" , CMD_ByteMode }, |
||
557 | { "l" , CMD_FillVal }, |
||
558 | { "e" , CMD_EntryAdr }, |
||
559 | { "S" , CMD_StartHeader }, |
||
560 | { "k" , CMD_AutoErase }, |
||
561 | { "SEGMENT" , CMD_ForceSegment } |
||
562 | }; |
||
563 | |||
564 | int main(int argc, char **argv) |
||
565 | { |
||
566 | as_cmd_results_t cmd_results; |
||
567 | char *p_target_name; |
||
568 | const char *p_src_name; |
||
569 | StringRecPtr p_src_run; |
||
570 | |||
571 | nls_init(); |
||
572 | if (!NLS_Initialize(&argc, argv)) |
||
573 | exit(4); |
||
574 | |||
575 | be_le_init(); |
||
576 | strutil_init(); |
||
577 | bpemu_init(); |
||
578 | #ifdef _USE_MSH |
||
579 | nlmessages_init_buffer(p2bin_msh_data, sizeof(p2bin_msh_data), MsgId1, MsgId2); |
||
580 | #else |
||
581 | nlmessages_init_file("p2bin.msg", *argv, MsgId1, MsgId2); |
||
582 | #endif |
||
583 | ioerrs_init(*argv); |
||
584 | chunks_init(); |
||
585 | as_cmdarg_init(*argv); |
||
586 | msg_level_init(); |
||
587 | toolutils_init(*argv); |
||
588 | |||
589 | InitChunk(&UsedList); |
||
590 | |||
591 | StartAdr = 0; |
||
592 | StopAdr = 0x7fff; |
||
593 | StartAuto = True; |
||
594 | StopAuto = True; |
||
595 | FillVal = 0xff; |
||
596 | DoCheckSum = False; |
||
597 | last_byte_no_pad = False; |
||
598 | SizeDiv = 1; |
||
599 | ANDEq = 0; |
||
600 | EntryAdr = -1; |
||
601 | EntryAdrPresent = False; |
||
602 | AutoErase = False; |
||
603 | StartHeader = 0; |
||
604 | ValidSegment = SegCode; |
||
605 | |||
606 | as_cmd_register(P2BINParams, as_array_size(P2BINParams)); |
||
607 | if (e_cmd_err == as_cmd_process(argc, argv, "P2BINCMD", &cmd_results)) |
||
608 | { |
||
609 | ParamError(cmd_results.error_arg_in_env, cmd_results.error_arg); |
||
610 | exit(1); |
||
611 | } |
||
612 | |||
613 | if ((msg_level >= e_msg_level_verbose) || cmd_results.write_version_exit) |
||
614 | { |
||
615 | String Ver; |
||
616 | |||
617 | as_snprintf(Ver, sizeof(Ver), "P2BIN V%s", Version); |
||
618 | WrCopyRight(Ver); |
||
619 | } |
||
620 | |||
621 | if (cmd_results.write_help_exit) |
||
622 | { |
||
623 | char *ph1, *ph2; |
||
624 | |||
625 | chkio_printf(OutName, "%s%s%s\n", getmessage(Num_InfoMessHead1), as_cmdarg_get_executable_name(), getmessage(Num_InfoMessHead2)); |
||
626 | for (ph1 = getmessage(Num_InfoMessHelp), ph2 = strchr(ph1, '\n'); ph2; ph1 = ph2 + 1, ph2 = strchr(ph1, '\n')) |
||
627 | { |
||
628 | *ph2 = '\0'; |
||
629 | chkio_printf(OutName, "%s\n", ph1); |
||
630 | *ph2 = '\n'; |
||
631 | } |
||
632 | } |
||
633 | |||
634 | if (cmd_results.write_version_exit || cmd_results.write_help_exit) |
||
635 | exit(0); |
||
636 | |||
637 | if (StringListEmpty(cmd_results.file_arg_list)) |
||
638 | { |
||
639 | fprintf(stderr, "%s: %s\n", as_cmdarg_get_executable_name(), getmessage(Num_ErrMessNoInputFiles)); |
||
640 | exit(1); |
||
641 | } |
||
642 | |||
643 | p_target_name = MoveAndCutStringListLast(&cmd_results.file_arg_list); |
||
644 | if (!p_target_name || !*p_target_name) |
||
645 | { |
||
646 | if (p_target_name) free(p_target_name); |
||
647 | p_target_name = NULL; |
||
648 | chkio_fprintf(stderr, OutName, "%s\n", getmessage(Num_ErrMsgTargMissing)); |
||
649 | exit(1); |
||
650 | } |
||
651 | |||
652 | strmaxcpy(TargName, p_target_name, STRINGSIZE); |
||
653 | if (!RemoveOffset(TargName, &Dummy)) |
||
654 | { |
||
655 | strmaxcpy(TargName, p_target_name, STRINGSIZE); |
||
656 | free(p_target_name); p_target_name = NULL; |
||
657 | ParamError(False, TargName); |
||
658 | } |
||
659 | |||
660 | /* special case: only one argument <name> treated like <name>.p -> <name).bin */ |
||
661 | |||
662 | if (StringListEmpty(cmd_results.file_arg_list)) |
||
663 | { |
||
664 | AddStringListLast(&cmd_results.file_arg_list, p_target_name); |
||
665 | DelSuffix(TargName); |
||
666 | } |
||
667 | AddSuffix(TargName, STRINGSIZE, BinSuffix); |
||
668 | free(p_target_name); p_target_name = NULL; |
||
669 | |||
670 | MaxGran = 1; |
||
671 | if (StartAuto || StopAuto) |
||
672 | { |
||
673 | if (StartAuto) |
||
674 | StartAdr = 0xfffffffful; |
||
675 | if (StopAuto) |
||
676 | StopAdr = 0; |
||
677 | for (p_src_name = GetStringListFirst(cmd_results.file_arg_list, &p_src_run); |
||
678 | p_src_name; p_src_name = GetStringListNext(&p_src_run)) |
||
679 | if (*p_src_name) |
||
680 | ProcessGroup(p_src_name, MeasureFile); |
||
681 | if (StartAdr > StopAdr) |
||
682 | { |
||
683 | chkio_fprintf(stderr, OutName, "%s\n", getmessage(Num_ErrMsgAutoFailed)); |
||
684 | exit(1); |
||
685 | } |
||
686 | if (msg_level >= e_msg_level_normal) |
||
687 | { |
||
688 | printf("%s: 0x%08lX-", getmessage(Num_InfoMessDeducedRange), LoDWord(StartAdr)); |
||
689 | printf("0x%08lX\n", LoDWord(StopAdr)); |
||
690 | } |
||
691 | } |
||
692 | |||
693 | OpenTarget(); |
||
694 | |||
695 | for (p_src_name = GetStringListFirst(cmd_results.file_arg_list, &p_src_run); |
||
696 | p_src_name; p_src_name = GetStringListNext(&p_src_run)) |
||
697 | if (*p_src_name) |
||
698 | ProcessGroup(p_src_name, ProcessFile); |
||
699 | |||
700 | CloseTarget(); |
||
701 | |||
702 | if (AutoErase) |
||
703 | for (p_src_name = GetStringListFirst(cmd_results.file_arg_list, &p_src_run); |
||
704 | p_src_name; p_src_name = GetStringListNext(&p_src_run)) |
||
705 | if (*p_src_name) |
||
706 | ProcessGroup(p_src_name, EraseFile); |
||
707 | |||
708 | ClearStringList(&cmd_results.file_arg_list); |
||
709 | |||
710 | return 0; |
||
711 | } |