Subversion Repositories pentevo

Rev

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

  1. /* p2hex.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Konvertierung von AS-P-Dateien nach Hex                                   */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12. #include <ctype.h>
  13. #include <string.h>
  14.  
  15. #include "version.h"
  16. #include "be_le.h"
  17. #include "bpemu.h"
  18. #include "nls.h"
  19. #include "nlmessages.h"
  20. #include "p2hex.rsc"
  21. #ifdef _USE_MSH
  22. # include "p2hex.msh"
  23. #endif
  24. #include "ioerrs.h"
  25. #include "strutil.h"
  26. #include "chunks.h"
  27. #include "stringlists.h"
  28. #include "msg_level.h"
  29. #include "cmdarg.h"
  30.  
  31. #include "toolutils.h"
  32. #include "headids.h"
  33.  
  34. static const char *HexSuffix = ".hex";
  35. #define MaxLineLen 254
  36. #define AVRLEN_DEFAULT 3
  37. #define DefaultCFormat "dSEl"
  38.  
  39. typedef void (*ProcessProc)(
  40. #ifdef __PROTOS__
  41. const char *FileName, LongWord Offset
  42. #endif
  43. );
  44.  
  45. static FILE *TargFile;
  46. static String TargName, CFormat;
  47. static Byte ForceSegment;
  48.  
  49. static LongWord StartAdr[SegCount], StopAdr[SegCount], LineLen, EntryAdr;
  50. static LargeInt Relocate;
  51. static Boolean StartAuto, StopAuto, AutoErase, EntryAdrPresent;
  52. static Word Seg, Ofs;
  53. static LongWord Dummy;
  54. static Byte IntelMode;
  55. static Byte MultiMode;   /* 0=8M, 1=16, 2=8L, 3=8H */
  56. static Byte MinMoto;
  57. static Boolean Rec5;
  58. static Boolean SepMoto;
  59. static LongWord AVRLen;
  60.  
  61. static Boolean RelAdr;
  62.  
  63. static unsigned FormatOccured;
  64. enum
  65. {
  66.   eMotoOccured = (1 << 0),
  67.   eIntelOccured = (1 << 1),
  68.   eMOSOccured = (1 << 2),
  69.   eDSKOccured = (1 << 3),
  70.   eMico8Occured = (1 << 4)
  71. };
  72. static Byte MaxMoto, MaxIntel;
  73.  
  74. static tHexFormat DestFormat;
  75.  
  76. static ChunkList UsedList;
  77.  
  78. static String CTargName;
  79. static unsigned NumCBlocks;
  80.  
  81. static void DefStartStopAdr(LongWord SegMask)
  82. {
  83.   Byte Seg;
  84.  
  85.   for (Seg = 0; Seg < SegCount; Seg++)
  86.     if (SegMask & (1 << Seg))
  87.     {
  88.       StartAdr[Seg] = 0;
  89.       StopAdr[Seg] = (Seg == SegData) ? 0x1fff : 0x7fff;
  90.     }
  91. }
  92.  
  93. static void Filename2CName(char *pDest, const char *pSrc)
  94. {
  95.   char Trans;
  96.   const char *pPos;
  97.   Boolean Written = False;
  98.  
  99.   pPos = strrchr(pSrc, PATHSEP);
  100. #ifdef DRSEP
  101.   if (!pPos)
  102.     pPos = strchr(pSrc, DRSEP);
  103. #endif
  104.   if (pPos)
  105.     pSrc = pPos + 1;
  106.  
  107.   for (; *pSrc; pSrc++)
  108.   {
  109.     Trans = (*pSrc == '-') ? '_' : *pSrc;
  110.     if (isalnum(*pSrc) || (*pSrc == '_'))
  111.     {
  112.       *pDest++ = Trans;
  113.       Written = True;
  114.     }
  115.     else if (Written)
  116.       break;
  117.   }
  118.   *pDest = '\0';
  119. }
  120.  
  121. static void GetCBlockName(char *pDest, size_t DestSize, unsigned Num)
  122. {
  123.   if (Num > 0)
  124.     as_snprintf(pDest, DestSize, "_%u", Num + 1);
  125.   else
  126.     *pDest = '\0';
  127. }
  128.  
  129. static void ParamError(Boolean InEnv, char *Arg)
  130. {
  131.    fprintf(stderr, "%s%s\n", getmessage(InEnv ? Num_ErrMsgInvEnvParam : Num_ErrMsgInvParam), Arg);
  132.    fprintf(stderr, "%s\n", getmessage(Num_ErrMsgProgTerm));
  133. }
  134.  
  135. static void OpenTarget(void)
  136. {
  137.   TargFile = fopen(TargName, "w");
  138.   if (!TargFile)
  139.     ChkIO(TargName);
  140. }
  141.  
  142. static void CloseTarget(void)
  143. {
  144.   errno = 0;
  145.   fclose(TargFile);
  146.   ChkIO(TargName);
  147.   if (Magic != 0)
  148.     unlink(TargName);
  149. }
  150.  
  151. static void PrCData(FILE *pTargFile, char Ident, const char *pName,
  152.                     const char *pCTargName, const char *pCBlockName, LongWord Value)
  153. {
  154.   const char *pFormat;
  155.  
  156.   if (strchr(CFormat, toupper(Ident)))
  157.     pFormat = "ul";
  158.   else if (strchr(CFormat, tolower(Ident)))
  159.     pFormat = "u";
  160.   else
  161.     return;
  162.  
  163.   errno = 0;
  164.   fprintf(pTargFile, "#define %s%s_%s 0x%08lX%s\n",
  165.           pCTargName, pCBlockName, pName,
  166.           LoDWord(Value), pFormat);
  167.   ChkIO(TargName);
  168. }
  169.  
  170. static void ProcessFile(const char *FileName, LongWord Offset)
  171. {
  172.   FILE *SrcFile;
  173.   Word TestID;
  174.   Byte InpHeader, InpCPU, InpSegment, InpGran;
  175.   LongWord InpStart, SumLen;
  176.   Word InpLen, TransLen;
  177.   Boolean doit, FirstBank = 0;
  178.   Boolean CDataLower = !!strchr(CFormat, 'd'),
  179.           CDataUpper = !!strchr(CFormat, 'D');
  180.   Byte Buffer[MaxLineLen];
  181.   Word *WBuffer = (Word *) Buffer;
  182.   LongWord ErgStart,
  183.            ErgStop = 0xfffffffful,
  184.            IntOffset = 0, MaxAdr;
  185.   LongInt NextPos;
  186.   LongWord ValidSegs;
  187.   Word ErgLen = 0, ChkSum = 0, RecCnt, Gran, HSeg;
  188.   String CBlockName;
  189.  
  190.   LongInt z;
  191.  
  192.   Byte MotRecType = 0;
  193.  
  194.   tHexFormat ActFormat;
  195.   const TFamilyDescr *FoundDscr;
  196.  
  197.   SrcFile = fopen(FileName, OPENRDMODE);
  198.   if (!SrcFile) ChkIO(FileName);
  199.  
  200.   if (!Read2(SrcFile, &TestID))
  201.     chk_wr_read_error(FileName);
  202.   if (TestID !=FileMagic)
  203.     FormatError(FileName, getmessage(Num_FormatInvHeaderMsg));
  204.  
  205.   if (msg_level >= e_msg_level_normal)
  206.   {
  207.     errno = 0; printf("%s==>>%s", FileName, TargName); ChkIO(OutName);
  208.   }
  209.  
  210.   SumLen = 0;
  211.  
  212.   do
  213.   {
  214.     ReadRecordHeader(&InpHeader, &InpCPU, &InpSegment, &InpGran, FileName, SrcFile);
  215.  
  216.     if (InpHeader == FileHeaderStartAdr)
  217.     {
  218.       if (!Read4(SrcFile, &ErgStart))
  219.         chk_wr_read_error(FileName);
  220.       if (!EntryAdrPresent)
  221.       {
  222.         EntryAdr = ErgStart;
  223.         EntryAdrPresent = True;
  224.       }
  225.     }
  226.  
  227.     else if (InpHeader == FileHeaderDataRec)
  228.     {
  229.       Gran = InpGran;
  230.  
  231.       if ((ActFormat = DestFormat) == eHexFormatDefault)
  232.       {
  233.         FoundDscr = FindFamilyById(InpCPU);
  234.         if (!FoundDscr)
  235.           FormatError(FileName, getmessage(Num_FormatInvRecordHeaderMsg));
  236.         else
  237.           ActFormat = FoundDscr->HexFormat;
  238.       }
  239.  
  240.       if (ForceSegment != SegNone)
  241.         ValidSegs = (1 << ForceSegment);
  242.       else
  243.       {
  244.         ValidSegs = (1 << SegCode);
  245.         if (eHexFormatTiDSK == ActFormat)
  246.           ValidSegs |= (1 << SegData);
  247.       }
  248.  
  249.       switch (ActFormat)
  250.       {
  251.         case eHexFormatMotoS:
  252.         case eHexFormatIntel32:
  253.         case eHexFormatC:
  254.           MaxAdr = 0xfffffffful;
  255.           break;
  256.         case eHexFormatIntel16:
  257.           MaxAdr = 0xffff0ul + 0xffffu;
  258.           break;
  259.         case eHexFormatAtmel:
  260.           MaxAdr = (1 << (AVRLen << 3)) - 1;
  261.           break;
  262.         case eHexFormatMico8:
  263.           MaxAdr = 0xfffffffful;
  264.           break;
  265.         default:
  266.           MaxAdr = 0xffffu;
  267.       }
  268.  
  269.       if (!Read4(SrcFile, &InpStart))
  270.         chk_wr_read_error(FileName);
  271.       if (!Read2(SrcFile, &InpLen))
  272.         chk_wr_read_error(FileName);
  273.  
  274.       NextPos = ftell(SrcFile) + InpLen;
  275.       if (NextPos >= FileSize(SrcFile) - 1)
  276.         FormatError(FileName, getmessage(Num_FormatInvRecordLenMsg));
  277.  
  278.       doit = FilterOK(InpCPU) && (ValidSegs & (1 << InpSegment));
  279.  
  280.       if (doit)
  281.       {
  282.         InpStart += Offset;
  283.         ErgStart = max(StartAdr[InpSegment], InpStart);
  284.         ErgStop = min(StopAdr[InpSegment], InpStart + (InpLen/Gran) - 1);
  285.         doit = (ErgStop >= ErgStart);
  286.         if (doit)
  287.         {
  288.           ErgLen = (ErgStop + 1 - ErgStart) * Gran;
  289.           if (AddChunk(&UsedList, ErgStart, ErgStop - ErgStart + 1, True))
  290.           {
  291.             errno = 0; fprintf(stderr, " %s\n", getmessage(Num_ErrMsgOverlap)); ChkIO(OutName);
  292.           }
  293.         }
  294.       }
  295.  
  296.       if (doit && (ErgStop > MaxAdr))
  297.       {
  298.         errno = 0; fprintf(stderr, " %s\n", getmessage(Num_ErrMsgAdrOverflow)); ChkIO(OutName);
  299.       }
  300.  
  301.       if (doit)
  302.       {
  303.         /* an Anfang interessierender Daten */
  304.  
  305.         if (fseek(SrcFile, (ErgStart - InpStart) * Gran, SEEK_CUR) == -1)
  306.           ChkIO(FileName);
  307.  
  308.         /* Statistik, Anzahl Datenzeilen ausrechnen */
  309.  
  310.         RecCnt = ErgLen / LineLen;
  311.         if ((ErgLen % LineLen) !=0)
  312.           RecCnt++;
  313.  
  314.         /* relative Angaben ? */
  315.  
  316.         if (RelAdr)
  317.           ErgStart -= StartAdr[InpSegment];
  318.  
  319.         /* Auf Zieladressbereich verschieben */
  320.  
  321.         ErgStart += Relocate;
  322.  
  323.         /* Kopf einer Datenzeilengruppe */
  324.  
  325.         switch (ActFormat)
  326.         {
  327.           case eHexFormatMotoS:
  328.             if ((!(FormatOccured & eMotoOccured)) || (SepMoto))
  329.             {
  330.               errno = 0; fprintf(TargFile, "S0030000FC\n"); ChkIO(TargName);
  331.             }
  332.             if ((ErgStop >> 24) != 0)
  333.               MotRecType = 2;
  334.             else if ((ErgStop >> 16) !=0)
  335.               MotRecType = 1;
  336.             else
  337.               MotRecType = 0;
  338.             if (MotRecType < (MinMoto - 1))
  339.               MotRecType = (MinMoto - 1);
  340.             if (MaxMoto < MotRecType)
  341.               MaxMoto = MotRecType;
  342.             if (Rec5)
  343.             {
  344.               ChkSum = Lo(RecCnt) + Hi(RecCnt) + 3;
  345.               errno = 0;
  346.               fprintf(TargFile, "S503%04X%02X\n", LoWord(RecCnt), Lo(ChkSum ^ 0xff));
  347.               ChkIO(TargName);
  348.             }
  349.             FormatOccured |= eMotoOccured;
  350.             break;
  351.           case eHexFormatMOS:
  352.             FormatOccured |= eMOSOccured;
  353.             break;
  354.           case eHexFormatIntel:
  355.             FormatOccured |= eIntelOccured;
  356.             IntOffset = 0;
  357.             break;
  358.           case eHexFormatIntel16:
  359.             FormatOccured |= eIntelOccured;
  360.             IntOffset = (ErgStart * Gran);
  361.             IntOffset -= IntOffset & 0x0f;
  362.             HSeg = IntOffset >> 4;
  363.             ChkSum = 4 + Lo(HSeg) + Hi(HSeg);
  364.             IntOffset /= Gran;
  365.             errno = 0; fprintf(TargFile, ":02000002%04X%02X\n", LoWord(HSeg), Lo(0x100 - ChkSum)); ChkIO(TargName);
  366.             if (MaxIntel < 1)
  367.               MaxIntel = 1;
  368.             break;
  369.           case eHexFormatIntel32:
  370.             FormatOccured |= eIntelOccured;
  371.             IntOffset = (ErgStart * Gran);
  372.             IntOffset -= IntOffset & 0xffff;
  373.             HSeg = IntOffset >> 16;
  374.             ChkSum = 6 + Lo(HSeg) + Hi(HSeg);
  375.             IntOffset /= Gran;
  376.             errno = 0; fprintf(TargFile, ":02000004%04X%02X\n", LoWord(HSeg), Lo(0x100 - ChkSum)); ChkIO(TargName);
  377.             if (MaxIntel < 2)
  378.               MaxIntel = 2;
  379.             FirstBank = False;
  380.             break;
  381.           case eHexFormatTek:
  382.             break;
  383.           case eHexFormatAtmel:
  384.             break;
  385.           case eHexFormatMico8:
  386.             break;
  387.           case eHexFormatTiDSK:
  388.             if (!(FormatOccured & eDSKOccured))
  389.             {
  390.               FormatOccured |= eDSKOccured;
  391.               errno = 0; fprintf(TargFile, "%s%s\n", getmessage(Num_DSKHeaderLine), TargName); ChkIO(TargName);
  392.             }
  393.             break;
  394.           case eHexFormatC:
  395.             GetCBlockName(CBlockName, sizeof(CBlockName), NumCBlocks);
  396.             PrCData(TargFile, 's', "start", CTargName, CBlockName, ErgStart);
  397.             PrCData(TargFile, 'l', "len", CTargName, CBlockName, ErgLen);
  398.             PrCData(TargFile, 'e', "end", CTargName, CBlockName, ErgStart + ErgLen - 1);
  399.             if (CDataLower || CDataUpper)
  400.             {
  401.               errno = 0;
  402.               fprintf(TargFile, "static const unsigned char %s%s_data[] =\n{\n",
  403.                       CTargName, CBlockName);
  404.               ChkIO(TargName);
  405.             }
  406.             break;
  407.           default:
  408.             break;
  409.         }
  410.  
  411.         /* Datenzeilen selber */
  412.  
  413.         while (ErgLen > 0)
  414.         {
  415.           /* evtl. Folgebank fuer Intel32 ausgeben */
  416.  
  417.           if ((ActFormat == eHexFormatIntel32) && (FirstBank))
  418.           {
  419.             IntOffset += (0x10000 / Gran);
  420.             HSeg = IntOffset >> 16;
  421.             ChkSum = 6 + Lo(HSeg) + Hi(HSeg);
  422.             errno = 0;
  423.             fprintf(TargFile, ":02000004%04X%02X\n", LoWord(HSeg), Lo(0x100 - ChkSum));
  424.             ChkIO(TargName);
  425.             FirstBank = False;
  426.           }
  427.  
  428.           /* Recordlaenge ausrechnen, fuer Intel32 auf 64K-Grenze begrenzen
  429.              Bei Atmel nur 2 Byte pro Zeile!
  430.              Bei Mico8 nur 4 Byte (davon ein Wort=18 Bit) pro Zeile! */
  431.  
  432.           TransLen = min(LineLen, ErgLen);
  433.           if ((ActFormat == eHexFormatIntel32) && ((ErgStart & 0xffff) + (TransLen/Gran) >= 0x10000))
  434.           {
  435.             TransLen = Gran * (0x10000 - (ErgStart & 0xffff));
  436.             FirstBank = True;
  437.           }
  438.           else if (ActFormat == eHexFormatAtmel)
  439.             TransLen = min(2, TransLen);
  440.           else if (ActFormat == eHexFormatMico8)
  441.             TransLen = min(4, TransLen);
  442.  
  443.           /* Start der Datenzeile */
  444.  
  445.           switch (ActFormat)
  446.           {
  447.             case eHexFormatMotoS:
  448.               errno = 0;
  449.               fprintf(TargFile, "S%c%02X", '1' + MotRecType, Lo(TransLen + 3 + MotRecType));
  450.               ChkIO(TargName);
  451.               ChkSum = TransLen + 3 + MotRecType;
  452.               if (MotRecType >= 2)
  453.               {
  454.                 errno = 0; fprintf(TargFile, "%02X", Lo(ErgStart >> 24)); ChkIO(TargName);
  455.                 ChkSum += ((ErgStart >> 24) & 0xff);
  456.               }
  457.               if (MotRecType >= 1)
  458.               {
  459.                 errno = 0; fprintf(TargFile, "%02X", Lo(ErgStart >> 16)); ChkIO(TargName);
  460.                 ChkSum += ((ErgStart >> 16) & 0xff);
  461.               }
  462.               errno = 0; fprintf(TargFile, "%04X", LoWord(ErgStart)); ChkIO(TargName);
  463.               ChkSum += Hi(ErgStart) + Lo(ErgStart);
  464.               break;
  465.             case eHexFormatMOS:
  466.               errno = 0; fprintf(TargFile, ";%02X%04X", Lo(TransLen), LoWord(ErgStart)); ChkIO(TargName);
  467.               ChkSum += TransLen + Lo(ErgStart) + Hi(ErgStart);
  468.               break;
  469.             case eHexFormatIntel:
  470.             case eHexFormatIntel16:
  471.             case eHexFormatIntel32:
  472.             {
  473.               Word WrTransLen;
  474.               LongWord WrErgStart;
  475.  
  476.               WrTransLen = (MultiMode < 2) ? TransLen : (TransLen / Gran);
  477.               WrErgStart = (ErgStart - IntOffset) * ((MultiMode < 2) ? Gran : 1);
  478.               errno = 0;
  479.               fprintf(TargFile, ":%02X%04X00", Lo(WrTransLen), LoWord(WrErgStart));
  480.               ChkIO(TargName);
  481.               ChkSum = Lo(WrTransLen) + Hi(WrErgStart) + Lo(WrErgStart);
  482.  
  483.               break;
  484.             }
  485.             case eHexFormatTek:
  486.               errno = 0;
  487.               fprintf(TargFile, "/%04X%02X%02X", LoWord(ErgStart), Lo(TransLen),
  488.                                          Lo(Lo(ErgStart) + Hi(ErgStart) + TransLen));
  489.               ChkIO(TargName);
  490.               ChkSum = 0;
  491.               break;
  492.             case eHexFormatTiDSK:
  493.               errno = 0; fprintf(TargFile, "9%04X", LoWord(/*Gran**/ErgStart));
  494.               ChkIO(TargName);
  495.               ChkSum = 0;
  496.               break;
  497.             case eHexFormatAtmel:
  498.               for (z = (AVRLen - 1) << 3; z >= 0; z -= 8)
  499.               {
  500.                 errno = 0;
  501.                 fprintf(TargFile, "%02X", Lo(ErgStart >> z));
  502.                 ChkIO(TargName);
  503.               }
  504.               errno = 0;
  505.               fputc(':', TargFile);
  506.               ChkIO(TargName);
  507.               break;
  508.             case eHexFormatMico8:
  509.               break;
  510.             case eHexFormatC:
  511.               errno = 0;
  512.               fprintf(TargFile, "  ");
  513.               ChkIO(TargName);
  514.               break;
  515.             default:
  516.               break;
  517.           }
  518.  
  519.           /* Daten selber */
  520.  
  521.           if (fread(Buffer, 1, TransLen, SrcFile) !=TransLen)
  522.             chk_wr_read_error(FileName);
  523.           if (MultiMode == 1)
  524.             switch (Gran)
  525.             {
  526.               case 4:
  527.                 DSwap(Buffer, TransLen);
  528.                 break;
  529.               case 2:
  530.                 WSwap(Buffer, TransLen);
  531.                 break;
  532.               case 1:
  533.                 break;
  534.             }
  535.           switch (ActFormat)
  536.           {
  537.             case eHexFormatTiDSK:
  538.               if (HostBigEndian)
  539.                 WSwap(WBuffer, TransLen);
  540.               for (z = 0; z < (TransLen / 2); z++)
  541.               {
  542.                 errno = 0;
  543.                 if (((ErgStart + z >= StartAdr[SegData]) && (ErgStart + z <= StopAdr[SegData]))
  544.                  || (InpSegment == SegData))
  545.                   fprintf(TargFile, "M%04X", LoWord(WBuffer[z]));
  546.                 else
  547.                   fprintf(TargFile, "B%04X", LoWord(WBuffer[z]));
  548.                 ChkIO(TargName);
  549.                 ChkSum += WBuffer[z];
  550.                 SumLen += Gran;
  551.               }
  552.               break;
  553.             case eHexFormatAtmel:
  554.               if (TransLen >= 2)
  555.               {
  556.                 fprintf(TargFile, "%04X", LoWord(WBuffer[0]));
  557.                 SumLen += 2;
  558.               }
  559.               else if (TransLen >= 1)
  560.               {
  561.                 fprintf(TargFile, "%04X", Lo(WBuffer[0]));
  562.                 SumLen++;
  563.               }
  564.               break;
  565.             case eHexFormatMico8:
  566.               if (TransLen >= 4)
  567.               {
  568.                 fprintf(TargFile, "%01X%02X%02X", Buffer[1] & 0x0f, Buffer[2] % 0xff, Buffer[3] & 0xff);
  569.                 SumLen += 4;
  570.               }
  571.               break;
  572.             case eHexFormatC:
  573.               if (CDataLower || CDataUpper)
  574.                 for (z = 0; z < (LongInt)TransLen; z++)
  575.                   if ((MultiMode < 2) || (z % Gran == MultiMode - 2))
  576.                   {
  577.                     errno = 0;
  578.                     fprintf(TargFile, CDataLower ? "0x%02x%s" : "0x%02X%s", (unsigned)Buffer[z],
  579.                             (ErgLen - z > 1) ? "," : "");
  580.                     ChkIO(TargName);
  581.                     ChkSum += Buffer[z];
  582.                     SumLen++;
  583.                   }
  584.               break;
  585.             default:
  586.               for (z = 0; z < (LongInt)TransLen; z++)
  587.                 if ((MultiMode < 2) || (z % Gran == MultiMode - 2))
  588.                 {
  589.                   errno = 0; fprintf(TargFile, "%02X", Lo(Buffer[z])); ChkIO(TargName);
  590.                   ChkSum += Buffer[z];
  591.                   SumLen++;
  592.                 }
  593.           }
  594.  
  595.           /* Ende Datenzeile */
  596.  
  597.           switch (ActFormat)
  598.           {
  599.             case eHexFormatMotoS:
  600.               errno = 0;
  601.               fprintf(TargFile, "%02X\n", Lo(ChkSum ^ 0xff));
  602.               ChkIO(TargName);
  603.               break;
  604.             case eHexFormatMOS:
  605.               errno = 0;
  606.               fprintf(TargFile, "%04X\n", LoWord(ChkSum));
  607.               break;
  608.             case eHexFormatIntel:
  609.             case eHexFormatIntel16:
  610.             case eHexFormatIntel32:
  611.               errno = 0;
  612.               fprintf(TargFile, "%02X\n", Lo(1 + (ChkSum ^ 0xff)));
  613.               ChkIO(TargName);
  614.               break;
  615.             case eHexFormatTek:
  616.               errno = 0;
  617.               fprintf(TargFile, "%02X\n", Lo(ChkSum));
  618.               ChkIO(TargName);
  619.               break;
  620.             case eHexFormatTiDSK:
  621.               errno = 0;
  622.               fprintf(TargFile, "7%04XF\n", LoWord(ChkSum));
  623.               ChkIO(TargName);
  624.               break;
  625.             case eHexFormatAtmel:
  626.             case eHexFormatMico8:
  627.             case eHexFormatC:
  628.               errno = 0;
  629.               fprintf(TargFile, "\n");
  630.               ChkIO(TargName);
  631.               break;
  632.             default:
  633.               break;
  634.           }
  635.  
  636.           /* Zaehler rauf */
  637.  
  638.           ErgLen -= TransLen;
  639.           ErgStart += TransLen/Gran;
  640.         }
  641.  
  642.         /* Ende der Datenzeilengruppe */
  643.  
  644.         switch (ActFormat)
  645.         {
  646.           case eHexFormatMotoS:
  647.             if (SepMoto)
  648.             {
  649.               errno = 0;
  650.               fprintf(TargFile, "S%c%02X", '9' - MotRecType, Lo(3 + MotRecType));
  651.               ChkIO(TargName);
  652.               for (z = 1; z <= 2 + MotRecType; z++)
  653.               {
  654.                 errno = 0; fprintf(TargFile, "%02X", 0); ChkIO(TargName);
  655.               }
  656.               errno = 0;
  657.               fprintf(TargFile, "%02X\n", Lo(0xff - 3 - MotRecType));
  658.               ChkIO(TargName);
  659.             }
  660.             break;
  661.           case eHexFormatMOS:
  662.             break;
  663.           case eHexFormatIntel:
  664.           case eHexFormatIntel16:
  665.           case eHexFormatIntel32:
  666.             break;
  667.           case eHexFormatTek:
  668.             break;
  669.           case eHexFormatTiDSK:
  670.             break;
  671.           case eHexFormatAtmel:
  672.             break;
  673.           case eHexFormatMico8:
  674.             break;
  675.           case eHexFormatC:
  676.             if (CDataLower || CDataUpper)
  677.             {
  678.               errno = 0;
  679.               fprintf(TargFile, "};\n\n");
  680.               NumCBlocks++;
  681.               ChkIO(TargName);
  682.             }
  683.             break;
  684.           default:
  685.             break;
  686.         };
  687.       }
  688.       if (fseek(SrcFile, NextPos, SEEK_SET) == -1)
  689.         ChkIO(FileName);
  690.     }
  691.     else
  692.       SkipRecord(InpHeader, FileName, SrcFile);
  693.   }
  694.   while (InpHeader !=0);
  695.  
  696.   if (msg_level >= e_msg_level_normal)
  697.   {
  698.     errno = 0; printf(" ("); ChkIO(OutName);
  699.     errno = 0; printf(Integ32Format, SumLen); ChkIO(OutName);
  700.     errno = 0; printf(" %s)\n", getmessage((SumLen == 1) ? Num_Byte : Num_Bytes)); ChkIO(OutName);
  701.   }
  702.   if (!SumLen)
  703.   {
  704.     errno = 0; fputs(getmessage(Num_WarnEmptyFile), stderr); ChkIO(OutName);
  705.   }
  706.  
  707.   errno = 0;
  708.   fclose(SrcFile);
  709.   ChkIO(FileName);
  710. }
  711.  
  712. static ProcessProc CurrProcessor;
  713. static LongWord CurrOffset;
  714.  
  715. static void Callback(char *Name)
  716. {
  717.   CurrProcessor(Name, CurrOffset);
  718. }
  719.  
  720. static void ProcessGroup(const char *GroupName_O, ProcessProc Processor)
  721. {
  722.   String Ext, GroupName;
  723.  
  724.   CurrProcessor = Processor;
  725.   strmaxcpy(GroupName, GroupName_O, STRINGSIZE);
  726.   strmaxcpy(Ext, GroupName, STRINGSIZE);
  727.   if (!RemoveOffset(GroupName, &CurrOffset))
  728.   {
  729.     ParamError(False, Ext);
  730.     exit(1);
  731.   }
  732.   AddSuffix(GroupName, STRINGSIZE, getmessage(Num_Suffix));
  733.  
  734.   if (!DirScan(GroupName, Callback))
  735.     fprintf(stderr, "%s%s%s\n", getmessage(Num_ErrMsgNullMaskA), GroupName, getmessage(Num_ErrMsgNullMaskB));
  736. }
  737.  
  738. static void MeasureFile(const char *FileName, LongWord Offset)
  739. {
  740.   FILE *f;
  741.   Byte Header, InpCPU, InpSegment, Gran;
  742.   Word Length, TestID;
  743.   LongWord Adr, EndAdr;
  744.   LongInt NextPos;
  745.   LongWord ValidSegs;
  746.   Boolean doit;
  747.  
  748.   f = fopen(FileName, OPENRDMODE);
  749.   if (!f)
  750.     ChkIO(FileName);
  751.  
  752.   if (!Read2(f, &TestID))
  753.     chk_wr_read_error(FileName);
  754.   if (TestID !=FileMagic)
  755.     FormatError(FileName, getmessage(Num_FormatInvHeaderMsg));
  756.  
  757.   do
  758.   {
  759.     ReadRecordHeader(&Header, &InpCPU, &InpSegment, &Gran, FileName, f);
  760.  
  761.     if (Header == FileHeaderDataRec)
  762.     {
  763.       if (!Read4(f, &Adr))
  764.         chk_wr_read_error(FileName);
  765.       if (!Read2(f, &Length))
  766.         chk_wr_read_error(FileName);
  767.       NextPos = ftell(f) + Length;
  768.       if (NextPos > FileSize(f))
  769.         FormatError(FileName, getmessage(Num_FormatInvRecordLenMsg));
  770.  
  771.       if (ForceSegment != SegNone)
  772.         ValidSegs = (1 << ForceSegment);
  773.       else
  774.         ValidSegs = (1 << SegCode) | (1 << SegData);
  775.  
  776.       doit = FilterOK(InpCPU) && (ValidSegs & (1 << InpSegment));
  777.  
  778.       if (doit)
  779.       {
  780.         Adr += Offset;
  781.         EndAdr = Adr + (Length/Gran) - 1;
  782.         if (StartAuto)
  783.           if (StartAdr[InpSegment] > Adr)
  784.             StartAdr[InpSegment] = Adr;
  785.         if (StopAuto)
  786.           if (EndAdr > StopAdr[InpSegment])
  787.             StopAdr[InpSegment] = EndAdr;
  788.       }
  789.  
  790.       fseek(f, NextPos, SEEK_SET);
  791.     }
  792.     else
  793.      SkipRecord(Header, FileName, f);
  794.   }
  795.   while(Header !=0);
  796.  
  797.   fclose(f);
  798. }
  799.  
  800. /* ------------------------------------------- */
  801.  
  802. static as_cmd_result_t CMD_AdrRange(Boolean Negate, const char *Arg)
  803. {
  804.   if (Negate)
  805.   {
  806.     DefStartStopAdr(1 << SegCode);
  807.     return e_cmd_ok;
  808.   }
  809.   else
  810.     return CMD_Range(&StartAdr[SegCode], &StopAdr[SegCode],
  811.                      &StartAuto, &StopAuto, Arg);
  812. }
  813.  
  814. static as_cmd_result_t CMD_RelAdr(Boolean Negate, const char *Arg)
  815. {
  816.   UNUSED(Arg);
  817.  
  818.   RelAdr = (!Negate);
  819.   return e_cmd_ok;
  820. }
  821.  
  822. static as_cmd_result_t CMD_AdrRelocate(Boolean Negate, const char *Arg)
  823. {
  824.   Boolean ok;
  825.   UNUSED(Arg);
  826.  
  827.   if (Negate)
  828.   {
  829.     Relocate = 0;
  830.     return e_cmd_ok;
  831.   }
  832.   else
  833.   {
  834.     Relocate = ConstLongInt(Arg, &ok, 10);
  835.     if (!ok) return e_cmd_err;
  836.  
  837.     return e_cmd_arg;
  838.   }
  839. }
  840.  
  841. static as_cmd_result_t CMD_Rec5(Boolean Negate, const char *Arg)
  842. {
  843.   UNUSED(Arg);
  844.  
  845.   Rec5 = (!Negate);
  846.   return e_cmd_ok;
  847. }
  848.  
  849. static as_cmd_result_t CMD_SepMoto(Boolean Negate, const char *Arg)
  850. {
  851.   UNUSED(Arg);
  852.  
  853.   SepMoto = !Negate;
  854.   return e_cmd_ok;
  855. }
  856.  
  857. static as_cmd_result_t CMD_IntelMode(Boolean Negate, const char *Arg)
  858. {
  859.   int Mode;
  860.   Boolean ok;
  861.  
  862.   if (*Arg == '\0')
  863.     return e_cmd_err;
  864.   else
  865.   {
  866.     Mode = ConstLongInt(Arg, &ok, 10);
  867.     if ((!ok) || (Mode < 0) || (Mode > 2))
  868.       return e_cmd_err;
  869.     else
  870.     {
  871.       if (!Negate)
  872.         IntelMode = Mode;
  873.       else if (IntelMode == Mode)
  874.         IntelMode = 0;
  875.       return e_cmd_arg;
  876.     }
  877.   }
  878. }
  879.  
  880. static as_cmd_result_t CMD_MultiMode(Boolean Negate, const char *Arg)
  881. {
  882.   int Mode;
  883.   Boolean ok;
  884.  
  885.   if (*Arg == '\0')
  886.     return e_cmd_err;
  887.   else
  888.   {
  889.     Mode = ConstLongInt(Arg, &ok, 10);
  890.     if ((!ok) || (Mode < 0) || (Mode > 3))
  891.       return e_cmd_err;
  892.     else
  893.     {
  894.       if (!Negate)
  895.         MultiMode = Mode;
  896.       else if (MultiMode == Mode)
  897.         MultiMode = 0;
  898.       return e_cmd_arg;
  899.     }
  900.   }
  901. }
  902.  
  903. static as_cmd_result_t CMD_DestFormat(Boolean Negate, const char *pArg)
  904. {
  905. #define NameCnt (sizeof(Names) / sizeof(*Names))
  906.  
  907.   static const char *Names[] =
  908.   {
  909.     "DEFAULT", "MOTO", "INTEL", "INTEL16", "INTEL32", "MOS", "TEK", "DSK", "ATMEL", "MICO8", "C"
  910.   };
  911.   static tHexFormat Format[] =
  912.   {
  913.     eHexFormatDefault, eHexFormatMotoS, eHexFormatIntel, eHexFormatIntel16,
  914.     eHexFormatIntel32, eHexFormatMOS, eHexFormatTek, eHexFormatTiDSK,
  915.     eHexFormatAtmel, eHexFormatMico8, eHexFormatC
  916.   };
  917.   unsigned z;
  918.   String Arg;
  919.  
  920.   strmaxcpy(Arg, pArg, STRINGSIZE);
  921.   NLS_UpString(Arg);
  922.  
  923.   z = 0;
  924.   while ((z < NameCnt) && (strcmp(Arg, Names[z])))
  925.     z++;
  926.   if (z >= NameCnt)
  927.     return e_cmd_err;
  928.  
  929.   if (!Negate)
  930.     DestFormat = Format[z];
  931.   else if (DestFormat == Format[z])
  932.     DestFormat = eHexFormatDefault;
  933.  
  934.   return e_cmd_arg;
  935. }
  936.  
  937. static as_cmd_result_t CMD_ForceSegment(Boolean Negate,  const char *Arg)
  938. {
  939.   int z = addrspace_lookup(Arg);
  940.  
  941.   if (z >= SegCount)
  942.     return e_cmd_err;
  943.  
  944.   if (!Negate)
  945.     ForceSegment = z;
  946.   else if (ForceSegment == z)
  947.     ForceSegment = SegNone;
  948.  
  949.   return e_cmd_arg;
  950. }
  951.  
  952. static as_cmd_result_t CMD_DataAdrRange(Boolean Negate,  const char *Arg)
  953. {
  954.   fputs(getmessage(Num_WarnDOption), stderr);
  955.   fflush(stdout);
  956.  
  957.   if (Negate)
  958.   {
  959.     DefStartStopAdr(1 << SegData);
  960.     return e_cmd_ok;
  961.   }
  962.   else
  963.   {
  964.     Boolean StartDataAuto, StopDataAuto;
  965.     as_cmd_result_t Ret = CMD_Range(&StartAdr[SegData], &StopAdr[SegData],
  966.                               &StartDataAuto, &StopDataAuto, Arg);
  967.  
  968.     if (StartDataAuto || StopDataAuto)
  969.       Ret = e_cmd_err;
  970.     return Ret;
  971.   }
  972. }
  973.  
  974. static as_cmd_result_t CMD_EntryAdr(Boolean Negate, const char *Arg)
  975. {
  976.   Boolean ok;
  977.  
  978.   if (Negate)
  979.   {
  980.     EntryAdrPresent = False;
  981.     return e_cmd_ok;
  982.   }
  983.   else
  984.   {
  985.     EntryAdr = ConstLongInt(Arg, &ok, 10);
  986.     if ((!ok) || (EntryAdr > 0xffff))
  987.       return e_cmd_err;
  988.     EntryAdrPresent = True;
  989.     return e_cmd_arg;
  990.   }
  991. }
  992.  
  993. static as_cmd_result_t CMD_LineLen(Boolean Negate, const char *Arg)
  994. {
  995.   Boolean ok;
  996.  
  997.   if (Negate)
  998.   {
  999.     if (*Arg !='\0')
  1000.       return e_cmd_err;
  1001.     else
  1002.     {
  1003.       LineLen = 16;
  1004.       return e_cmd_ok;
  1005.     }
  1006.   }
  1007.   else if (*Arg == '\0')
  1008.     return e_cmd_err;
  1009.   else
  1010.   {
  1011.     LineLen = ConstLongInt(Arg, &ok, 10);
  1012.     if ((!ok) || (LineLen < 1) || (LineLen > MaxLineLen))
  1013.       return e_cmd_err;
  1014.     else
  1015.     {
  1016.       LineLen += LineLen & 1;
  1017.       return e_cmd_arg;
  1018.     }
  1019.   }
  1020. }
  1021.  
  1022. static as_cmd_result_t CMD_MinMoto(Boolean Negate, const char *Arg)
  1023. {
  1024.   Boolean ok;
  1025.  
  1026.   if (Negate)
  1027.   {
  1028.     if (*Arg != '\0')
  1029.       return e_cmd_err;
  1030.     else
  1031.     {
  1032.       MinMoto = 0;
  1033.       return e_cmd_ok;
  1034.     }
  1035.   }
  1036.   else if (*Arg == '\0')
  1037.     return e_cmd_err;
  1038.   else
  1039.   {
  1040.     MinMoto = ConstLongInt(Arg, &ok, 10);
  1041.     if ((!ok) || (MinMoto < 1) || (MinMoto > 3))
  1042.       return e_cmd_err;
  1043.     else
  1044.       return e_cmd_arg;
  1045.   }
  1046. }
  1047.  
  1048. static as_cmd_result_t CMD_AutoErase(Boolean Negate, const char *Arg)
  1049. {
  1050.   UNUSED(Arg);
  1051.  
  1052.   AutoErase = !Negate;
  1053.   return e_cmd_ok;
  1054. }
  1055.  
  1056. static as_cmd_result_t CMD_AVRLen(Boolean Negate, const char *Arg)
  1057. {
  1058.   Word Temp;
  1059.   Boolean ok;
  1060.  
  1061.   if (Negate)
  1062.   {
  1063.     AVRLen = AVRLEN_DEFAULT;
  1064.     return e_cmd_ok;
  1065.   }
  1066.   else
  1067.   {
  1068.     Temp = ConstLongInt(Arg, &ok, 10);
  1069.     if ((!ok) || (Temp < 2) || (Temp > 3))
  1070.       return e_cmd_err;
  1071.     else
  1072.     {
  1073.       AVRLen = Temp;
  1074.       return e_cmd_arg;
  1075.     }
  1076.   }
  1077. }
  1078.  
  1079. static as_cmd_result_t CMD_CFormat(Boolean Negate, const char *pArg)
  1080. {
  1081.   if (Negate)
  1082.   {
  1083.     strcpy(CFormat, DefaultCFormat);
  1084.     return e_cmd_ok;
  1085.   }
  1086.   else
  1087.   {
  1088.     int NumData = 0, NumStart = 0, NumLen = 0, NumEnd = 0;
  1089.     const char *pFormat;
  1090.  
  1091.     for (pFormat = pArg; *pFormat; pFormat++)
  1092.       switch (toupper(*pFormat))
  1093.       {
  1094.         case 'S': NumStart++; break;
  1095.         case 'D': NumData++; break;
  1096.         case 'L': NumLen++; break;
  1097.         case 'E': NumEnd++; break;
  1098.         default: return e_cmd_err;
  1099.       }
  1100.     if ((NumData > 1) || (NumStart > 1) || (NumLen > 1) || (NumEnd > 1))
  1101.       return e_cmd_err;
  1102.     strcpy(CFormat, pArg);
  1103.     return e_cmd_arg;
  1104.   }
  1105. }
  1106.  
  1107. static const as_cmd_rec_t P2HEXParams[] =
  1108. {
  1109.   { "f"        , CMD_FilterList },
  1110.   { "r"        , CMD_AdrRange },
  1111.   { "R"        , CMD_AdrRelocate },
  1112.   { "a"        , CMD_RelAdr },
  1113.   { "i"        , CMD_IntelMode },
  1114.   { "m"        , CMD_MultiMode },
  1115.   { "F"        , CMD_DestFormat },
  1116.   { "5"        , CMD_Rec5 },
  1117.   { "s"        , CMD_SepMoto },
  1118.   { "d"        , CMD_DataAdrRange },
  1119.   { "e"        , CMD_EntryAdr },
  1120.   { "l"        , CMD_LineLen },
  1121.   { "k"        , CMD_AutoErase },
  1122.   { "M"        , CMD_MinMoto },
  1123.   { "SEGMENT"  , CMD_ForceSegment },
  1124.   { "AVRLEN"   , CMD_AVRLen },
  1125.   { "CFORMAT"  , CMD_CFormat }
  1126. };
  1127.  
  1128. static Word ChkSum;
  1129.  
  1130. int main(int argc, char **argv)
  1131. {
  1132.   char *p_target_name;
  1133.   const char *p_src_name;
  1134.   as_cmd_results_t cmd_results;
  1135.   StringRecPtr p_src_run;
  1136.  
  1137.   nls_init();
  1138.   if (!NLS_Initialize(&argc, argv))
  1139.     exit(4);
  1140.  
  1141.   be_le_init();
  1142.   bpemu_init();
  1143.   chunks_init();
  1144.   as_cmdarg_init(*argv);
  1145.   msg_level_init();
  1146.   toolutils_init(*argv);
  1147. #ifdef _USE_MSH
  1148.   nlmessages_init_buffer(p2hex_msh_data, sizeof(p2hex_msh_data), MsgId1, MsgId2);
  1149. #else
  1150.   nlmessages_init_file("p2hex.msg", *argv, MsgId1, MsgId2);
  1151. #endif
  1152.   ioerrs_init(*argv);
  1153.  
  1154.   InitChunk(&UsedList);
  1155.  
  1156.   DefStartStopAdr(0xffff);
  1157.   StartAuto = True;
  1158.   StopAuto = True;
  1159.   EntryAdr = -1;
  1160.   EntryAdrPresent = False;
  1161.   AutoErase = False;
  1162.   RelAdr = False;
  1163.   Rec5 = True;
  1164.   LineLen = 16;
  1165.   AVRLen = AVRLEN_DEFAULT;
  1166.   IntelMode = 0;
  1167.   MultiMode = 0;
  1168.   DestFormat = eHexFormatDefault;
  1169.   MinMoto = 1;
  1170.   *TargName = '\0';
  1171.   Relocate = 0;
  1172.   ForceSegment = SegNone;
  1173.   strcpy(CFormat, DefaultCFormat);
  1174.  
  1175.   as_cmd_register(P2HEXParams, as_array_size(P2HEXParams));
  1176.   if (e_cmd_err == as_cmd_process(argc, argv, "P2HEXCMD", &cmd_results))
  1177.   {
  1178.     ParamError(cmd_results.error_arg_in_env, cmd_results.error_arg);
  1179.     exit(1);
  1180.   }
  1181.  
  1182.   if ((msg_level >= e_msg_level_verbose) || cmd_results.write_version_exit)
  1183.   {
  1184.     String Ver;
  1185.  
  1186.     as_snprintf(Ver, sizeof(Ver), "P2HEX V%s", Version);
  1187.     WrCopyRight(Ver);
  1188.   }
  1189.  
  1190.   if (cmd_results.write_help_exit)
  1191.   {
  1192.     char *ph1, *ph2;
  1193.  
  1194.     errno = 0; printf("%s%s%s\n", getmessage(Num_InfoMessHead1), as_cmdarg_get_executable_name(), getmessage(Num_InfoMessHead2)); ChkIO(OutName);
  1195.     for (ph1 = getmessage(Num_InfoMessHelp), ph2 = strchr(ph1, '\n'); ph2; ph1 = ph2 + 1, ph2 = strchr(ph1, '\n'))
  1196.     {
  1197.       *ph2 = '\0';
  1198.       printf("%s\n", ph1);
  1199.       *ph2 = '\n';
  1200.     }
  1201.   }
  1202.  
  1203.   if (cmd_results.write_version_exit || cmd_results.write_help_exit)
  1204.     exit(0);
  1205.  
  1206.   if (StringListEmpty(cmd_results.file_arg_list))
  1207.   {
  1208.     fprintf(stderr, "%s: %s\n", as_cmdarg_get_executable_name(), getmessage(Num_ErrMessNoInputFiles));
  1209.     exit(1);
  1210.   }
  1211.  
  1212.   p_target_name = MoveAndCutStringListLast(&cmd_results.file_arg_list);
  1213.   if (!p_target_name || !*p_target_name)
  1214.   {
  1215.     errno = 0; fprintf(stderr, "%s\n", getmessage(Num_ErrMsgTargMissing)); ChkIO(OutName);
  1216.     if (p_target_name) free(p_target_name);
  1217.     p_target_name = NULL;
  1218.     exit(1);
  1219.   }
  1220.  
  1221.   strmaxcpy(TargName, p_target_name, STRINGSIZE);
  1222.   if (!RemoveOffset(TargName, &Dummy))
  1223.   {
  1224.     strmaxcpy(TargName, p_target_name, STRINGSIZE);
  1225.     free(p_target_name); p_target_name = NULL;
  1226.     ParamError(False, TargName);
  1227.   }
  1228.  
  1229.   /* special case: only one argument <name> treated like <name>.p -> <name).hex */
  1230.  
  1231.   if (StringListEmpty(cmd_results.file_arg_list))
  1232.   {
  1233.     AddStringListLast(&cmd_results.file_arg_list, p_target_name);
  1234.     DelSuffix(TargName);
  1235.   }
  1236.   free(p_target_name); p_target_name = NULL;
  1237.   AddSuffix(TargName, STRINGSIZE, HexSuffix);
  1238.   Filename2CName(CTargName, TargName);
  1239.   NumCBlocks = 0;
  1240.  
  1241.   if (StartAuto || StopAuto)
  1242.   {
  1243.     int z;
  1244.     Byte ChkSegment = ForceSegment ? ForceSegment : (Byte)SegCode;
  1245.  
  1246.     if (StartAuto)
  1247.       for (z = 0; z < SegCount; z++)
  1248.         StartAdr[z] = 0xfffffffful;
  1249.     if (StopAuto)
  1250.       for (z = 0; z < SegCount; z++)
  1251.         StopAdr[z] = 0;
  1252.  
  1253.     for (p_src_name = GetStringListFirst(cmd_results.file_arg_list, &p_src_run);
  1254.          p_src_name; p_src_name = GetStringListNext(&p_src_run))
  1255.       if (*p_src_name)
  1256.         ProcessGroup(p_src_name, MeasureFile);
  1257.  
  1258.     if (StartAdr[ChkSegment] > StopAdr[ChkSegment])
  1259.     {
  1260.       errno = 0;
  1261.       fprintf(stderr, "%s\n", getmessage(Num_ErrMsgAutoFailed));
  1262.       ChkIO(OutName);
  1263.       exit(1);
  1264.     }
  1265.     if (msg_level >= e_msg_level_normal)
  1266.     {
  1267.       printf("%s: 0x%08lX-", getmessage(Num_InfoMessDeducedRange), LoDWord(StartAdr[ChkSegment]));
  1268.       printf("0x%08lX\n", LoDWord(StopAdr[ChkSegment]));
  1269.     }
  1270.   }
  1271.  
  1272.   OpenTarget();
  1273.   FormatOccured = 0;
  1274.   MaxMoto = 0;
  1275.   MaxIntel = 0;
  1276.  
  1277.   if (DestFormat == eHexFormatC)
  1278.   {
  1279.     errno = 0;
  1280.     fprintf(TargFile, "#ifndef _%s_H\n#define _%s_H\n\n", CTargName, CTargName);
  1281.     ChkIO(TargName);
  1282.     NumCBlocks = 0;
  1283.   }
  1284.  
  1285.   for (p_src_name = GetStringListFirst(cmd_results.file_arg_list, &p_src_run);
  1286.        p_src_name; p_src_name = GetStringListNext(&p_src_run))
  1287.     if (*p_src_name)
  1288.       ProcessGroup(p_src_name, ProcessFile);
  1289.  
  1290.   if ((FormatOccured & eMotoOccured) && (!SepMoto))
  1291.   {
  1292.     errno = 0; fprintf(TargFile, "S%c%02X", '9' - MaxMoto, Lo(3 + MaxMoto)); ChkIO(TargName);
  1293.     ChkSum = 3 + MaxMoto;
  1294.     if (!EntryAdrPresent)
  1295.       EntryAdr = 0;
  1296.     if (MaxMoto >= 2)
  1297.     {
  1298.       errno = 0; fprintf(TargFile, "%02X", Lo(EntryAdr >> 24)); ChkIO(TargName);
  1299.       ChkSum += (EntryAdr >> 24) & 0xff;
  1300.     }
  1301.     if (MaxMoto >= 1)
  1302.     {
  1303.       errno = 0; fprintf(TargFile, "%02X", Lo(EntryAdr >> 16)); ChkIO(TargName);
  1304.       ChkSum += (EntryAdr >> 16) & 0xff;
  1305.     }
  1306.     errno = 0; fprintf(TargFile, "%04X", LoWord(EntryAdr & 0xffff)); ChkIO(TargName);
  1307.     ChkSum += (EntryAdr >> 8) & 0xff;
  1308.     ChkSum += EntryAdr & 0xff;
  1309.     errno = 0; fprintf(TargFile, "%02X\n", Lo(0xff - (ChkSum & 0xff))); ChkIO(TargName);
  1310.   }
  1311.  
  1312.   if (FormatOccured & eIntelOccured)
  1313.   {
  1314.     Word EndRecAddr = 0;
  1315.  
  1316.     if (EntryAdrPresent)
  1317.     {
  1318.       switch (MaxIntel)
  1319.       {
  1320.         case 2:
  1321.           errno = 0; fprintf(TargFile, ":04000005"); ChkIO(TargName);
  1322.           ChkSum = 4 + 5;
  1323.           errno = 0; fprintf(TargFile, "%08lX", LoDWord(EntryAdr)); ChkIO(TargName);
  1324.           ChkSum += ((EntryAdr >> 24) & 0xff) +
  1325.                     ((EntryAdr >> 16) & 0xff) +
  1326.                     ((EntryAdr >>  8) & 0xff) +
  1327.                     ( EntryAdr        & 0xff);
  1328.           goto WrChkSum;
  1329.  
  1330.         case 1:
  1331.           Seg = (EntryAdr >> 4) & 0xffff;
  1332.           Ofs = EntryAdr & 0x000f;
  1333.           errno = 0; fprintf(TargFile, ":04000003%04X%04X", LoWord(Seg), LoWord(Ofs)); ChkIO(TargName);
  1334.           ChkSum = 4 + 3 + Lo(Seg) + Hi(Seg) + Ofs;
  1335.           goto WrChkSum;
  1336.  
  1337.         default: /* == 0 */
  1338.           EndRecAddr = EntryAdr & 0xffff;
  1339.           break;
  1340.  
  1341.         WrChkSum:
  1342.           errno = 0; fprintf(TargFile, "%02X\n", Lo(0x100 - ChkSum)); ChkIO(TargName);
  1343.       }
  1344.     }
  1345.     errno = 0;
  1346.     switch (IntelMode)
  1347.     {
  1348.       case 0:
  1349.       {
  1350.         ChkSum = 1 + Hi(EndRecAddr) + Lo(EndRecAddr);
  1351.         fprintf(TargFile, ":00%04X01%02X\n", LoWord(EndRecAddr), Lo(0x100 - ChkSum));
  1352.         break;
  1353.       }
  1354.       case 1:
  1355.         fprintf(TargFile, ":00000001\n");
  1356.         break;
  1357.       case 2:
  1358.         fprintf(TargFile, ":0000000000\n");
  1359.         break;
  1360.     }
  1361.     ChkIO(TargName);
  1362.   }
  1363.  
  1364.   if (FormatOccured & eMOSOccured)
  1365.   {
  1366.     errno = 0; fprintf(TargFile, ";0000040004\n"); ChkIO(TargName);
  1367.   }
  1368.  
  1369.   if (FormatOccured & eDSKOccured)
  1370.   {
  1371.     if (EntryAdrPresent)
  1372.     {
  1373.       errno = 0;
  1374.       fprintf(TargFile, "1%04X7%04XF\n", LoWord(EntryAdr), LoWord(EntryAdr));
  1375.       ChkIO(TargName);
  1376.     }
  1377.     errno = 0; fprintf(TargFile, ":\n"); ChkIO(TargName);
  1378.   }
  1379.  
  1380.   if (DestFormat == eHexFormatC)
  1381.   {
  1382.     unsigned ThisCBlock;
  1383.     String CBlockName;
  1384.     const char *pFormat;
  1385.  
  1386.     errno = 0;
  1387.     fprintf(TargFile,
  1388.             "typedef struct\n"
  1389.             "{\n");
  1390.     for (pFormat = CFormat; *pFormat; pFormat++)
  1391.       switch (*pFormat)
  1392.       {
  1393.         case 'd':
  1394.         case 'D':
  1395.           fprintf(TargFile, "  const char *data;\n"); break;
  1396.         case 's':
  1397.           fprintf(TargFile, "  unsigned start;\n"); break;
  1398.         case 'S':
  1399.           fprintf(TargFile, "  unsigned long start;\n"); break;
  1400.         case 'l':
  1401.           fprintf(TargFile, "  unsigned len;\n"); break;
  1402.         case 'L':
  1403.           fprintf(TargFile, "  unsigned long len;\n"); break;
  1404.         case 'e':
  1405.           fprintf(TargFile, "  unsigned end;\n"); break;
  1406.         case 'E':
  1407.           fprintf(TargFile, "  unsigned long end;\n"); break;
  1408.         default:
  1409.           break;
  1410.       }
  1411.     fprintf(TargFile,
  1412.             "} %s_blk;\n"
  1413.             "static const %s_blk %s_blks[] =\n"
  1414.             "{\n",
  1415.             CTargName, CTargName, CTargName);
  1416.     for (ThisCBlock = 0; ThisCBlock < NumCBlocks; ThisCBlock++)
  1417.     {
  1418.       GetCBlockName(CBlockName, sizeof(CBlockName), ThisCBlock);
  1419.       fprintf(TargFile, "  {");
  1420.       for (pFormat = CFormat; *pFormat; pFormat++)
  1421.       {
  1422.         fprintf(TargFile, (pFormat != CFormat) ? ", " : " ");
  1423.         switch (toupper(*pFormat))
  1424.         {
  1425.           case 'D': fprintf(TargFile, "%s%s_data", CTargName, CBlockName); break;
  1426.           case 'S': fprintf(TargFile, "%s%s_start", CTargName, CBlockName); break;
  1427.           case 'L': fprintf(TargFile, "%s%s_len", CTargName, CBlockName); break;
  1428.           case 'E': fprintf(TargFile, "%s%s_end", CTargName, CBlockName); break;
  1429.           default: break;
  1430.         }
  1431.       }
  1432.       fprintf(TargFile, " },\n");
  1433.     }
  1434.     fprintf(TargFile, "  {");
  1435.     for (pFormat = CFormat; *pFormat; pFormat++)
  1436.       fprintf(TargFile, (pFormat != CFormat) ? ", 0" : " 0");
  1437.     fprintf(TargFile, " }\n"
  1438.                       "};\n\n");
  1439.  
  1440.     if (EntryAdrPresent)
  1441.       fprintf(TargFile, "#define %s_entry 0x%08lXul\n\n",
  1442.               CTargName, LoDWord(EntryAdr));
  1443.     fprintf(TargFile,
  1444.             "#endif /* _%s_H */\n",
  1445.             CTargName);
  1446.     ChkIO(TargName);
  1447.   }
  1448.   CloseTarget();
  1449.  
  1450.   if (AutoErase)
  1451.   {
  1452.     for (p_src_name = GetStringListFirst(cmd_results.file_arg_list, &p_src_run);
  1453.          p_src_name; p_src_name = GetStringListNext(&p_src_run))
  1454.       if (*p_src_name)
  1455.         ProcessGroup(p_src_name, EraseFile);
  1456.   }
  1457.  
  1458.   ClearStringList(&cmd_results.file_arg_list);
  1459.  
  1460.   return 0;
  1461. }
  1462.