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