Subversion Repositories pentevo

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

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