Subversion Repositories pentevo

Rev

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

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