═══ 1. Introduction ═══ Introduction This is binary editor (or file creator) which takes all commands via a text file or command line. It can verify the contents of files before a patch is applied. The following is an example of how a file can be created: OPENNEW L4029.PIC WRITE '1B'x || '[K' || '0B00 FF31 02 A0 04 00 00 0000 90'x CLOSE This program does not have commands such as #define & #include as its expected that you'd add a PPWIZARD preprocessor step if you wanted the much more power capabilities (macros with parameters, conditional inclusion etc). Please see my web page "http://www.ozemail.com.au/~dbareis". for the latest copy of BINTOOL or PPWIZARD, or contact me (Dennis Bareis) via email (db0@anz.com). I'm open to any reasonable suggestions. Please have a look at the proposed changes section and after using this program for a while tell me what you think. Note that I would have loved to have written this in Java, however as a compiled language it does not have an "interpret" instruction. Apparently something is being added to version 1.2 which might allow something similar, I'll have a look then. The "interpret" instruction is important as it allows the preprocessor to be extended as well as doing a lot of work I'd otherwise need to do myself (and I wouldn't do it as well). I will not be rewriting the preprocessor in Java (as it wouldn't be compatible with the rexx version), but with any luck I'd be able to write any similar future stuff in Java.... ═══ 1.1. Proposed Changes ═══ If I've got the time I like to think about the best way of implementing something (as well as questioning whether or not it should be). If I have a requirement I like to implement as generic a solution as possible. This is my "longer" term think about it list.. Come on, surely someone out there wishes this had an "xyz" feature or something worked better? I've only had one single comment about its functioning and this prompted me to make a change, since there have been so many downloads of this tool its either crap or perfect... I don't think its crap, but then again I doubt its perfect either, so comments please! Tell me what you think even if option is already listed as without feedback on whats important I could reasign priorities or delete an item altogether. Proposed Changes - Rough Priority 1. Command line parameters (such as /DEBUG, and /PARM). 2. Better output from script, get rid of commands, show again if in debug mode (plus normal interactive stuff) + maybe more. 3. DELETE command. Deletes specified number of bytes (shrinks file). 4. COPY command. Copies specified number of bytes to specified file. A CUT becomes a COPY then DELETE. 5. INSERT command. Insert contents of file. Also Insert specified bytes. 6. BOOKMARK locations. Then "MoveTo Fred" etc. ═══ 1.2. Change History ═══ Change History 1. Version 2K.033  Can now make better use of rexx variables by allowing variable substitution into command lines.  Fixed file open commands to die on open failure.  4th parameter of ReplaceString() no longer exists. ═══ 1.3. Bugs ═══ Currently Known Bugs Reporting Bugs or Suggestions If reporting bugs please supply: 1. All files involved (input, output and any Batch files used to run the preprocessor). You have hopefully trimmed out everything which is not required to reproduce the problem. 2. A detailed description of the problem. The easier you make it for me the faster I will be able to come up with a fix or tell you what your doing wrong etc. ═══ 2. BINTOOL.CMD Command Line ═══ BINTOOL.CMD Command Line BINTOOL[.CMD] [whitespace]?[whitespace] OR BINTOOL[.CMD] [whitespace]ScriptFile[whitespace] This program has two main modes "INTERACTIVE" mode where the user enters all information from a command prompt and file driven. If "?" is specified interactive mode is used otherwise you supply the name of the file which contains the commands to be executed. In both modes blank lines and ones that begin with ";" are ignored. If a line contains ";;" then the last occurrance within a line and anything following is removed (inline comment). Script Mode If a command or verification fails the script terminates. Interactive Mode If a command or verification fails an error is displayed but the program does not terminate. The command prompt maintains a history of previous commands and all usual keys work including "" or selective recall. In interactive mode the "RECORD" command can be used to record all the commands typed so you can later on rerun what you have recorded to repeat if required. RETURN CODES  A return code of 0 indicates success.  Any other value indicates an error occurred. ═══ 2.1. /Color ═══ Switch /Color[:YesOrNo] This is a BINTOOL.CMD command line switch. You can set up your own default switches in the "BINTOOL_OPTIONS" environment variable. You can determine if colors are used in displayed output. Useful if redirecting output to log files (or you just hate colors!). If the "YesOrNo" is not specified then it defaults to "Y", otherwise one of the following values is expected:  Y  N  YES  NO For colors to work the session must support ANSI color strings. OS/2 does this by default. NT does not seem to. ═══ 2.2. /Debug ═══ Switch /Debug This is a BINTOOL.CMD command line switch. You can set up your own default switches in the "BINTOOL_OPTIONS" environment variable. This option can be useful in determining what is going wrong when you don't get the output you expected. ═══ 3. Commands ═══ Commands The following commands are available to you when you use the BINTOOL.CMD:  CLOSE  DECIMAL  DUMP  DUMPCHAR  EXIT  GOTO  FIND  FINDCS  HEXADECIMAL  LOCATE[!]  MOVETO  ONERROR  OPEN  OPENNEW  OPENREAD  QUIT  REBUILD  RECORD  REXX  SYSTEM  VERIFY  VERIFYFILE  WRITE  ? Note that a lot of the commands are demonstrated further in the example scripts that are included in this manual. Also note that for anything but trivial scripts its worth the effort to include a "PPWIZARD" step in a batch file rather than using BINTOOL directly. This would allow you to use more powerful commands such as #define, #evaluate, #include, #if and more. ═══ 3.1. CLOSE ═══ CLOSE This will close the currently open file. It does not take parameters. ═══ 3.2. DECIMAL ═══ DECIMAL If you do not specifically indicate that a number is in either hex or decimal then by default the number is assumed to be hexadecimal. To indicate a number is in base 10 preceed the number with '$', for hexadecimal use 'x'. This commands purpose is to change the default to decimal. To restore it use the "HEXADECIMAL" command. ═══ 3.3. DUMP ═══ DUMP This command will dump all or part of the current file in both hex and character modes. The default character set used is ASCII with dots used for unusual characters, if this is unsuitable you could create your own character tables and load them with the "DUMPCHAR" command. A second dump command immediately following a previous one will always continue from where the previous one left off. Commands which affect the current position (such as WRITE) will reset the position from which following dumps take place. A dump command does not move the read/write position. Syntax [whitespace]DUMP [whitespace][NumBytesToDump][whitespace] The "NumBytesToDump" specifies the number of bytes to dump. If not specified a default is used. EXAMPLE OF DUMP OUTPUT 40: 0E1F BA0E 00B4 09CD 21B8 014C CD21 5468 | ........!..L.!Th | 50: 6973 2070 726F 6772 616D 2063 616E 6E6F | is program canno | 60: 7420 6265 2072 756E 2069 6E20 6120 444F | t be run in a DO | 70: 5320 7365 7373 696F 6E2E 0D0D 0A24 0000 | S session....$.. | ═══ 3.4. DUMPCHAR ═══ DUMPCHAR This command allows you to redefine the character set used in the character portion of a dump. This could be as simple as changing the ASCII character set so that blanks are used instead of dot for unusual chacters. See EBCDIC.BIN for an example for how to create a new character set. Syntax [whitespace]DUMPCHAR [whitespace][["]CharacterSetFile["]][whitespace] The "CharacterSetFile" specifies the name of the file to be loaded. If not specified then the character set is restored to the default. FORMAT OF FILE The following describes the contents of the file (all bytes in ASCII): 1. It must begin with the string "DUMPCHAR". 2. The character "|". 3. A description of the file, displayed when loaded. 4. The character "|". 5. There must be exactly 256 characters which are mapped to the hex value. ═══ 3.5. EXIT ═══ EXIT In interactive mode this will exit the program. Opened files will be closed. ═══ 3.6. FIND ═══ FIND This command will FIND a number of bytes in the file from the current location onwards. If we don't find the string then the current file position is restored. This command is used to perform a case insensitive search. If you require a case sensitive search you should use "FINDCS" instead. Note for performance a case sensitive search will be performed anyway if your search string does not contain any letters. Syntax [whitespace]FIND [whitespace]RexStringExpression[whitespace] The "RexStringExpression" is a rexx expression which will be executed. The result should be a string which is to be verified. EXAMPLES FIND '0000'x || copies('*', 8) || '0B00'x ;;Look for these 12 bytes WRITE 'FFFF'x ;;Patch the first 2 bytes ═══ 3.7. FINDCS ═══ FINDCS This command is the same as the "FIND" command except that a case sensitive search is performed. ═══ 3.8. GOTO ═══ GOTO This command will transfer control to the line with the label specified. Syntax [whitespace]GOTO [whitespace]Label[whitespace] The "Label" is the name of a label that should be defined somewhere in the source script (either before or after the current location). EXAMPLES ;--- Transfer control to the "END" label --- GOTO END ... ... ;--- Define the "END" label ---------------- :End ═══ 3.9. HEXADECIMAL ═══ HEXADECIMAL If you do not specifically indicate that a number is in either hex or decimal then by default the number is assumed to be hexadecimal. To indicate a number is in base 10 preceed the number with '$', for hexadecimal use 'x'. This commands purpose is to change the back to hexadecimal in situations where you have probably changed the default number base. For example you could have previously used the "DECIMAL" command to make base 10 the default number base. ═══ 3.10. LOCATE[!] ═══ LOCATE[!] These commands will find the first character that is in or not in a list of characters you supply. You could use this to verify that a file contains no null bytes ('00x') etc. Syntax [whitespace]LOCATE[!] [whitespace]RexStringExpression[whitespace] If the command used is "LOCATE" then the search will be for the first character that is also in the list you supply. If LOCATE! is used then it will try to find a character that is not in the list. The "RexStringExpression" is a rexx expression which will be executed. The result is a sequence of characters. EXAMPLES See if there are any null bytes in the file: LOCATE '00'x Find the first non numeric byte: LOCATE! xrange('0', '9') ═══ 3.11. MOVETO ═══ MOVETO This command is used to move the current read, write or dump location to a new position within the file. Note that all seeks will fail unless the file contains at least one byte (rexx feature). If you try to move outside of the valid range the command will fail. Syntax [whitespace]MOVETO [whitespace]START|END[whitespace] OR [whitespace]MOVETO [whitespace]+|- Offset[whitespace] OR [whitespace]MOVETO [whitespace]Offset[whitespace] The "Offset" parameter is a decimal or hex value which specifies how much to move or where to move to. to be opened. EXAMPLES MoveTo Start MoveTo End MOVETO + x1 ;;Move forwards 1 byte (number supplied as hex) MOVETO - $2 ;;Move backwards 2 bytes (number supplied as decimal) HEXADECIMAL ;;Ensure default is hex MoveTo B ;;Move to offset B hex (0 = 1st byte) ═══ 3.12. ONERROR ═══ ONERROR This command can be used to specify a label where processing will be transferred if the next command fails. Syntax [whitespace]ONERROR [whitespace]Label[whitespace] The "Label" is the name of a label that should be defined somewhere in the source script (either before or after the current location). EXAMPLES ;--- Patch all Nulls ------------------------- rexx NullCounter = 0 :PatchLoop ;--- Look for null bytes ----------------- OnError NoMoreNulls FIND "00"x ;--- Overwrite null byte ----------------- WRITE 'FF'; rexx NullCounter = NullCounter + 1 goto PatchLoop :NoMoreNulls rexx say AddCommasToDecimalNumber(NullCounter) || ' null byte(s) converted.' ═══ 3.13. OPEN ═══ OPEN This command is used to open a file for read and write. If you wish to start with a clean file then use "OPENNEW" instead. If you don't intend to update the file then you should use "OPENREAD". Syntax [whitespace]OPEN [whitespace]["]FileName["][whitespace] The "FileName" parameter is the name of the file to be opened. EXAMPLES OPEN "MEMORY.BIN" DUMP CLOSE ═══ 3.14. OPENNEW ═══ OPENNEW This command is the same as "OPEN" except that any existing file is first deleted so that you are starting with a "clean" file. ═══ 3.15. OPENREAD ═══ OPENREAD This command is the same as "OPEN" except that the file must exists and is opened for read only. You will not be able to perform any commands that modify the file (such as "WRITE"). ═══ 3.16. QUIT ═══ QUIT An alias for "EXIT". ═══ 3.17. REBUILD ═══ REBUILD This command allows you to open any binary file and create a script which could be used to recreate it from scratch. One possible use of this command is to binary edit the file with a text editor. Might be slower but its certainly easier. Once in text form you can use commands such as PVCS to track source changes. Difference programs can also be used. As the command only rebuilds the file from the current location onwards to capture the whole file ensure that you are at the start of the file (Use "MOVETO" if required). Syntax [whitespace]REBUILD [whitespace]["]NewScriptFile["][whitespace] The "NewScriptFile" parameter if supplied is the name of a file to which information is to be written. EXAMPLES OPENREAD "XCOPY.EXE" REBUILD "XCOPY.BIN" CLOSE ═══ 3.18. RECORD ═══ RECORD This command can only be used in interactive mode and is used to record the commands you enter, on the theory that you will want to use these later to polish up an automated script. It allows you to experiment to produce the correct result, then with minor editing of the produced file (to remove your mistakes) you have a script which is very likely to work. Syntax [whitespace]RECORD [whitespace][["]RecordFileName["]][whitespace] The "RecordFileName" parameter if supplied is the name of a file to which information is to be written. If no filename is supplied then recording is turned off. EXAMPLES RECORD "MEMORY.BIN" RECORD ═══ 3.19. REXX ═══ REXX This command will let you execute any rexx statement. This is a specialised command which you may never have need for. Syntax [whitespace]REXX [whitespace]RexxCommand[whitespace] The "RexxCommand" parameter is any valid rexx command (or commands). Any variables you set will remain until the end of the program or modified. EXAMPLES ;--- Calculator ---------------------------------------------------------------- rexx say 40 * 3 + 11 ;--- Output a status message --------------------------------------------------- REXX say 'About to patch the file' ;--- Perform a simple validation that the "PATH" environment variable exists --- rexx if GetEnv("PATH") = '' then do; call CommandFailure '"PATH" Envvar missing!'; end ;--- Make sure exactly 256 bytes are written to the file ----------------------- rexx StartTable = CurrentOffset(); WRITE copies('.', 256); rexx NumberOfBytes = CurrentOffset() - StartTable; rexx if NumberOfBytes <> 256 then do; call CommandFailure 'Wrote ' || NumberOfBytes || ' bytes, expected exactly 256!'; end ═══ 3.20. SYSTEM ═══ SYSTEM This command allows you to execute system commands. The system command does not fail if a non-zero return code is returned by the command processor however the rexx variable "SystemRc" is set and can be verified with the "REXX" command if required. Syntax [whitespace]REXX [whitespace][SystemCommand][whitespace] The "SystemCommand" parameter (if supplied) is anything you could type from an operating system command prompt. If not supplied a command prompt is started (use "EXIT" to leave this command prompt). EXAMPLES SYSTEM SYSTEM dir *.exe ═══ 3.21. VERIFY ═══ VERIFY This command will VERIFY a number of bytes in the file at the current position. The current position is not modified so a subsequent WRITE will overwrite the verified bytes. You may wish a more global file level check, if so have a look at the "VERIFYFILE" command. Syntax [whitespace]VERIFY [whitespace]RexStringExpression[whitespace] The "RexStringExpression" is a rexx expression which will be executed. The result should be a string which is to be verified. EXAMPLES MOVETO + x1 ;;Move forwards 1 decimal VERIFY '[K' || '0B00'x ;;Verify 4 of the bytes WRITE '0000 0000'x ;;Overwrite the 4 verified bytes ═══ 3.22. VERIFYFILE ═══ VERIFYFILE This command will verify a files: 1. Existance 2. Length 3. CRC32 If you can't verify the files contents at this level the "VERIFY" command may be more suitable for your needs. Syntax [whitespace]VERIFYFILE [whitespace]"FileName" [whitespace][FileLength [whitespace][FileCrc32]][whitespace] The "FileName" parameter specifies the name of a file. Its expected to exist. This is the only required parameter. The "FileLength" parameter specifies the length of the file. As well as existing it is expected to have this file size. The length is supplied in decimal. The "FileCrc32" parameter specifies the CRC32 of the file. As well as existing and having the correct length it is expected to have the correct CRC. A CRC is unlikely to be the same if a files contents are not as expected. The CRC used by this program is the same as that used by PKZIP. Note that the CRC routine is written in pure rexx and is not that fast so you may not wish to check the CRC or a really large file. The CRC is supplied in exactly 8 hexadecimal characters. EXAMPLES The following demonstrates the 3 different file level verifications that can be performed: VerifyFile "L4029.PIC" ;;Ensure File exists VerifyFile "L4029.PIC" 15 ;;Ensure File exists + correct length (15 decimal) VerifyFile "L4029.PIC" 15 B8BD46E4 ;;Ensure File exists + correct length (15 decimal) + CRC32 is correct ═══ 3.23. WRITE ═══ WRITE This command will WRITE a number of bytes to the output file to the current location. A subsequent write's characters will be written immediately after the previous ones. Syntax [whitespace]WRITE [whitespace]RexStringExpression[whitespace] The "RexStringExpression" is a rexx expression which will be executed. The result should be a string which is to be written to the file. EXAMPLES WRITE '1B'x || '[K' || '0B00 FF31 02 A0 04 00 00 0000 90'x WRITE copies('*', 10) WRITE '0D0A'x ;;Output CR + LF WRITE binary('0100 0001'); ;;Ascii 'A' ═══ 3.24. ? ═══ ? This command will display the online manual. Syntax [whitespace]? [whitespace][HelpOnWhat][whitespace] The "HelpOnWhat" parameter is optional. If not specified then the maunal is opened at the table of contents, otherwise the manual will be opened at the first heading that matches what you typed. EXAMPLES ? ? dump ? write ═══ 4. Procedures ═══ Procedures The following Procedures are available to you whenever you execute a rexx expression (for example in REXX & WRITE commands).:  AddCommasToDecimalNumber  Binary  B2C  CommandFailure  CurrentOffset  EOL  GetEnv  GotoLabel  ReplaceString ═══ 4.1. AddCommasToDecimalNumber() ═══ AddCommasToDecimalNumber() This function takes a single parameter (a decimal integer) and returns the number with commas as required. ═══ 4.2. Binary() ═══ Binary() This routine takes a single parameter (a binary string) and returns a string of characters that represent the passed string. Note that "B2C()" is an alias for this command. Sometimes a value is more meaningful in binary. If using a PPWIZARD front end it would also provide the option of programatically building different bit strings based on conditions. EXAMPLES WRITE binary('0100 0001') ;;Ascii 'A' WRITE binary('0100 0010 0100 0011') ;;Ascii 'BC' WRITE binary('01000100 01000101') ;;Ascii 'DE' WRITE binary('0000 0000') ;;x00 ═══ 4.3. CommandFailure() ═══ CommandFailure() This routine requires a single parameter (a string to display). The error message will be displayed and then clean up processing will take place and the program exited with a non-zero return code. Its major use if in validations such as that shown in the example below. Do not call exit() directly. EXAMPLES ;--- Perform a simple validation that the "PATH" environment variable exists - rexx if GetEnv("PATH") = '' then do; call CommandFailure '"PATH" Envvar missing!'; end ═══ 4.4. CurrentOffset() ═══ CurrentOffset() This routine takes no parameters and returns the current offset in the file ('!' is returned on error). You must of course only try calling this routine when a file is open! EXAMPLES ;--- Make sure exactly 256 bytes are written to the file ----------------------- rexx StartTable = CurrentOffset(); WRITE copies('.', 256); rexx NumberOfBytes = CurrentOffset() - StartTable; rexx if NumberOfBytes <> 256 then do; call CommandFailure 'Wrote ' || NumberOfBytes || ' bytes, expected exactly 256!'; end ═══ 4.5. EOL() ═══ EOL() This routine takes no parameters and returns the character or characters required to terminate a text line. On PC systems it would return a Carriage Return followed by a Line Feed. On Unix systems only a Line Feed would be returned. This routine should be called rather than hardcoding the CR + LF etc to make your script platform independant. EXAMPLES WRITE '0D0A'x ;;Output CR + LF (Hardcoded - not recommended) WRITE EOL() ;;Same as '0D0A'x on PC systems ═══ 4.6. GetEnv() ═══ GetEnv() This routine takes a single parameter (the name of an environment variable) and returns its contents. EXAMPLES ;--- Make sure "PATH" exists ------------------------------------- rexx if GetEnv("PATH") = '' then do; call CommandFailure '"PATH" Envvar missing!'; end ;--- Write the contents of the "path" to the file ---------------- WRITE GetEnv("PATH"); ═══ 4.7. GotoLabel() ═══ GotoLabel() This routine takes a single parameter (the name of a label). The next command to be executed will be from the line following the label in the script file. The command would be useful in "REXX" commands to make inteligent decisions. ═══ 4.8. ReplaceString() ═══ ReplaceString() This function will convert all occurances of a substring as you specify. The function takes 4 parameters although only the first 3 are required, the parameters are: 1. The string which is to be translated. 2. The FROM string. 3. The TO string. ═══ 5. Rexx Variable Substitution ═══ The rexx command allows you to create rexx variables, possibly by getting a value from an environment variable, it is possible to have these substituted into a command line. To have one or more rexx variables substituted into a line simply preceed each rexx variable name by "<@" and add ">" after the variable name. EXAMPLE OF DUMP OUTPUT ;--- Open file (name specified by batch file) ---- rexx WantedCmd = "OpenNew " || GetEnv('FILENAME') <@WantedCmd> ═══ 6. Example Scripts ═══ Example Scripts  EBCDIC.BIN  EXAMPLE.BIN  PATCHALL.BIN  PPWIZARD.BIN ═══ 6.1. EBCDIC.BIN ═══ EBCDIC.BIN This script creates "EBCDIC.TBL" which can then be loaded via a "DUMPCHAR" command so that subsequent "DUMP" commands display the characters in EBCDIC. ;---------------------------------------------------------------------------- ;------------------------------[ EBCDIC.BIN ]-------------------------------- ;---------------------------------------------------------------------------- ; ; Used to create "EBCDIC.TBL" which can then be loaded via the "DUMPCHAR" ; command to control the characters displayed by the "DUMP" command. ; ;---------------------------------------------------------------------------- ;*** $Header: E:/DB/PVCS.IT/OS2/BINTOOL/EBCDIC.BIV 1.2 11 Jun 1998 18:48:10 Dennis_Bareis $ ;--- Open a NEW file -------------------------------------------------------- OpenNew "EBCDIC.TBL" ;--- Output header ---------------------------------------------------------- write 'DUMPCHAR' write '|' write 'To EBCDIC' write '|' ;--- Remember Current Offset ------------------------------------------------ rexx StartTable = CurrentOffset(); ;--- Output 256 char translation set ---------------------------------------- WRITE '................................' WRITE '................................' WRITE ' ' WRITE '...........' WRITE '<(+.&' WRITE '.........' WRITE '!$*);.-/' WRITE '........' WRITE '|,%_>?' WRITE '..........' WRITE ":#@'" WRITE '="' WRITE '.' WRITE 'abcdefghi' WRITE '.{..+..' WRITE 'jklmnopqr' WRITE '.}.....~' WRITE 'stuvwxyz' WRITE '...' WRITE '[' WRITE '...............' WRITE ']' WRITE '...' WRITE 'ABCDEFGHI' WRITE '.......' WRITE 'JKLMNOPQR' WRITE '......\.' WRITE 'STUVWXYZ' WRITE '......' WRITE '0123456789' WRITE '......' ;--- Verify that exactly 256 bytes were written ----------------------------- rexx NumberOfBytes = CurrentOffset() - StartTable; rexx if NumberOfBytes <> 256 then do; call CommandFailure 'EBCDIC character table has ' || NumberOfBytes || ' bytes, expected exactly 256!'; end ;--- Close the file --------------------------------------------------------- close ═══ 6.2. EXAMPLE.BIN ═══ EXAMPLE.BIN This is a simple example with no real purpose. ;---------------------------------------------------------------------------- ;------------------------------[ EXAMPLE.BIN ]------------------------------- ;---------------------------------------------------------------------------- ; ; This is an example file which shows most of the commands available. ; It is not a realistic example but it does function. ; ; Also have a look at my PPWIZARD tool. If this was run as a step prior ; to this one then you could have much more powerful commands such as ; #if, #evaluate, #define. You could define macros with parameters and ; conditional inclusion. These features were left out of this tool on the ; assumption that you'd use PPWIZARD. In a line below the contents of the ; "PATH" evironment variable is written, no validation of its existance ; is or can be performed without using PPWIZARD. ; ; ; This tool: ; ; (a) Easily verify file contents then perform patches. ; (b) Run difference & source management programs over the source. ; (c) Comment changes. ; (d) Allows you to binary edit files with a text editor! ; ; ; To Execute this file: ; ; BINTOOL.CMD EXAMPLE.BIN ; ; ; To try command interactively (Type "QUIT" to exit): ; ; BINTOOL.CMD ? ; ;---------------------------------------------------------------------------- ;*** $Header: E:/DB/PVCS.IT/OS2/BINTOOL/EXAMPLE.BIV 1.8 11 Jun 1998 18:48:10 Dennis_Bareis $ ;--- Open a NEW file -------------------------------------------------------- OPENNEW L4029.PIC ;--- Write out the Lexmark 4029 Initialization Codes ------------------------ WRITE '1B'x || '[K' || '0B00 FF31 02 A0 04 00 00 0000 90'x ;--- Close the file --------------------------------------------------------- CLOSE ;--- Open a binary file ----------------------------------------------------- OPENREAD 'L4029.PIC' ;--- DUMP "BINTOOL" Commands required to rebuild this file ------------------ REBUILD L4029.TXT ;--- Close the file --------------------------------------------------------- CLOSE ;--- Perform some "FILE LEVEL" verifications before patching ---------------- VerifyFile "L4029.PIC" ;;Ensure File exists VerifyFile "L4029.PIC" 15 ;;Ensure File exists + correct length (15 decimal) VerifyFile "L4029.PIC" 15 B8BD46E4 ;;Ensure File exists + correct length (15 decimal) + CRC32 is correct ;--- Perform a simple validation that the "PATH" environment variable exists - rexx if GetEnv("PATH") = '' then do; call CommandFailure 'ERROR: "PATH" Envvar missing!'; end ;--- Open file (don't delete it!) ------------------------------------------ OPEN "L4029.PIC" ;--- Move around a bit ------------------------------------------------------ ;DUMPCHAR EBCDIC ;;Dump character information in EBCDIC (used EBCDIC.TBL) DUMP ;;Dump first part of file MOVETO START MOVETO + x1 ;;Move forwards 1 decimal VERIFY '[K' || '0B00'x ;;Verify 4 of the bytes MOVETO + xA ;;Move backwards 1 decimal MOVETO - $2 ;;Move backwards 2 decimal MOVETO + 5 ;;Move forwards 5 HEX DECIMAL ;;Default now decimal MOVETO - 1 MOVETO - $1 HEXADECIMAL ;;Default now hex (again) MoveTo B ;;Move to offset B hex (0 = 1st byte) MOVETO END ;--- Jump forwards a bit (small!) ------------------------------------------- goto NextLine :NextLine ;--- Write some stuff to end ------------------------------------------------ WRITE '0D0A'x ;;Output CR + LF WRITE copies('~', 70) WRITE EOL() ;;Same as '0D0A'x on PC systems WRITE GetEnv("PATH"); WRITE EOL() WRITE binary('0100 0001') ;;Ascii 'A' WRITE binary('0100 0010 0100 0011') ;;Ascii 'BC' WRITE binary('01000100 01000101') ;;Ascii 'DE' ;--- Write the current offset to the file ----------------------------------- write CurrentOffset(); ;--- Close the file --------------------------------------------------------- CLOSE ;--- Handy Commands in INTERACTIVE Command ---------------------------------- ;QUIT ;;Exit Interactive mode ;SYSTEM dir ;;Run the DIR command ;SYSTEM ;;Go to OS/2 command prompt ;RECORD "1.LOG" ;;Remember commands and logs some results as comments ;RECORD ;;Turn off recording. ═══ 6.3. PATCHALL.BIN ═══ PATCHALL.BIN ;---------------------------------------------------------------------------- ;------------------------------[ EBCDIC.BIN ]-------------------------------- ;---------------------------------------------------------------------------- ; ; Simplistic example where everythings hardcoded. Main things demonstrated ; are labels, the GOTO command and ONERROR command. ; ; Note that the only command handled by an error handler is the ; FIND command. If any other command (such as the WRITE command) fails the ; program will fatally terminate. If this was not desired an ; ONERROR command would need to be placed at each line which might fail. ; ;---------------------------------------------------------------------------- ;*** $Header: E:/DB/PVCS.IT/OS2/BINTOOL/PATCHALL.BIV 1.0 11 Jun 1998 18:48:10 Dennis_Bareis $ ;--- Open the file to be patched -------------------------------------------- OPEN "AFTER.EXE" ;--- Patch all Nulls -------------------------------------------------------- rexx NullCounter = 0 :PatchLoop ;--- Look for null bytes ------------------------------------------------- OnError NoMoreNulls FINDCS "00"x ;--- Replace Null byte with "FF" hex ------------------------------------- WRITE 'FF'; rexx NullCounter = NullCounter + 1 goto PatchLoop :NoMoreNulls rexx say AddCommasToDecimalNumber(NullCounter) || ' null byte(s) converted.' ;--- Close the file --------------------------------------------------------- close ═══ 6.4. PPWIZARD.BIN ═══ PBINTOOL.CMD This batch file could be used to process "PPWIZARD.BIN": /**********************************/ /* BINTOOL.CMD with PPWIZARD STEP */ /**********************************/ /*--- Initialization --------------------------------------------------------*/ address cmd '@echo off' DebugSwitches = ''; /*DebugSwitches = '/debug';*/ /*--- Check thate the user supplied a filename and that it exists -----------*/ UsersScriptFile = strip(arg(1)); if UsersScriptFile = '' then Abort("You did not supply the name of a script file!"); if stream(UsersScriptFile, 'c', 'query exists') = '' then Abort('The file "' || UsersScriptFile || '" does not exist!'); /*--- Get name of temp file (not best way but portable) ---------------------*/ TmpFile = GetEnv("TMP") || '\PBT' || right(time('S'), 5, '0') || ".TMP"; /*--- Run the PPWIZARD step -------------------------------------------------*/ address cmd 'cmd.exe /c PPWIZARD.CMD ' || UsersScriptFile || ' /crlf /output:' || TmpFile || ' ' || DebugSwitches; if Rc <> 0 then Abort("PPWIZARD step failed (Rc = " || Rc || ')'); /*--- Run the BINTOOL step --------------------------------------------------*/ address cmd 'cmd.exe /c BINTOOL.CMD ' || TmpFile; if Rc <> 0 then Abort("BINTOOL step failed (Rc = " || Rc || ')'); /*--- Command worked so delete the temporary file ---------------------------*/ address cmd 'del ' || TmpFile || ' >nul 2>&1'; /*--- Thats all Folks -------------------------------------------------------*/ exit(0); /*===========================================================================*/ Abort: /*===========================================================================*/ CallersLine = SIGL; say arg(1) || ''; exit(CallersLine); /*===========================================================================*/ GetEnv: /* */ /* arg(1) : Name of environment variable. */ /*===========================================================================*/ return( value(arg(1),,'OS2ENVIRONMENT') ); PPWIZARD.BIN ;---------------------------------------------------------------------------- ;------------------------------[ PPWIZARD.BIN ]------------------------------ ;---------------------------------------------------------------------------- ; ; Simplistic example of using PPWIZARD. ; ; Note that it would be smarter to validate both addresses first and then ; write the new value. As it currently stands this example could fail ; at the second validation after we've already patched the file. ; ; It would be smarter yet to be woring on a copy and only update the original ; as the last step (maybe using "SYSTEM copy ......"). ; ;---------------------------------------------------------------------------- ;*** $Header: E:/DB/PVCS.IT/OS2/BINTOOL/PPWIZARD.BIV 1.0 11 Jun 1998 18:48:12 Dennis_Bareis $ ;--- Set up some constants -------------------------------------------------- #define FileToPatch "XYZ.CMD" #define ExpectToFind "97.123" #define FirstPosn x1001 #define SecondPosn x3415 ;--- Create YY.DDD Version # (example "98.107") ----------------------------- #evaluate YYDDD ~substr(date('Sorted'),3,2) || '.' || right(date('Days'), 3, '0')~ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;[ One Way ];;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;--- Open the file and update the version numbers --------------------------- Open <$FileToPatch> MoveTo <$FirstPosn> verify <$ExpectToFind> write <$YYDDD> MoveTo <$SecondPosn> verify <$ExpectToFind> write <$YYDDD> close ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;[ Another Way ];;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;--- Create macro to perform a patch (takes OFFSET as parameter) ------------ #define PatchVer \ MoveTo {$Offset} \ verify <$ExpectToFind> \ write <$YYDDD> ;--- Repeat the above in a slightly better way ------------------------------ Open <$FileToPatch> <$PatchVer Offset='<$FirstPosn>'> <$PatchVer Offset='<$SecondPosn>'> close