home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 551.lha / Chop_v0.92 / Chop.mod < prev    next >
Encoding:
Text File  |  1991-09-08  |  15.6 KB  |  587 lines

  1. MODULE Chop;
  2.  
  3. (*
  4.  
  5. Chop v0.92 by Terry Brown, 1991
  6.  
  7. Chop filename [-sn] [-bn] [-cn] [-Bs|-As] [-in] [-Ps] [-p]
  8.  
  9. -sn  skip first n bytes, start from start if omitted
  10. -bn  take only n byte chunks, take remainder of file if omitted
  11. -cn  take only n chunks, take chunks to end of file if omitted
  12. -Bs  after taking -bn bytes, take bytes until string s is reached
  13. -As  after taking -bn bytes, take bytes until end of string s is reached
  14. -in  buffer size n kilobytes, default 40, needs two of them
  15. -Ps  string s is path and file name for output
  16. -p   prompt before writing each file
  17.  
  18. s must conatin no spaces, ? matches anything, and `hh is a hex constant
  19.  
  20. watch for shells which pre-expand wild cards etc.
  21.  
  22. Eg. Chop dh0:bigText -b10000 -B`0A`20 -Pdf0:textBit -p
  23.  
  24. breaks bigText into roughly 10000 byte peices before lines starting with a
  25. space, saving them to df0:textBit.1, df0:textBit.2 etc., and giving you a
  26. chance to change disks before each write.
  27. (`0A`20 is hex for newline + space)
  28.  
  29.  
  30. *)
  31.  
  32.  
  33. FROM CommandLine    IMPORT GetCL,CLStrings;
  34. FROM InOut          IMPORT WriteString,WriteLn;
  35. IMPORT InOut; (* need Read from here and DOSFiles *)
  36. FROM LongInOut      IMPORT WriteLongCard;
  37. FROM Memory         IMPORT AllocMem,FreeMem,MemReqSet;
  38. FROM DOSFiles       IMPORT Open,Close,FileHandle,ModeNewFile,ModeOldFile,
  39.                            Seek,OffsetBeginning,Read,Write,DeleteFile;
  40. FROM Strings        IMPORT Copy,InitStringModule,Concat,CompareResults,
  41.                            Compare,Length,Delete,Insert;
  42. FROM Conversions    IMPORT ConvertFromString,ConvertToString;
  43. FROM SYSTEM         IMPORT ADDRESS,NULL;
  44.  
  45. CONST
  46. maxArgs         = 9;
  47. skpArg          = "-s";
  48. szeArg          = "-b";
  49. cntArg          = "-c";
  50. bfrArg          = "-B";
  51. aftArg          = "-A";
  52. bufArg          = "-i";
  53. preArg          = "-P";
  54. pmtArg          = "-p";
  55.  
  56. multiWild       = "*";
  57. singleWild      = "?";
  58. hexPrecur       = "`";
  59. defaultBuf      = 40*1024;
  60.  
  61. TYPE
  62. states          = (srchI,endI,endN,done,writeI,writeN);
  63.  
  64. VAR
  65. inFile,outFile      : FileHandle;
  66. inFileNm,outFileNm  : CLStrings;
  67. iBuf,nBuf,tBuf,
  68. iStrt,iEnd,
  69. nStrt,nEnd          : ADDRESS;
  70. bufSize,skpSize,
  71. blkSize,blkCount,
  72. blkNum,actRead,
  73. actWrite,curSize    : LONGCARD;
  74. split,before        : BOOLEAN;
  75. splitStr            : CLStrings;
  76. arg                 : ARRAY [1..maxArgs] OF CLStrings;
  77. args                : CARDINAL;
  78. lcard               : LONGCARD;
  79. lint                : LONGINT;
  80. i,j,iOld            : CARDINAL;
  81. bool,more,bufSwt,
  82. killSrch,prompt,
  83. falseMatch          : BOOLEAN;
  84. s                   : CLStrings;
  85. c                   : CHAR;
  86. cPtr,matchStrt      : POINTER TO CHAR;
  87. matchPos            : CARDINAL;
  88. state               : states;
  89.  
  90. PROCEDURE ErrMsg;
  91.  
  92. BEGIN
  93.  
  94. WriteLn;
  95. WriteLn; WriteString("Chop v0.92 by Terry Brown, 1991");
  96. WriteLn;
  97. WriteLn; WriteString("Chop filename [-sn] [-bn] [-cn] [-Bs|-As] [-in] [-Ps] [-p]");
  98. WriteLn;
  99. WriteLn; WriteString("-sn  skip first n bytes, start from start if omitted");
  100. WriteLn; WriteString("-bn  take only n byte chunks, take remainder of file if omitted");
  101. WriteLn; WriteString("-cn  take only n chunks, take chunks to end of file if omitted");
  102. WriteLn; WriteString("-Bs  after taking -bn bytes, take bytes until string s is reached");
  103. WriteLn; WriteString("-As  after taking -bn bytes, take bytes until end of string s is reached");
  104. WriteLn; WriteString("-in  buffer size n kilobytes, default 40, needs two of them");
  105. WriteLn; WriteString("-Ps  string s is path and file name for output");
  106. WriteLn; WriteString("-p   prompt before writing each file");
  107. WriteLn;
  108. WriteLn; WriteString("s must conatin no spaces, ? matches anything, and `hh is a hex constant");
  109. WriteLn;
  110. WriteLn; WriteString("watch for shells which pre-expand wild cards etc.");
  111. WriteLn;
  112. WriteLn; WriteString("Eg. Chop dh0:bigText -b10000 -B`0A`20 -Pdf0:textBit -p");
  113. WriteLn;
  114. WriteLn; WriteString("breaks bigText into roughly 10000 byte peices before lines starting with a");
  115. WriteLn; WriteString("space, saving them to df0:textBit.1, df0:textBit.2 etc., and giving you a");
  116. WriteLn; WriteString("chance to change disks before each write.");
  117. WriteLn; WriteString("(`0A`20 is hex for newline + space)");
  118. WriteLn;
  119. END ErrMsg;
  120.  
  121.  
  122. PROCEDURE begins(a,b : CLStrings) : BOOLEAN;
  123.  
  124. (* return true if string a matches string a begins with string b *)
  125.  
  126. VAR
  127. s : CLStrings; 
  128.  
  129. BEGIN
  130.  
  131.   Copy(a,0,Length(b),s);
  132.   IF Compare(s,b)=Equal THEN 
  133.   RETURN TRUE
  134.   ELSE
  135.   RETURN FALSE
  136.   END;
  137.  
  138. END begins;
  139.  
  140.  
  141. PROCEDURE nextOut(fn : CLStrings; n : LONGCARD) : FileHandle;
  142.  
  143. VAR
  144. done      : BOOLEAN;
  145. s         : CLStrings;
  146. x         : FileHandle;
  147. c         : CHAR;
  148.  
  149. BEGIN
  150.  
  151.   ConvertToString(n,10,FALSE,s,done);
  152.   WHILE Length(s)<3 DO
  153.     Insert("0",s,0);
  154.   END;
  155.   Concat(".",s,s);
  156.   Concat(fn,s,s);
  157.   
  158.   IF prompt THEN
  159.     WriteString("Hit RETURN to write file ");
  160.     WriteString(s);
  161.     InOut.Read(c);
  162.   END;
  163.   
  164.   x:=Open(s,ModeNewFile);
  165.   IF x=0 THEN
  166.     WriteString("Couldn't open output file");
  167.     WriteLn;
  168.   END;  
  169.  
  170.   RETURN x;
  171.  
  172. END nextOut;
  173.  
  174.  
  175. PROCEDURE flush; (* rest of buffer *)
  176.  
  177. BEGIN
  178.  
  179.    actWrite:=Write(outFile,iStrt,LONGCARD(iEnd-iStrt));
  180.    curSize:=curSize+actWrite; (* everything we've got *)
  181.  
  182. END flush;
  183.  
  184.  
  185. PROCEDURE switch;
  186.  
  187. (* swap buffer and load next, if it exists *)
  188.  
  189. BEGIN
  190.  
  191.    IF (nEnd=nBuf) THEN
  192.      more:=FALSE; (* that's all of it *)
  193.    ELSE
  194.      tBuf:=iBuf; (* don't lose track of buffer *)
  195.      iBuf:=nBuf;
  196.      iStrt:=nStrt;
  197.      iEnd:=nEnd;
  198.      nBuf:=tBuf;
  199.      IF iEnd=iBuf+ADDRESS(bufSize) THEN (* that was a full buffer *)
  200.        actRead:=Read(inFile,nBuf,bufSize);
  201.        nStrt:=nBuf; nEnd:=nBuf+ADDRESS(actRead);
  202.      ELSE
  203.        nStrt:=nBuf; nEnd:=nBuf;
  204.      END; (* getting next buffer if possible *)
  205.    END; (* buffer switching *)
  206.    
  207. END switch;
  208.  
  209.  
  210. (* the program ************************************************************)
  211.  
  212. BEGIN
  213.  
  214.   InitStringModule; (* why ? *)
  215.   
  216.   IF NOT GetCL(args,arg) OR (args<2) THEN
  217.     ErrMsg;
  218.     RETURN;
  219.   END;
  220.   
  221.   FOR i:=1 TO args DO
  222.     IF arg[i,Length(arg[i])-1]=CHR(10) THEN
  223.       Delete(arg[i],Length(arg[i])-1,1);
  224.     END;
  225.   END;
  226.   
  227.   inFileNm:=arg[1];
  228.   outFileNm:=inFileNm;
  229.   prompt:=FALSE;
  230.   skpSize:=0;
  231.   blkSize:=0;
  232.   blkCount:=0; (* indicates keep taking blocks until there's none left *)
  233.   split:=FALSE;
  234.   bufSize:=defaultBuf;
  235.   
  236.   i:=2;
  237.  
  238.   iOld:=maxArgs+10; (* make sure iOld<>i *)
  239.   
  240.   WHILE (i<=args) AND (iOld<>i) DO
  241.   
  242.     iOld:=i;
  243.   
  244.     IF begins(arg[i],skpArg) THEN
  245.       Copy(arg[i],Length(skpArg),Length(arg[i])-Length(skpArg),s);
  246.       ConvertFromString(s,10,FALSE,MAX(LONGCARD),lcard,bool);
  247.       IF bool THEN skpSize:=lcard END;
  248.       INC(i);
  249.     END;
  250.     
  251.     IF begins(arg[i],szeArg) THEN
  252.       Copy(arg[i],Length(szeArg),Length(arg[i])-Length(szeArg),s);
  253.       ConvertFromString(s,10,FALSE,MAX(LONGCARD),lcard,bool);
  254.       IF bool THEN blkSize:=lcard END;
  255.       INC(i);
  256.     END;
  257.   
  258.     IF begins(arg[i],cntArg) THEN
  259.       Copy(arg[i],Length(cntArg),Length(arg[i])-Length(cntArg),s);
  260.       ConvertFromString(s,10,FALSE,MAX(LONGCARD),lcard,bool);
  261.       IF bool THEN blkCount:=lcard END;
  262.       INC(i);
  263.     END;
  264.  
  265.     IF begins(arg[i],preArg) THEN
  266.       Copy(arg[i],Length(bfrArg),Length(arg[i])-Length(bfrArg),outFileNm);
  267.       INC(i);
  268.     END;
  269.     
  270.     IF begins(arg[i],pmtArg) THEN
  271.       prompt:=TRUE;
  272.       INC(i);
  273.     END;
  274.     
  275.     IF begins(arg[i],bfrArg) THEN
  276.       split:=TRUE; before:=TRUE;
  277.       Copy(arg[i],Length(bfrArg),Length(arg[i])-Length(bfrArg),splitStr);
  278.       INC(i);
  279.     END;
  280.     
  281.     IF begins(arg[i],aftArg) THEN
  282.       split:=TRUE; before:=FALSE;
  283.       Copy(arg[i],Length(aftArg),Length(arg[i])-Length(aftArg),splitStr);
  284.       INC(i);
  285.     END;
  286.     
  287.     IF begins(arg[i],bufArg) THEN
  288.       Copy(arg[i],Length(cntArg),Length(arg[i])-Length(cntArg),s);
  289.       ConvertFromString(s,10,FALSE,MAX(LONGCARD),lcard,bool);
  290.       IF bool THEN bufSize:=1024*lcard END;
  291.       INC(i);
  292.     END;
  293.     
  294.   END; (* WHILE args to parse *)
  295.  
  296.   IF i<args THEN (* not all command line arguments were used *)
  297.     ErrMsg;
  298.     RETURN;
  299.   END;
  300.  
  301.   WriteString("inFile : "); WriteString(inFileNm); WriteLn;
  302.   WriteString("skip   : "); WriteLongCard(skpSize,10); WriteLn;
  303.   WriteString("size   : "); WriteLongCard(blkSize,10); WriteLn;
  304.   WriteString("count  : "); WriteLongCard(blkCount,10); WriteLn;
  305.   IF split THEN
  306.     IF before THEN
  307.       WriteString("before : "); WriteString(splitStr); WriteLn;
  308.     ELSE
  309.       WriteString("after  : "); WriteString(splitStr); WriteLn;
  310.     END;
  311.   END;
  312.   WriteString("buffer : "); WriteLongCard(bufSize,10);
  313.   WriteString(" (");
  314.   WriteLongCard(2*bufSize,10); WriteString(" bytes total)");
  315.   WriteLn;
  316.   IF Compare(inFileNm,outFileNm)<>Equal THEN
  317.     WriteString("prefix : "); WriteString(outFileNm); WriteLn;
  318.   END;
  319.   IF prompt THEN 
  320.     WriteString("Prompt before each file");WriteLn;
  321.   END;
  322.   
  323.   WriteLn;
  324.   WriteString("Continue ? (y/n) ");
  325.   InOut.Read(c);
  326.   IF (c<>"y") AND (c<>"Y") THEN RETURN END;
  327.  
  328.   IF split THEN (* pre-parse search string *)
  329.     i:=0;
  330.     WHILE INTEGER(i)<INTEGER(Length(splitStr))-2 DO
  331.       IF splitStr[i]=hexPrecur THEN (* a hex thing *)
  332.         Copy(splitStr,i+1,2,s);
  333.         Delete(splitStr,i,2);
  334.         ConvertFromString(s,16,FALSE,255,lcard,bool);
  335.         splitStr[i]:=CHR(SHORT(lcard));
  336.       END;
  337.       INC(i); (* as usual, I forgot the first time *)
  338.     END;
  339.   END;
  340.  
  341.  
  342.   IF prompt THEN
  343.     InOut.Read(c); (* seems to need flushing *)
  344.   END;
  345.  
  346.   
  347.  (* start setup **************************************************************)
  348.   
  349.   inFile:=Open(inFileNm,ModeOldFile);
  350.   IF inFile=0 THEN
  351.     WriteString("Couldn't open input file");
  352.     WriteLn;
  353.     RETURN;
  354.   END;  
  355.   
  356.     
  357.   iBuf:=AllocMem(bufSize,MemReqSet{});
  358.   IF iBuf=0 THEN
  359.     WriteString("Couldn't get mem for input buffer 1");
  360.     WriteLn;
  361.     Close(inFile);
  362.     Close(outFile);
  363.     RETURN;
  364.   END;
  365.   
  366.   nBuf:=AllocMem(bufSize,MemReqSet{});
  367.   IF nBuf=0 THEN
  368.     WriteString("Couldn't get mem for input buffer 2");
  369.     WriteLn;
  370.     Close(inFile);
  371.     Close(outFile);
  372.     FreeMem(iBuf,bufSize);
  373.     RETURN;
  374.   END;
  375.   
  376.   (* load buffers ******************************************************)
  377.   
  378.    
  379.   IF skpSize<>0 THEN
  380.     lint:=Seek(inFile,LONGINT(skpSize),OffsetBeginning);
  381.     IF lint=-1 THEN
  382.       Close(inFile);
  383.       Close(outFile);
  384.       FreeMem(iBuf,bufSize);
  385.       FreeMem(nBuf,bufSize);
  386.       WriteString("Error skipping data - skipped whole file?");
  387.       WriteLn;
  388.       RETURN
  389.     END;
  390.   END;
  391.  
  392.   IF blkSize=0 THEN (* now just copy out rest of file *)
  393.   
  394.    blkNum:=1;
  395.    outFile:=nextOut(outFileNm,blkNum);
  396.    IF outFile=0 THEN
  397.      Close(inFile);
  398.      RETURN;
  399.    END;
  400.      
  401.   
  402.     REPEAT
  403.       actRead:=Read(inFile,iBuf,bufSize);
  404.       actWrite:=Write(outFile,iBuf,actRead);
  405.     UNTIL actRead<>bufSize;
  406.     
  407.     Close(outFile);
  408.     
  409.   ELSE (* got to chop it up *)
  410.   
  411.     (* first, load both buffers *)
  412.     
  413.     actRead:=Read(inFile,iBuf,bufSize);
  414.     iStrt:=iBuf; iEnd:=iBuf+ADDRESS(actRead);
  415.     IF actRead=bufSize THEN
  416.       actRead:=Read(inFile,nBuf,bufSize);
  417.       nStrt:=nBuf; nEnd:=nBuf+ADDRESS(actRead);
  418.     ELSE
  419.       nStrt:=nBuf; nEnd:=nBuf;
  420.     END;
  421.     
  422.     more:=TRUE; (* more available *)
  423.     blkNum:=1;
  424.     
  425.     
  426.     REPEAT
  427.     
  428.       outFile:=nextOut(outFileNm,blkNum);
  429.       IF outFile=0 THEN
  430.         Close(inFile);
  431.            RETURN;
  432.       END;
  433.          
  434.       curSize:=0; (* number of bytes out to the current block *)
  435.  
  436.       killSrch:=FALSE;
  437.     
  438.       
  439.       WHILE (curSize<blkSize) AND more DO
  440.         IF ADDRESS(blkSize-curSize)<=iEnd-iStrt THEN
  441.           actWrite:=Write(outFile,iStrt,blkSize-curSize);
  442.           curSize:=curSize+actWrite;
  443.           iStrt:=iStrt+ADDRESS(actWrite);
  444.           matchPos:=0;
  445.           
  446.           IF split THEN
  447.           
  448.             cPtr:=iStrt;
  449.             matchPos:=0;
  450.             state:=srchI;
  451.             
  452.             WHILE state<>done DO
  453.             
  454.               CASE state OF
  455.               
  456.               srchI :
  457.                 WHILE (cPtr^<>splitStr[matchPos]) AND more DO
  458.                   INC(cPtr);
  459.                   IF cPtr>=iEnd THEN
  460.                     flush;
  461.                     switch;
  462.                     cPtr:=iStrt;
  463.                   END;
  464.                 END;
  465.                 IF NOT more THEN
  466.                   state:=done; (* didn't find start of target *)
  467.                 ELSE
  468.                   matchStrt:=cPtr;
  469.                   state:=endI; (* found start *)
  470.                 END;
  471.               | (* all for srchI *)
  472.                 
  473.               endI :
  474.                 REPEAT
  475.                   INC(matchPos);
  476.                   INC(cPtr);
  477.                 UNTIL (cPtr=iEnd) OR (matchPos>=Length(splitStr)) OR (cPtr^<>splitStr[matchPos]);
  478.                 IF matchPos>=Length(splitStr) THEN
  479.                   state:=writeI;
  480.                 ELSE
  481.                   IF cPtr=iEnd THEN
  482.                     cPtr:=nStrt;
  483.                     state:=endN;
  484.                   ELSE  (* not target *)
  485.                     state:=srchI;
  486.                     matchPos:=0;
  487.                     cPtr:=matchStrt;
  488.                     INC(cPtr);
  489.                   END;
  490.                 END;
  491.               | (* end of search in iBuf *)
  492.                 
  493.               endN :
  494.                 WHILE ((cPtr^=splitStr[matchPos]) OR (cPtr^=singleWild)) AND (matchPos<Length(splitStr)) AND (cPtr<nEnd) DO
  495.                   INC(cPtr);
  496.                   INC(matchPos);
  497.                 END;
  498.                 IF matchPos=Length(splitStr) THEN
  499.                   state:=writeN;
  500.                 ELSE
  501.                   IF cPtr=nEnd THEN
  502.                     WriteString("Out of range search for end of target");
  503.                     state:=srchI;
  504.                     cPtr:=matchStrt;
  505.                     INC(cPtr);
  506.                   ELSE (* not target *)
  507.                     state:=srchI;
  508.                     cPtr:=matchStrt;
  509.                     INC(cPtr);
  510.                   END;
  511.                 END;
  512.               | (* end of endN *)
  513.                 
  514.               writeI :
  515.                 IF before THEN
  516.                   actWrite:=Write(outFile,iStrt,LONGCARD(ADDRESS(matchStrt)-iStrt));
  517.                   iStrt:=matchStrt;
  518.                   state:=done;
  519.                 ELSE
  520.                   actWrite:=Write(outFile,iStrt,LONGCARD(ADDRESS(cPtr)-iStrt));
  521.                   iStrt:=cPtr;
  522.                   state:=done;
  523.                 END;
  524.                 
  525.               | (* done i Write *)
  526.               
  527.               writeN :
  528.                 IF before THEN 
  529.                   actWrite:=Write(outFile,iStrt,LONGCARD(ADDRESS(matchStrt)-iStrt));
  530.                   iStrt:=matchStrt;
  531.                   state:=done;
  532.                 ELSE  
  533.                   flush; (* send all of iBuf *)
  534.                   actWrite:=Write(outFile,nBuf,LONGCARD(ADDRESS(cPtr)-nBuf));
  535.                   nStrt:=cPtr;
  536.                   switch;
  537.                   state:=done;
  538.                 END;
  539.               | (* done n Write *)
  540.               
  541.               ELSE (* case shouldn't come here ! *)
  542.               
  543.               END; (* case *)                  
  544.                 
  545.             END; (* when state=done *)
  546.           END; (* if split *)
  547.                 
  548.         ELSE (* not enough in buffer *)
  549.           flush;  (* give it what there is *)
  550.           switch; (* see if theres more, will set more=FALSE if not *)
  551.         END; (* sending buffer (or part of) to block *)
  552.       END; (* making block *)
  553.     
  554.       Close(outFile);
  555.       
  556.       IF curSize=0 THEN (* whoops, created empty file *)
  557.         ConvertToString(blkNum,10,FALSE,s,bool);
  558.         WHILE Length(s)<3 DO
  559.           Insert("0",s,0);
  560.         END;
  561.         Concat(".",s,s);
  562.         Concat(outFileNm,s,s);
  563.         IF NOT DeleteFile(s) THEN
  564.           WriteLn;
  565.           WriteString("Whoops, error deleting empty file.");
  566.           WriteLn;
  567.         END;
  568.       END;
  569.       
  570.       INC (blkNum);
  571.       
  572.       IF (blkNum>blkCount) AND (blkCount<>0) THEN
  573.         more:=FALSE; (* even if it's not *)
  574.       END;
  575.         
  576.     UNTIL NOT more; (* all blocks made *)
  577.   
  578.   END; (* end of cut up *)
  579.   
  580.  
  581.   Close(inFile);
  582.   
  583.   FreeMem(iBuf,bufSize);
  584.   FreeMem(nBuf,bufSize);
  585.  
  586. END Chop.
  587.