home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / SIMTEL / CPMUG / CPMUG052.ARK / VARBATCH.3 < prev    next >
Text File  |  1984-04-29  |  10KB  |  351 lines

  1. $This file constitutes the 3rd module of program BATCH.
  2.  
  3. SHOW  ^;  $'Start of the installation module
  4.  
  5. DEF  SizeOfModel        = AfterModel - Model;
  6. SHOW  SizeOfModel;
  7.  
  8. DEF  CPMPerformFunction        = #0005;
  9. DEF  CPMDefaultFCB        = #005C;
  10. DEF  CPMDefaultTextBuf        = #0080;
  11. DEF  SectorSize            = #80;
  12. DEF  AfterCPMDefaultTextBuf    = CPMDefaultTextBuf + SectorSize;
  13.  
  14. $CP/M system functions
  15. DEF  CPMTypeOut            = 2;
  16. DEF  CPMOpen            = 15;
  17. DEF  CPMClose            = 16;
  18. DEF  CPMRead            = 20;
  19.  
  20. MACRO  CPMSystemCall;
  21. C <-  `P(1);
  22. ASM IF  `CHARS =|=`P(2)=|= ~= 0;
  23. DE <-  `P(2);
  24. END ASMIF;
  25. CALL  CPMPerformFunction;
  26. END MACRO;
  27.  
  28. MACRO  TypeOutMessage;
  29. HL <-  ^ + 9;
  30. CALL  TypeOutLine;
  31. GO.  ^ + `CHARS =|=`P(1)=|= + 2;
  32. BYTE  `P(1), TextTerminator;
  33. END MACRO;
  34.  
  35. MACRO  Error,Message<-;
  36. Type Out Message  `P(1);
  37. GO.  WarmBoot;
  38. END MACRO;
  39.  
  40. :CRLF                BYTE  CarriageReturn, LineFeed;
  41.                 BYTE  TextTerminator;
  42.  
  43. :EndOfFileWasFound        BYTE  FALSE;
  44.  
  45. :FileInputCursor        WORD  AfterCPMDefaultTextBuf;
  46.                     $Addr. of next char. to input
  47.                     $from the batch text file,
  48.                     $initialized to force reading of
  49.                     $the 1st sector of the file
  50.  
  51. :RelocationValue        WORD  NoInitialValue;
  52.  
  53. :GO_BATCH_CONST            GO.  BatchCONST;
  54. :GO_BATCH_CONIN            GO.  BatchCONIN;
  55. :AFTER_GO_BATCH 
  56.  
  57. :TypeOutString 
  58.    PROCEDURE;
  59.       .HL -> A;  ? << A -  TextTerminator;  IF = EXIT;
  60.       HL\/;
  61.       A -> E;
  62.       CPM System Call  CPMTypeOut;
  63.       /\HL;  HL + 1 -> HL;
  64.       REPEAT;
  65.    END PROCEDURE;
  66.  
  67. :TypeOutCRLF 
  68.    PROCEDURE;
  69.       HL <-  CRLF;  CALL  TypeOutString;
  70.    END PROCEDURE;
  71.  
  72. :TypeOutLine 
  73.    PROCEDURE;
  74.       HL\/;
  75.       CALL  TypeOutCRLF;
  76.       /\HL;  CALL  TypeOutString;
  77.    END PROCEDURE;
  78.  
  79. :OpenBatchTextFile 
  80.    PROCEDURE;
  81.       $Verify the file name
  82.       A <- .  CPMDefaultFCB + 1;  ? << A -  " ";
  83.       IF = THEN;
  84.      Error, Message <-  "WHAT FILE?";
  85.       END IF;
  86.       A <- .  CPMDefaultFCB + 9;  ? << A -  " ";
  87.       IF = THEN;
  88.      $Use the default file name extension
  89.      HL <-  "AB";  HL -> .  CPMDefaultFCB + 9;
  90.      A <-  "T";  A -> .  CPMDefaultFCB + 11;
  91.       END IF;
  92.       CPM System Call  CPMOpen, CPMDefaultFCB;
  93.       A + 1 -> A;            $Test the return code
  94.       IF 0 THEN;
  95.      Error, Message <-  "NO FILE";
  96.       END IF;
  97.    END PROCEDURE;
  98.  
  99. :CloseBatchTextFile 
  100.    PROCEDURE;
  101.       CPM System Call  CPMClose, CPMDefaultFCB;
  102.       A + 1 -> A;            $Test the return code
  103.       IF 0 THEN;
  104.      Error, Message <-  "ERR CLOSING FILE";
  105.       END IF;
  106.    END PROCEDURE;
  107.  
  108. :Read1SectorOfBatchTextFile 
  109.    PROCEDURE;
  110.       CPM System Call  CPMRead, CPMDefaultFCB;
  111.       A -> .  EndOfFileWasFound;
  112.    END PROCEDURE;
  113.  
  114. :Input1CharFromBatchTextFile 
  115.    PROCEDURE;
  116.       HL <- .  FileInputCursor;
  117.       $Test if past the end of the buffer by comparing addresses
  118.       IF;
  119.      L -> A;  ? << A -  >< AfterCPMDefaultTextBuf;
  120.       IS = AND;
  121.      H -> A;  ? << A -  <> AfterCPMDefaultTextBuf;
  122.       IS = THEN;
  123.      CALL  Read1SectorOfBatchTextFile;
  124.      HL <-  CPMDefaultTextBuf;
  125.      ? << A <- .  EndOfFileWasFound;
  126.      IF ~0 THEN;
  127.         .HL <-  Substitute;
  128.      END IF;
  129.       END IF;
  130.       .HL -> A;
  131.       HL + 1 -> HL;  HL -> .  FileInputCursor;
  132.    END PROCEDURE;
  133.  
  134. :RelocateAddressesInTheModel 
  135.    PROCEDURE;
  136.       HL <-  Model;  DE <-  MODEL;
  137.       DO;
  138.      .DE -> A;  A - .HL -> A;
  139.      IF ~= THEN;
  140.         $Verify that this is the 1st byte of a word that must be
  141.         $relocated
  142.         A?\/;
  143.         ? << A -  >< (MODEL - Model);
  144.         IF ~= THEN;
  145.            Error, Message <-  "CODE MODELS DO NOT CORRESPOND";
  146.         END IF;
  147.         HL + 1 -> HL;  DE + 1 -> DE;
  148.         /\A?;
  149.         .DE -> A;  A - .HL - CY -> A;  ? << A -  <> (MODEL - Model);
  150.         IF ~= THEN;
  151.            HL -> .  DiagnosticInfo;  HL <-> DE;
  152.           HL -> .  DiagnosticInfo + 2;
  153.            Error, Message <-  "1-BYTE RELOC ADDR PROHIBITED";
  154.         END IF;
  155.         $Perform relocation
  156.         DE\/;  HL\/;
  157.         .HL -> D;  HL - 1 -> HL;  .HL -> E;
  158.                     $Original addr. from Model ->
  159.                     $DE
  160.         HL <- .  RelocationValue;  HL + DE -> HL;  HL <-> DE;
  161.                     $Relocated addr. -> DE
  162.         /\HL;
  163.         D -> .HL;  HL - 1 -> HL;  E -> .HL;  HL + 1 -> HL;
  164.         /\DE;
  165.      END IF;
  166.      HL + 1 -> HL;  DE + 1 -> DE;
  167.      $Test if done by comparing addresses
  168.      L -> A;  ? << A -  >< AfterModel;  IF ~= REPEAT;
  169.      H -> A;  ? << A -  <> AfterModel;  IF ~= REPEAT;
  170.       END DO;
  171.    END PROCEDURE;
  172.  
  173. :CopyModelToSafeMemory 
  174.    PROCEDURE;
  175.       HL <- .  SafeMemory;
  176.       DE <-  Model;
  177.       DO;
  178.      .DE -> A;  A -> .HL;
  179.      HL + 1 -> HL;  DE + 1 -> DE;
  180.      $Test if done by comparing addresses
  181.      E -> A;  ? << A -  >< AfterModel;  IF ~= REPEAT;
  182.      D -> A;  ? << A -  <> AfterModel;  IF ~= REPEAT;
  183.       END DO;
  184.    END PROCEDURE;
  185.  
  186. :CopyCharToSafeMemory 
  187.    PROCEDURE;
  188.       A -> D;                $Copy the char.
  189.       $Verify that there is at least 1 available byte remaining in safe
  190.       $memory
  191.       IF;
  192.      L -> A;  A - C >> ?;
  193.       IS = AND;
  194.      H -> A;  A - B >> ?;
  195.       IS = THEN;
  196.      Error, Message <-  "BATCH TEXT TOO LONG";
  197.       END IF;
  198.       D -> .HL;                $Copy the char. into safe
  199.                     $memory
  200.       HL + 1 -> HL;
  201.    END PROCEDURE;
  202.  
  203. :CopyTextToSafeMemory 
  204.    PROCEDURE;
  205.       HL <- .  AfterSafeMemory;  H -> B;  L -> C;
  206.                     $1st addr. after end of safe
  207.                     $memory -> BC
  208.       HL <- .  SafeMemory;  DE <-  SizeOfModel;  HL + DE -> HL;
  209.                     $Destination addr. of text ->
  210.                     $HL
  211.       DO;
  212.      HL\/;  BC\/;
  213.      CALL  Input1CharFromBatchTextFile;
  214.      HL <-  Escape;  A - .HL >> ?;
  215.      IF = THEN;
  216.         CALL  Input1CharFromBatchTextFile;
  217.         ? << A -  "C";
  218.         IF = THEN;
  219.            $This is the start of a comment to the batch processor
  220.            DO;
  221.           CALL  Input1CharFromBatchTextFile;
  222.           HL <-  Escape;  A - .HL >> ?;  IF = EXIT;
  223.           ? << A -  Substitute;  IF = EXIT;
  224.           A -> E;  CPM System Call  CPMTypeOut;
  225.           REPEAT;
  226.            END DO;
  227.         ELSE;
  228.            $Regenerate and copy the escape char.
  229.            A -> H;            $Char. following escape
  230.            /\BC;  HL <-> .SP;
  231.            A <- .  Escape;  CALL  CopyCharToSafeMemory;
  232.            HL <-> .SP;  BC\/;
  233.            H -> A;            $Char. following escape
  234.         END IF;
  235.      END IF;
  236.      /\BC;  /\HL;
  237.      ? << A -  CarriageReturn;
  238.      IF = THEN;
  239.         CALL  CopyCharToSafeMemory;
  240.         $Delete any possible following LineFeed
  241.         HL\/;  BC\/;
  242.         CALL  Input1CharFromBatchTextFile;
  243.         /\BC;  /\HL;
  244.         ? << A -  LineFeed;  IF = REPEAT;
  245.      END IF;
  246.      ? << A -  Substitute;
  247.      IF = THEN;
  248.         A <- .  Escape;  CALL  CopyCharToSafeMemory;
  249.         A <-  FileTerminator;  CALL  CopyCharToSafeMemory;
  250.         HL\/;            $1st addr. after end of batch
  251.                     $text
  252.         DE <-  AfterBatchText;  HL <- .  RelocationValue;
  253.            HL + DE -> HL;
  254.         /\DE;  E -> .HL;  HL + 1 -> HL;  D -> .HL;
  255.                     $1st addr. after end of batch
  256.                     $text
  257.         EXIT;
  258.      END IF;
  259.      CALL  CopyCharToSafeMemory;
  260.      REPEAT;
  261.       END DO;
  262.    END PROCEDURE;
  263.  
  264. :CopyOriginalJMPVectorToModel 
  265.    PROCEDURE;
  266.       HL <- .  AdrOf_JMP_WBOOT;  HL + 1 -> HL;  HL + 1 -> HL;
  267.      HL + 1 -> HL;  HL -> .  AdrOf_JMP_CONST;
  268.       DE <-  GO_OriginalCONST;
  269.       B <-  AfterGO_Original - GO_OriginalCONST;
  270.       DO;
  271.      .HL -> A;  A -> . DE;
  272.      HL + 1 -> HL;  DE + 1 -> DE;
  273.      B - 1 -> B;  IF ~0 REPEAT;
  274.       END DO;
  275.    END PROCEDURE;
  276.  
  277. $Verify that the batch program is not calling itself recursively.  The
  278. $detection method is to test whether the original CONST address is the
  279. $same as the address of the batch version of CONST.
  280. :VerifyLackOfRecursion 
  281.    PROCEDURE;
  282.       DE <-  BatchCONST;  HL <- .  RelocationValue;  HL + DE -> HL;
  283.      HL <-> DE;            $Relocated addr. of BatchCONST
  284.                     $ -> DE
  285.       HL <- .  GO_OriginalCONST + 1;
  286.       IF;
  287.      D -> A;  A - H >> ?;
  288.       IS = AND;
  289.      E -> A;  A - L >> ?;
  290.       IS = THEN;
  291.      Error, Message <-  "BATCH MUST NOT CALL ITSELF";
  292.       END IF;
  293.    END PROCEDURE;
  294.  
  295. :InstateBatchProcessing 
  296.    PROCEDURE;
  297.       HL <- .  AdrOf_JMP_CONST;  DE <-  GO_BATCH_CONST;
  298.       B <-  AFTER_GO_BATCH - GO_BATCH_CONST;
  299.       DO;
  300.      .DE -> A;  A -> .HL;
  301.      HL + 1 -> HL;  DE + 1 -> DE;
  302.      B - 1 -> B;  IF ~0 REPEAT;
  303.       END DO;
  304.    END PROCEDURE;
  305.  
  306. :Main                    $*** Not a procedure ***
  307.    CALL  OpenBatchTextFile;
  308.    CALL  YourPatchProc;
  309.    HL <- .  SizeOfSafeMemory;  HL <-> DE;  HL <- .  SafeMemory;
  310.       HL + DE -> HL;  HL -> .  AfterSafeMemory;
  311.       HL -> .  AFTERSAFEMEMORY;
  312.    HL <- .  SafeMemory;  DE <-  - Model;  HL + DE -> HL;
  313.       HL -> .  RelocationValue;  HL <-> DE;
  314.    HL <- .  GO_BATCH_CONST + 1;  HL + DE -> HL;
  315.       HL -> .  GO_BATCH_CONST + 1;
  316.    HL <- .  GO_BATCH_CONIN + 1;  HL + DE -> HL;
  317.       HL -> .  GO_BATCH_CONIN + 1;
  318.    CALL  RelocateAddressesInTheModel;
  319.    CALL  CopyOriginalJMPVectorToModel;
  320.    CALL  VerifyLackOfRecursion;
  321.    CALL  CopyModelToSafeMemory;
  322.    CALL  CopyTextToSafeMemory;
  323.    CALL  CloseBatchTextFile;
  324.    CALL  InstateBatchProcessing;
  325.    GO.  WarmBoot;
  326.  
  327. $You may assemble or patch in the code here, to store the correct values
  328. $into variables SafeMemory and SizeOfSafeMemory.
  329. :YourPatchProc 
  330.    PROCEDURE;
  331.       $This procedure may expand as necessary, to accommodate your code.
  332.       $The existing code in this procedure may be discarded.  It is
  333.       $peculiar to the version of CP/M and the BIOS used by the author
  334.       $of this program.
  335.       $*************************
  336.       $SafeMemory starts after the end of BIOS.
  337.       HL <- .  CPMPerformFunction + 1;  DE <-  #10C0;  HL + DE -> HL;
  338.      HL -> .  SafeMemory;
  339.       $SafeMemory extends up to the 2nd 1K boundary of address space.
  340.       L -> A;  ~A -> A;  A -> L;
  341.       H -> A;  ~A -> A;  A <- A &  #03;  A -> H;
  342.       HL + 1 -> HL;
  343.       DE <-  #0400;  HL + DE -> HL;
  344.       HL -> .  SizeOfSafeMemory;
  345. $The following values override the values calculated above.  The over-
  346. $riding values are used only for testing and demonstration.
  347. HL<-  #3000;HL->.  SafeMemory;HL<-  #800;HL->.  SizeOfSafeMemory;$******
  348.    END PROCEDURE;
  349.  
  350. :ZZZ    END  Start;
  351.