1 /* toolutils.c */
2 /*****************************************************************************/
3 /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
4 /* */
5 /* AS-Portierung */
6 /* */
7 /* Unterroutinen fuer die AS-Tools */
8 /* */
9 /*****************************************************************************/
10
11 #include "stdinc.h"
12 #include "endian.h"
13 #include <string.h>
14
15 #include "strutil.h"
16 #include "stringlists.h"
17 #include "cmdarg.h"
18 #include "stdhandl.h"
19 #include "ioerrs.h"
20
21 #include "nls.h"
22 #include "nlmessages.h"
23 #include "tools.rsc"
24
25 #include "toolutils.h"
26
27 #include "version.h"
28
29 /****************************************************************************/
30
31 static Boolean DoFilter;
32 static int FilterCnt;
33 static Byte FilterBytes[100];
34
35 Word FileID = 0x1489; /* Dateiheader Eingabedateien */
36 const char *OutName = "STDOUT"; /* Pseudoname Output */
37
38 static TMsgCat MsgCat;
39
40 const char *SegNames[PCMax + 1] =
41 {
42 "NONE",
43 "CODE",
44 "DATA",
45 "IDATA",
46 "XDATA",
47 "YDATA",
48 "BITDATA",
49 "IO",
50 "REG",
51 "ROMDATA",
52 "EEDATA"
53 };
54
55 /****************************************************************************/
56
WrCopyRight(const char * Msg)57 void WrCopyRight(const char *Msg)
58 {
59 printf("%s\n%s\n", Msg, InfoMessCopyright);
60 }
61
DelSuffix(char * Name)62 void DelSuffix(char *Name)
63 {
64 char *p,*z,*Part;
65
66 p = NULL;
67 for (z = Name; *z != '\0'; z++)
68 if (*z == '\\')
69 p = z;
70 Part = (p != NULL) ? p : Name;
71 Part = strchr(Part, '.');
72 if (Part != NULL)
73 *Part = '\0';
74 }
75
AddSuffix(char * pName,unsigned NameSize,const char * Suff)76 void AddSuffix(char *pName, unsigned NameSize, const char *Suff)
77 {
78 char *p, *z, *Part;
79
80 p = NULL;
81 for (z = pName; *z != '\0'; z++)
82 if (*z == '\\')
83 p = z;
84 Part = (p != NULL) ? p : pName;
85 if (strchr(Part, '.') == NULL)
86 strmaxcat(pName, Suff, NameSize);
87 }
88
FormatError(const char * Name,const char * Detail)89 void FormatError(const char *Name, const char *Detail)
90 {
91 fprintf(stderr, "%s%s%s (%s)\n",
92 catgetmessage(&MsgCat, Num_FormatErr1aMsg),
93 Name,
94 catgetmessage(&MsgCat, Num_FormatErr1bMsg),
95 Detail);
96 fprintf(stderr, "%s\n",
97 catgetmessage(&MsgCat, Num_FormatErr2Msg));
98 exit(3);
99 }
100
ChkIO(const char * Name)101 void ChkIO(const char *Name)
102 {
103 int io;
104
105 io = errno;
106
107 if (io == 0)
108 return;
109
110 fprintf(stderr, "%s%s%s\n",
111 catgetmessage(&MsgCat, Num_IOErrAHeaderMsg),
112 Name,
113 catgetmessage(&MsgCat, Num_IOErrBHeaderMsg));
114
115 fprintf(stderr, "%s.\n", GetErrorMsg(io));
116
117 fprintf(stderr, "%s\n",
118 catgetmessage(&MsgCat, Num_ErrMsgTerminating));
119
120 exit(2);
121 }
122
Granularity(Byte Header,Byte Segment)123 Word Granularity(Byte Header, Byte Segment)
124 {
125 switch (Header)
126 {
127 case 0x09:
128 case 0x76:
129 case 0x7d:
130 return 4;
131 case 0x36: /* MN161x */
132 case 0x70:
133 case 0x71:
134 case 0x72:
135 case 0x74:
136 case 0x75:
137 case 0x77:
138 case 0x12:
139 case 0x6d:
140 return 2;
141 case 0x3b: /* AVR */
142 return (Segment == SegCode) ? 2 : 1;
143 default:
144 return 1;
145 }
146 }
147
ReadRecordHeader(Byte * Header,Byte * CPU,Byte * Segment,Byte * Gran,const char * Name,FILE * f)148 void ReadRecordHeader(Byte *Header, Byte *CPU, Byte* Segment,
149 Byte *Gran, const char *Name, FILE *f)
150 {
151 #ifdef _WIN32
152 /* CygWin B20 seems to mix up the file pointer under certain
153 conditions. Difficult to reproduce, so we reposition it. */
154
155 long pos;
156
157 pos = ftell(f);
158 fflush(f);
159 rewind(f);
160 fseek(f, pos, SEEK_SET);
161 #endif
162
163 if (fread(Header, 1, 1, f) != 1)
164 ChkIO(Name);
165 if ((*Header != FileHeaderEnd) && (*Header != FileHeaderStartAdr))
166 {
167 if ((*Header == FileHeaderDataRec) || (*Header == FileHeaderRDataRec) ||
168 (*Header == FileHeaderRelocRec) || (*Header == FileHeaderRRelocRec))
169 {
170 if (fread(CPU, 1, 1, f) != 1)
171 ChkIO(Name);
172 if (fread(Segment, 1, 1, f) != 1)
173 ChkIO(Name);
174 if (fread(Gran, 1, 1, f) != 1)
175 ChkIO(Name);
176 }
177 else if (*Header <= 0x7f)
178 {
179 *CPU = *Header;
180 *Header = FileHeaderDataRec;
181 *Segment = SegCode;
182 *Gran = Granularity(*CPU, *Segment);
183 }
184 }
185 }
186
WriteRecordHeader(Byte * Header,Byte * CPU,Byte * Segment,Byte * Gran,const char * Name,FILE * f)187 void WriteRecordHeader(Byte *Header, Byte *CPU, Byte *Segment,
188 Byte *Gran, const char *Name, FILE *f)
189 {
190 if ((*Header == FileHeaderEnd) || (*Header == FileHeaderStartAdr))
191 {
192 if (fwrite(Header, 1, 1, f) != 1)
193 ChkIO(Name);
194 }
195 else if ((*Header == FileHeaderDataRec) || (*Header == FileHeaderRDataRec))
196 {
197 if ((*Segment != SegCode) || (*Gran != Granularity(*CPU, *Segment)) || (*CPU >= 0x80))
198 {
199 if (fwrite(Header, 1, 1, f))
200 ChkIO(Name);
201 if (fwrite(CPU, 1, 1, f))
202 ChkIO(Name);
203 if (fwrite(Segment, 1, 1, f))
204 ChkIO(Name);
205 if (fwrite(Gran, 1, 1, f))
206 ChkIO(Name);
207 }
208 else
209 {
210 if (fwrite(CPU, 1, 1, f))
211 ChkIO(Name);
212 }
213 }
214 else
215 {
216 if (fwrite(CPU, 1, 1, f))
217 ChkIO(Name);
218 }
219 }
220
SkipRecord(Byte Header,const char * Name,FILE * f)221 void SkipRecord(Byte Header, const char *Name, FILE *f)
222 {
223 int Length;
224 LongWord Addr, RelocCount, ExportCount, StringLen;
225 Word Len;
226
227 switch (Header)
228 {
229 case FileHeaderStartAdr:
230 Length = 4;
231 break;
232 case FileHeaderEnd:
233 Length = 0;
234 break;
235 case FileHeaderRelocInfo:
236 if (!Read4(f, &RelocCount))
237 ChkIO(Name);
238 if (!Read4(f, &ExportCount))
239 ChkIO(Name);
240 if (!Read4(f, &StringLen))
241 ChkIO(Name);
242 Length = (16 * RelocCount) + (16 * ExportCount) + StringLen;
243 break;
244 default:
245 if (!Read4(f, &Addr))
246 ChkIO(Name);
247 if (!Read2(f, &Len))
248 ChkIO(Name);
249 Length = Len;
250 break;
251 }
252
253 if (fseek(f, Length, SEEK_CUR) != 0) ChkIO(Name);
254 }
255
ReadRelocInfo(FILE * f)256 PRelocInfo ReadRelocInfo(FILE *f)
257 {
258 PRelocInfo PInfo;
259 PRelocEntry PEntry;
260 PExportEntry PExp;
261 Boolean OK = FALSE;
262 LongWord StringLen, StringPos;
263 LongInt z;
264
265 /* get memory for structure */
266
267 PInfo = (PRelocInfo) malloc(sizeof(TRelocInfo));
268 if (PInfo != NULL)
269 {
270 PInfo->RelocEntries = NULL;
271 PInfo->ExportEntries = NULL;
272 PInfo->Strings = NULL;
273
274 /* read global numbers */
275
276 if ((Read4(f, &PInfo->RelocCount))
277 && (Read4(f, &PInfo->ExportCount))
278 && (Read4(f, &StringLen)))
279 {
280 /* allocate memory */
281
282 PInfo->RelocEntries = (PRelocEntry) malloc(sizeof(TRelocEntry) * PInfo->RelocCount);
283 if ((PInfo->RelocCount == 0) || (PInfo->RelocEntries != NULL))
284 {
285 PInfo->ExportEntries = (PExportEntry) malloc(sizeof(TExportEntry) * PInfo->ExportCount);
286 if ((PInfo->ExportCount == 0) || (PInfo->ExportEntries != NULL))
287 {
288 PInfo->Strings = (char*) malloc(sizeof(char) * StringLen);
289 if ((StringLen == 0) || (PInfo->Strings != NULL))
290 {
291 /* read relocation entries */
292
293 for (z = 0, PEntry = PInfo->RelocEntries; z < PInfo->RelocCount; z++, PEntry++)
294 {
295 if (!Read8(f, &PEntry->Addr))
296 break;
297 if (!Read4(f, &StringPos))
298 break;
299 PEntry->Name = PInfo->Strings + StringPos;
300 if (!Read4(f, &PEntry->Type))
301 break;
302 }
303
304 /* read export entries */
305
306 for (z = 0, PExp = PInfo->ExportEntries; z < PInfo->ExportCount; z++, PExp++)
307 {
308 if (!Read4(f, &StringPos))
309 break;
310 PExp->Name = PInfo->Strings + StringPos;
311 if (!Read4(f, &PExp->Flags))
312 break;
313 if (!Read8(f, &PExp->Value))
314 break;
315 }
316
317 /* read strings */
318
319 if (z == PInfo->ExportCount)
320 OK = ((fread(PInfo->Strings, 1, StringLen, f)) == StringLen);
321 }
322 }
323 }
324 }
325 }
326
327 if (!OK)
328 {
329 if (PInfo != NULL)
330 {
331 DestroyRelocInfo(PInfo);
332 PInfo = NULL;
333 }
334 }
335
336 return PInfo;
337 }
338
DestroyRelocInfo(PRelocInfo PInfo)339 void DestroyRelocInfo(PRelocInfo PInfo)
340 {
341 if (PInfo->Strings != NULL)
342 {
343 free(PInfo->Strings);
344 PInfo->Strings = NULL;
345 }
346 if ((PInfo->ExportCount > 0) && (PInfo->RelocEntries != NULL))
347 {
348 free(PInfo->RelocEntries);
349 PInfo->RelocEntries = NULL;
350 }
351 if ((PInfo->RelocCount > 0) && (PInfo->ExportEntries != NULL))
352 {
353 free(PInfo->ExportEntries);
354 PInfo->ExportEntries = NULL;
355 }
356 free (PInfo);
357 }
358
CMD_FilterList(Boolean Negate,const char * Arg)359 CMDResult CMD_FilterList(Boolean Negate, const char *Arg)
360 {
361 Byte FTemp;
362 Boolean err;
363 char *p;
364 int Search;
365 String Copy;
366
367 if (*Arg == '\0')
368 return CMDErr;
369 strmaxcpy(Copy, Arg, STRINGSIZE);
370
371 do
372 {
373 p = strchr(Copy,',');
374 if (p != NULL)
375 *p = '\0';
376 FTemp = ConstLongInt(Copy, &err, 10);
377 if (!err)
378 return CMDErr;
379
380 for (Search = 0; Search < FilterCnt; Search++)
381 if (FilterBytes[Search] == FTemp)
382 break;
383
384 if ((Negate) && (Search < FilterCnt))
385 FilterBytes[Search] = FilterBytes[--FilterCnt];
386
387 else if ((!Negate) && (Search >= FilterCnt))
388 FilterBytes[FilterCnt++] = FTemp;
389
390 if (p != NULL)
391 strmov(Copy, p + 1);
392 }
393 while (p != NULL);
394
395 DoFilter = (FilterCnt != 0);
396
397 return CMDArg;
398 }
399
CMD_Range(LongWord * pStartAddr,LongWord * pStopAddr,Boolean * pStartAuto,Boolean * pStopAuto,const char * Arg)400 extern CMDResult CMD_Range(LongWord *pStartAddr, LongWord *pStopAddr,
401 Boolean *pStartAuto, Boolean *pStopAuto,
402 const char *Arg)
403 {
404 const char *p;
405 String StartStr;
406 Boolean ok;
407
408 p = strchr(Arg, '-');
409 if (!p) return CMDErr;
410
411 strmemcpy(StartStr, sizeof(StartStr), Arg, p - Arg);
412 *pStartAuto = AddressWildcard(StartStr);
413 if (*pStartAuto)
414 ok = True;
415 else
416 *pStartAddr = ConstLongInt(StartStr, &ok, 10);
417 if (!ok)
418 return CMDErr;
419
420 *pStopAuto = AddressWildcard(p + 1);
421 if (*pStopAuto)
422 ok = True;
423 else
424 *pStopAddr = ConstLongInt(p + 1, &ok, 10);
425 if (!ok)
426 return CMDErr;
427
428 if (!*pStartAuto && !*pStopAuto && (*pStartAddr > *pStopAddr))
429 return CMDErr;
430
431 return CMDArg;
432 }
433
FilterOK(Byte Header)434 Boolean FilterOK(Byte Header)
435 {
436 int z;
437
438 if (DoFilter)
439 {
440 for (z = 0; z < FilterCnt; z++)
441 if (Header == FilterBytes[z])
442 return True;
443 return False;
444 }
445 else
446 return True;
447 }
448
RemoveOffset(char * Name,LongWord * Offset)449 Boolean RemoveOffset(char *Name, LongWord *Offset)
450 {
451 int z, Nest;
452 Boolean err;
453
454 *Offset = 0;
455 if ((*Name) && (Name[strlen(Name)-1] == ')'))
456 {
457 z = strlen(Name) - 2;
458 Nest = 0;
459 while ((z >= 0) && (Nest >= 0))
460 {
461 switch (Name[z])
462 {
463 case '(': Nest--; break;
464 case ')': Nest++; break;
465 }
466 if (Nest != -1)
467 z--;
468 }
469 if (Nest != -1)
470 return False;
471 else
472 {
473 Name[strlen(Name) - 1] = '\0';
474 *Offset = ConstLongInt(Name + z + 1, &err, 10);
475 Name[z] = '\0';
476 return err;
477 }
478 }
479 else
480 return True;
481 }
482
EraseFile(const char * FileName,LongWord Offset)483 void EraseFile(const char *FileName, LongWord Offset)
484 {
485 UNUSED(Offset);
486
487 if (unlink(FileName) == -1)
488 ChkIO(FileName);
489 }
490
toolutils_init(const char * ProgPath)491 void toolutils_init(const char *ProgPath)
492 {
493 version_init();
494
495 opencatalog(&MsgCat, "tools.msg", ProgPath, MsgId1, MsgId2);
496
497 FilterCnt = 0;
498 DoFilter = False;
499 }
500
AddressWildcard(const char * addr)501 Boolean AddressWildcard(const char *addr)
502 {
503 return ((strcmp(addr, "$") == 0) || (as_strcasecmp(addr, "0x") == 0));
504 }
505
506 #ifdef CKMALLOC
507 #undef malloc
508 #undef realloc
509
ckmalloc(size_t s)510 void *ckmalloc(size_t s)
511 {
512 void *tmp = malloc(s);
513 if (tmp == NULL)
514 {
515 fprintf(stderr,"allocation error(malloc): out of memory");
516 exit(255);
517 }
518 return tmp;
519 }
520
ckrealloc(void * p,size_t s)521 void *ckrealloc(void *p, size_t s)
522 {
523 void *tmp = realloc(p,s);
524 if (tmp == NULL)
525 {
526 fprintf(stderr,"allocation error(realloc): out of memory");
527 exit(255);
528 }
529 return tmp;
530 }
531 #endif
532
WrError(Word Num)533 void WrError(Word Num)
534 {
535 UNUSED(Num);
536 }
537