IMD 1.16: 29/05/2007 11:56:49 FOGCPM.006 --FOGCPM006CALC CMD$DB2BAKUPCMD  MATHLIB CMDl DB2&3MAXINF !"#$%&'DB2&3MAXINF()*+,-./01234567-10-00 85 -00-10 85 DBPRETTYCOM89:;<=>?@ABCDEFGDBPRETTYCOMhHIJKLMNOPQRST-CPM006 DOCDBPRETTYDOCUVWENCODE COMXYZ[\]^_`abcdefgENCODE COM2hijklmnENCODE DOCaopqrstuvwxyz{LOAD-HEXDOCE|}~NEWBAS11ASMNEWBAS11ASMVDBTYPE ASMVDBTYPE ASMThis is the disk name. ****************************< CALC.CMD >***************************** * This is a dBASE II calculator program which utilizes a "Keyin" func- * * tion and programmed function keys. The program is ready to run on * * TeleVideo 802s, 803s & TPC-1s. Others will require modification for * * cursor on and off and function key settings. * * The "Keyin" location is set as 17616 because I've modified my dBASE II* * with Gene Head's NEWBASE.ASM file. * * 01/15/85 Originally Written * ******************************< Wes Tyler >****************************** ERASE *--> Cursor Off ? chr(27)+'.0' ? chr(27)+'.0' *--> Set Up Function Keys For *--> a carriage return followed by a symbol ? chr(27)+"|11"+chr(13)+"@"+chr(25) ? chr(27)+"|21"+chr(13)+"A"+chr(25) ? chr(27)+"|31"+chr(13)+"B"+chr(25) ? chr(27)+"|41"+chr(13)+"C"+chr(25) ? chr(27)+"|51"+chr(13)+"D"+chr(25) ? chr(27)+"|61"+chr(13)+"E"+chr(25) ? chr(27)+"|71"+chr(13)+"F"+chr(25) ? chr(27)+"|81"+chr(13)+"G"+chr(25) ? chr(27)+"|91"+chr(13)+"H"+chr(25) ? chr(27)+"|:1"+chr(13)+"I"+chr(25) SET TALK OFF SET INTE OFF *--> Sign On @ 7,37 SAY "CALC.CMD" SET INTE ON @ 8,30 SAY "A dBASE II Calculator" SET INTE OFF @ 9,35 SAY "by Wes Tyler" STORE 0 TO mcount DO WHILE mcount < 150 STORE mcount + 1 TO mcount ENDDO ERASE *--> Menu For The Function Keys Set Above @ 13,34 SAY "F1 = ADD" @ 14,34 SAY "F2 = MULTIPLY" @ 15,34 SAY "F3 = SUBTRACT" @ 16,34 SAY "F4 = DIVIDE" @ 18,34 SAY "F7 = CE/CM" @ 19,34 SAY "F9 = QUIT TO CPM" @ 20,34 SAY "F10 = dBASE II" *--> Initialize memory and entry values STORE 0.0 TO memory, entry *--> Set It to not clear memory STORE F TO clearmem *--> Begin Calculator loop DO WHILE T @ 9,32 GET entry PICTURE '999999999999.9999' *--> Cursor On @ 9,32 SAY chr(27)+'.2' READ *--> Cursor Off @ 9,32 SAY chr(27)+'.0' @ 9,32 SAY chr(27)+'.0' *--> Function Key 'RETURNS' from above read *--> and loads keyin with 'maction' *--> This WILL NOT WORK unless your dBASE II has been modified *--> for a keyin feature at decimal location 17616 STORE chr(peek(17616)) TO maction DO CASE CASE maction = '@' *--> ADDITION STORE memory + entry TO memory *--> Next line sets memory up for display STORE memory TO entry *--> Set It to not clear memory STORE F TO clearmem LOOP CASE maction = 'A' *--> MULTIPLICATION IF memory <> 0 STORE memory * entry TO memory ELSE *--> If memory = 0 assume they wish *--> to multiply this entry to next *--> entry, so change this entry to memory! STORE entry TO memory ENDIF *--> Next line sets memory up for display STORE memory TO entry *--> Set It to not clear memory STORE F TO clearmem LOOP CASE maction = 'B' *--> SUBTRACTION STORE memory - entry TO memory *--> Next line sets memory up for display STORE memory TO entry *--> Set It to not clear memory STORE F TO clearmem LOOP CASE maction = 'C' *--> DIVISION IF memory <> 0 STORE memory / entry TO round STORE INT((round * 10000) + .5 ) / 10000 TO memory ELSE *--> If memory = 0 assume they wish *--> to divide this entry by next *--> entry, so change this entry to memory! STORE entry TO memory ENDIF *--> Next line sets memory up for display STORE memory TO entry *--> Set It to not clear memory STORE F TO clearmem LOOP CASE maction = 'F' *--> CLEAR ENTRY/CLEAR MEMORY IF .NOT. clearmem *--> Set It to clear memory next time through STORE T TO clearmem *--> Next line sets memory up for display and clears *--> entry by replacing it with memory STORE memory TO entry ELSE *--> Set It to not clear memory STORE F TO clearmem *--> Actually clear it now STORE 0 TO memory, entry ENDIF LOOP CASE maction = 'H' *--> QUIT TO CP/M ERASE *--> If memory isn't zero we'll leave it on the screen IF memory <> 0 @ 9,33 SAY memory USING '999999999999.9999' ENDIF *--> Cursor On @ 0, 0 SAY chr(27)+'.2' SET CONSOLE OFF QUIT CASE maction = 'I' *--> QUIT TO dBASE II ERASE *--> If memory isn't zero we'll leave it on the screen IF memory <> 0 @ 9,33 SAY memory USING '999999999999.9999' ENDIF SET TALK ON CLEAR *--> Cursor On @ 0, 0 SAY chr(27)+'.2' CANCEL OTHERWISE STORE memory TO entry ENDCASE ENDDO *< DO WHILE T >* *<< Set It to clear memory next time through STORE T TO clearmem *--> Next line sets memory up for display and clears *--> entry by replacing it with memory STORE memory TO entry ELSE *--> Set It to not clear memory STORE F TO clearmem *--> Actually clear it now STORE 0 TO memory, entry ENDIF LOOP CASE maction = 'H' *--> QUIT TO CP/M ERASE *--> If memory isn't zero we'll leave it on the screen IF memory <> 0 @* * * * Cobbled together by ; * * Ralph L. Smotherman * 4068 Port Cleburne Lane * Hermitage, Tn. 37076 * * fast file backup for dBaseII * this short command file will hopefully minimize the problems * associated with the inevitable dbaseII lost file problem and * at least allow recovery of the data entered in all previous * data entry sessions. * no provision is made for recovery of the index files as they can be * reconstructed from the data file set talk off use FILENAME go bott store # to M:PREVLAST save to DB2BAKUP * * YOUR PROGRAM SHOULD BE INSERTED HERE ******* * restore from DB2BAKUP use FILENAME go bott store # to M:THISLAST go M:PREVLAST skip store str((M:THISLAST-M:PREVLAST),5) to M:NUMBER copy next &M:NUMBER to TEMP1 * * if disk drive capacity allows, I suggest assigning the *.BKP * file to a drive other than that of the data file(*.DBF). * use FILENAME.BKP appe from TEMP1 dele file TEMP1 clear return * * Hopefully this file will be of more value to you than your cost for * the file. * * le backup for dBaseII * this short command file will hopefully minimize the problems * associated with the inevitable dbaseII lost file problem and * at least allow recovery of the data entered in all previous * data entry sessions. * no provision is made for recovery of the index files as they can be * reconstructed from the data file set talk off use FILENAME go bott store # to M:PREVLAST save to DB2BAKUP * * YOUR PROGRAM SHOULD BE INSERTED HERE ******* * restore from DB2BAKUP use FILENAME go bott store # to M:THISLAST go M:PREVLAST skip store str((M:THISLAST-M:PREVLAST),5) to M:NUMBER copy next &M:NUMBER to TEMP1 * * if disk drive capacity allows, I suggest assigning the *.BKP * file to a drive other than that of the data file(*.DBF). * use FILENAME.BKP appe from TEMP1 dele file TEMP1 clear return * * Hopefully this file will be of more value to y* <<<===============================================================>>> * * This program is a mathematics function library for dBASE II. This * file will need to have the function called by a name to exectute the * case. Load the three charcter function code in a variable called * FUNCTION. Load the parameters as required by the function needed and * say : DO MATHLIB * * E X A M P L E * =================== * * store 'SQR' to FUNCTION * store (your value) to NUMBER * DO MATHLIB * * <<<=================================================================>>> * * <<< W A R N I N G >>> * * The following is a list of variables used by this library. Consider * them to be reserved words or your variables with the same name will * be gone. * * A PASS * ABSX POWRX * ATNX RADIANS * COSX RD * CSX RNDX * D * DEGREES S * DELTA SEED * DMS * EXPO SEPX * EXPX SINX * FACT SLOGX * LOGX SNX * LOGO SQRD * M * MD * NUMBER SQRX * NX TANX * * * <<<================================================================>>> * These functions were copied from the October 1984 issue of DATA BASED * ADVISOR magazine. They were written by Keith R. Plossi, Vice * President of George Plossl Educational Services, Inc., of * Atlanta, Georgia. Bob Williams Kansas City District COE * * <<<=================================================================>>> * * M O D I F I C A T I O N H I S T O R Y * ________________________________________ * * DATE--11/30/84 * AUTHOR--Steven R. Burns Kansas City District COE * DESCRIPTION--Several functions have been added to enhance the versatility * of this library. The DMS to DEGREES function changes degrees, minutes, * and seconds in the format DDD.MMSS to decimal degrees which are used in * the Degrees to Radians function. An incorrect value for PI was published * for this function and this has been corrected. In addition, function * routines were written to convert Radians to Degrees and Degrees to degrees, * minutes, and seconds (DMS). Also the SIN, COS, and TAN functions have * been expanded to increase their accuracy. The ATN function has been * commented out, however the original code has been left in place along with * comments on how to make it more accurate. * * * <<<==================================================================>>> do case * <<<==================================================================>>> * * ------>>>> Absolute Value Function <<<<------- * * ------------------------------------------------------ * | Function Call: ABS Input Parameters: NUMBER | * | Output Variable : ABSX | * ------------------------------------------------------ * * case !(FUNCTION) = 'ABS' .AND. TYPE(NUMBER) <> 'U' if NUMBER < 0 store -1*NUMBER to ABSX else store NUMBER to ABSX endif release NUMBER * <<<==================================================================>>> * * ------>>>> Random Number Function <<<<-------- * * ------------------------------------------------------ * | Function Call: RND Input Parameters: SEED | * | Default Seed = .375 Output Variable : RNDX | * ------------------------------------------------------ * case !(FUNCTION) = 'RND' .AND. TYPE(SEED) <> 'U' if SEED <= 0 .or. SEED >= 1 store .375 to SEED endif store (SEED*9821+.211327)-INT(SEED*9821+.211327) to SEED store SEED to RNDX * <<<==================================================================>>> * * -------->>> Square Root Function <<<--------- * * ------------------------------------------------------ * | Function Call: SQR Input Parameters: NUMBER | * | Output Variable : SQRX | * ------------------------------------------------------ * case !(FUNCTION) = 'SQR' .AND. TYPE (NUMBER) <> 'U' if NUMBER < 0 store -1*NUMBER to NUMBER endif store 1 to A, SQRX store F to SQRD do while .not. SQRD store .5*(A + NUMBER/A) to SQRX store SQRX-A to DELTA if DELTA < 0 store -1*DELTA to DELTA endif if DELTA < .000001 store T to SQRD else store SQRX to A endif enddo release NUMBER, A, SQRD, DELTA * <<<===============================================================>>> * * --------->>> Normal Probability Function <<<-------- * * * It computes the area under the normal curve such that * a number of zero yields a 50% or .5000 area. * * * ------------------------------------------------------ * | Function Call: PRB Input Parameters: NUMBER | * | Output Variable : PRBX | * ------------------------------------------------------ * case !(FUNCTION) = 'PRB' .AND. TYPE(NUMBER) <> 'U' store F to FLG if NUMBER < 0 store T to FLG store -1*NUMBER to NUMBER endif if NUMBER < 3.08 .and. NUMBER > -3.08 store .436184 to A store -.120168 to B store .937298 to C store .398942 to D2 store -1.000000* NUMBER*NUMBER/2.000000 to D1 store D1 to NX, POWRX store 1.000000+NX to EXPX store 1.000000 to FACT, PASS do while PASS < 14 store PASS + 1 to PASS store PASS*FACT to FACT store POWRX*NX to POWRX store EXPX to EXPO store EXPX+POWRX/FACT to EXPX enddo store EXPX to DX store DX * D2 to DX release NX, EXPO, EXPX, POWRX, FACT, PASS store 1.000000/(1.000000 + .3326 * NUMBER) to EX store 1.00 - DX * (A*EX + B*EX*EX + C*EX*EX*EX) to PRBX store str(PRBX,6,4) to SEPX store &SEPX to PRBX else store .999999 to PRBX endif if FLG store 1.00 - PRBX to PRBX endif release A, B, C, D1, D2, DX, EX, FLG, NUMBER, SEPX * <<<=============================================================>>> * * -------->>>> Exponential Function (e to X power) <<<<-------- * * ------------------------------------------------------ * | Function Call: EXP Input Parameters: NUMBER | * | Output Variable : EXPX | * ------------------------------------------------------ * case !(FUNCTION) = 'EXP' .AND. TYPE(NUMBER) <> 'U' store NUMBER to NX, POWRX store 1+NX to EXPX store 1 to FACT, PASS do while PASS < 12 store PASS + 1 to PASS store PASS*FACT to FACT store POWRX*NX to POWRX store EXPX to EXPO store EXPX+POWRX/FACT to EXPX enddo store STR(EXPX,12,4) to SEPX store &SEPX to EXPX release NUMBER, NX, EXPO, POWRX, FACT, SEPX, PASS * <<<==================================================================>>> * * ---------->>>> DMS to Degrees Function <<<<-------- * Format for DMS = DDD.MMSS * ------------------------------------------------------ * | Function Call: DEC Input Parameters: DMS | * | Output Variable : DEGREES| * ------------------------------------------------------ * case !(FUNCTION) = 'DEC' .AND. TYPE(DMS)<>'U' store INT(DMS) to D store (DMS-D)*100 to MD store INT(MD) to M store (MD-M)*100 to S store D/1.000000000 to DEGREES store DEGREES +M/60 TO DEGREES store DEGREES +S/3600 TO DEGREES release D,MD,M,S,DMS * <<<==================================================================>>> * * ---------->>>> Radians Function <<<<-------- * * ------------------------------------------------------ * | Function Call: RAD Input Parameter : DEGREES| * | Output Variable : RADIANS| * ------------------------------------------------------ * case !(FUNCTION) = 'RAD' .AND. TYPE(DEGREES) <> 'U' store DEGREES*3.141592654/180.000000000 to RADIANS release DEGREES * <<<==================================================================>>> * * ---------->>>> Degrees Function <<<<-------- * * ------------------------------------------------------ * | Function Call: DEG Input Parameter : RADIANS| * | Output Variable : DEGREES| * ------------------------------------------------------ * case !(FUNCTION) = 'DEG' .AND. TYPE(RADIANS) <> 'U' store RADIANS*180.000000000/3.141592654 to DEGREES release RADIANS * <<<==================================================================>>> * * ---------->>>> Degrees to DMS Function <<<<-------- * Format for DMS = DDD.MMSS * ------------------------------------------------------ * | Function Call: DMS Input Parameter : DEGREES| * | Output Variables: DMS | * ------------------------------------------------------ * case !(FUNCTION) = 'DMS' .AND. TYPE(DEGREES) <> 'U' store INT(DEGREES) to DMS store (DEGREES-DMS)*60 to MD store INT(MD) to M store (((MD-M)*60)+.0005) to S store (INT(1000*(S)))/1000.00000000 to S store DMS+M/100+S/10000 to DMS release DEGREES, MD, M, S * <<<==================================================================>>> * * ---------->>>> Sine Function <<<<------------ * * ------------------------------------------------------ * | Function Call: SIN Input Parameter : RADIANS| * | Output Variable : SINX | * ------------------------------------------------------ * case !(FUNCTION) = 'SIN' .AND. TYPE(RADIANS) <> 'U' store RADIANS to RD store RD-RD*RD*RD/6+RD*RD*RD*RD*RD/120-RD*RD*RD*RD*RD*RD*RD/5040 to SINX store SINX+RD*RD*RD*RD*RD*RD*RD*RD*RD/362880 to SINX store SINX+RD*RD*RD*RD*RD*RD*RD*RD*RD*RD*RD/39916800 to SINX release RADIANS, RD * <<<==================================================================>>> * * ----------->>> Cosine Function <<<<------------- * * ------------------------------------------------------ * | Function Call: COS Input Parameters: RADIANS| * | Output Variable : COSX | * ------------------------------------------------------ * case !(FUNCTION) = 'COS' .AND. TYPE(RADIANS) <> 'U' store RADIANS to RD store 1-RD*RD/2+RD*RD*RD*RD/24-RD*RD*RD*RD*RD*RD/720 to COSX  store COSX+RD*RD*RD*RD*RD*RD*RD*RD/40320 to COSX store COSX-RD*RD*RD*RD*RD*RD*RD*RD*RD*RD/3628800 to COSX store COSX+RD*RD*RD*RD*RD*RD*RD*RD*RD*RD*RD*RD/479001600 to COSX release RADIANS, RD * <<<==================================================================>>> * * --------->>>> Tangent Function <<<<--------------- * * ------------------------------------------------------ * | Function Call: TAN Input Parameters: RADIANS| * | Output Variable : TANX | * ------------------------------------------------------ * case !(FUNCTION) = 'TAN' .AND. TYPE(RADIANS) <> 'U' store RADIANS to RD store RD-RD*RD*RD/6+RD*RD*RD*RD*RD/120-RD*RD*RD*RD*RD*RD*RD/5040 to SNX store SNX+RD*RD*RD*RD*RD*RD*RD*RD*RD/362880 to SNX * store SNX+RD*RD*RD*RD*RD*RD*RD*RD*RD*RD*RD/39916800 to SNX store 1-RD*RD/2+RD*RD*RD*RD/24-RD*RD*RD*RD*RD*RD/720 to CSX store CSX+RD*RD*RD*RD*RD*RD*RD*RD/40320 to CSX store CSX-RD*RD*RD*RD*RD*RD*RD*RD*RD*RD/3628800 to CSX * store CSX+RD*RD*RD*RD*RD*RD*RD*RD*RD*RD*RD*RD/479001600 to CSX store SNX/CSX to TANX release RADIANS, RD, SNX, CSX * <<<=================================================================>>> * * -------->>> Arc Tangent Function <<<---------- * ****THIS FUNCTION IS NOT ACCURATE--IT NEEDS WORK**** * ------------------------------------------------------ * | Function Call: ATN Input Parameters: NUMBER | * | Output Variable : RADIANS| * ------------------------------------------------------ * These series functions need to be expanded to at least NX**41/41 to be * accurate to the nearest 0.1 seconds when converted to DMS. *case !(FUNCTION) = 'ATN' .AND. TYPE(NUMBER) <> 'U' * store NUMBER to NX * if NX*NX < 1 * store NX-NX*NX*NX/3+NX*NX*NX*NX*NX/5-NX*NX*NX*NX*NX*NX*NX/7; * to RADIANS * store RADIANS +NX*NX*NX*NX*NX*NX*NX*NX*NX/9 to RADIANS * store RADIANS -NX*NX*NX*NX*NX*NX*NX*NX*NX*NX*NX/11 to RADIANS * These series functions need to be expanded to at least 1/(41*NX**41) to be * accurate to the nearest 0.1 seconds when converted to DMS. *else * store 1.570796327-1/NX+1/(3*NX*NX*NX )-1/(5*NX*NX*NX*NX*NX) to RADIANS * store RADIANS+1/(7*NX*NX*NX*NX*NX*NX*NX)-; * 1/(9*NX*NX*NX*NX*NX*NX*NX*NX*NX) to RADIANS * store RADIANS+1/(11*NX*NX*NX*NX*NX*NX*NX*NX*NX*NX*NX) to RADIANS *endif *release NUMBER, NX * <<<=================================================================>>> * * ---------->>> Natural (Naperian) Logarithm <<<--------- * * ------------------------------------------------------ * | Function Call: LNX Input Parameters: NUMBER | * | Output Variable : LOGX | * ------------------------------------------------------ * case !(FUNCTION) = 'LNX' .AND. TYPE(NUMBER) <> 'U' store (NUMBER-1.000000)/(NUMBER+1.000000) to NX, POWRX, LOGX store 1 to PASS do while PASS < 14 store PASS + 2 to PASS store POWRX*NX*NX to POWRX store LOGX to LOGO store LOGX+POWRX/PASS to LOGX enddo store 2.00*LOGX to LOGX store STR(LOGX,12,4) to SLOGX store &SLOGX to LOGX release NUMBER, NX, LOGO, POWRX, PASS, SLOGX * <<<=================================================================>>> * * ------------->>> Otherwise Undefined <<<----------- * * otherwise store 'UNKNOWN' to FUNCTION endcase if FUNCTION <> 'UNKOWN' release FUNCTION endif return ------ * * otherwise store 'UNKNOWN' to FUNCTION endcase if FUNCTperian) Logarithm <<<--------- * * ------------------------------------------------------ * | Function Call: LNX Input Parameters: NUMBER | * | Output Variable : LOGX | * ------------------------------------------------------ * case !(FUNCTION) = 'LNX' .AND. TYPE(NUMBER) <> 'U' store (NUMBER-1.000000)/(NUMBER+1.000000) to NX, POWRX, LOGX store 1 to PASS do while PASS < 14 store PASS + 2 to PASS store POWRX*NX*NX to POWRX store LOGX t Maximizing Performance with dBase II and III by Alan Simpson Reprinted from "Personal Systems", The Journal of the San Diego Computer Society Issues of November and December 1984 and January 1985 Typed and Formatted by Rick Yount, Oak Harbor, WA (206) 675-9797 This article may be reprinted for any non-commercial purpose; please credit the Author and "Personal Systems". TABLE OF CONTENTS: Trimming Minutes Down to Seconds ........... 1 Don't Resort to Re-Sorting ................. 2 Faster Sorts ............................... 4 Faster Searching ........................... 4 Faster Math ................................ 5 Faster Reports ............................. 6 Faster Copying ............................. 6 Faster Edits ............................... 7 Searching for Ranges ....................... 8 Estimating Performance ..................... 8 Managing Multiple Index Files .............. 9 Trade-Offs ................................ 10 Technical Rationale ....................... 12 Everyone wants the most out of their computer. Granted, it's nice that the computer can trim down to minutes what usually requires humans hours to perform. But then, nobody complains if those computer minutes can be trimmed down to seconds. In this paper we'll discuss and compare general techniques for maximizing the performance of dBase. We'll trim some of those long dBase processing minutes down to quick dBase seconds. TRIMMING MINUTES DOWN TO SECONDS We'll begin by benchmarking (comparing) a few techniques for performing some basic tasks with dBase II. We'll use a simple mailing list database as an example. Its name is MAIL.DBF, and it has this structure: FLD NAME TYPE WIDTH DEC 001 LNAME C 020 000 002 FNAME C 020 000 003 ADDRESS C 020 000 004 CITY C 020 000 005 STATE C 010 000 006 ZIP C 010 000 007 AMOUNT N 009 002 First, let's discuss various methods for sorting this database: ---------------------------------------------------------------- Maximizing dBase II and III Performance - by Alan Simpson Page 1 DON'T RESORT TO RE-SORTING There are basically four methods to maintain a sorted list of items in a database. The first is to simply CREATE the MAIL database, add records to it, then sort it with the SORT command. For example, suppose you CREATE MAIL and APPEND 999 records to it. To add another record to it, and maintain an alphabetical listing by last name, you would need to use the commands: USE MAIL APPEND SORT ON LNAME TO TEMP This procedure would require about 940 seconds to re-sort a database with 1000 records in it. Another method would be to USE MAIL, APPEND the new record, then INDEX the file on the LNAME field, using the commands below: USE MAIL APPEND  INDEX ON LNAME TO NAMES This procedure requires about 530 seconds to re-sort the 1000-record database back into last name order A third method would be to locate the position in the database that the new record belongs, and INSERT a new record into its proper alphabetical place, as below: USE MAIL LIST (to find the insertion point) INSERT The time required would be however long it takes you to find the appropriate place to insert the new record, plus about 124 seconds for the INSERT command to rearrange the database. The fourth method is to create an index file of the field to sort on, and keep that index file active while adding the new record(s). In most cases, the best time to index a file is immediately after creating it, as in the commands below: CREATE MAIL USE MAIL INDEX ON LNAME TO NAMES It only takes about two seconds to create the index file when the database is empty. At this point, the MAIL.DBF database and the LNAME.NDX files exist on disk, but both are empty. To add new data, you would need to make the NAMES.NDX file active by typing in the commands: ---------------------------------------------------------------- Maximizing dBase II and III Performance - by Alan Simpson Page 2 USE MAIL INDEX NAMES If you always USE MAIL INDEX NAMES when you add new data, the index file will automatically be updated, therefore the data will always be sorted. So to add one record to the MAIL database with 999 records in it, you would type the commands: USE MAIL INDEX NAMES APPEND   There is no need to go through the INDEX ON procedure again, because the NAMES.NDX file was active during the appending procedure. The time required to automatically re-sort the index file using this method is a scant 3 seconds. Add to that the original two seconds for the INDEX ON command to create the initial index file for a total of 5 seconds. Table 1 compares the processing times for the four methods (using a 16-bit computer with 256K RAM, floppies, and dBase II Version 2.4): ------------------------------------------------------- Method Commands Used Time Required 1 USE, APPEND and SORT 940 seconds 2 USE, APPEND and INDEX ON 530 seconds 3 USE, INSERT 129 seconds 4 USE file1 INDEX file2 APPEND 5 seconds ------------------------------------------------------- Table 1: Sorting Times; Four Different Approaches Remember, you need to first create an index file based upon the field(s) you wish the database to be sorted by. Use the INDEX ON command to create the index (.NDX) file. For example, to maintain an alphabetical listing of people on the MAIL database by last name, type in the commands: USE MAIL INDEX ON LNAME TO NAMES This creates and stores an index file called NAMES.NDX on disk. To make the index file active, specify its name in the USE command, as below: USE MAIL INDEX NAMES Once the file is made active in this way, any changes to the database, whether they be through APPEND, EDIT, BROWSE, REPLACE, PACK or READ will automatically re-sort and adjust the index file accordingly. Avoiding the re-sorting process on only one way in which index files can greatly improve the speed of a dBase II software system. Most types of processing that involve searching can also be accelerated. ---------------------------------------------------------------- Maximizing dBase II and III Performance - by Alan Simpson Page 3 FASTER SORTS In some cases, a database should be physically sorted rather than indexed. For example, the UPDATE command works best if the file you are updating FROM is physically pre-sorted. You could use the SORT command to create a sorted database called TEMP from the MAIL database using the commands: USE MAIL SORT ON LNAME TO TEMP This approach takes about 940 seconds, or about 15 minutes of processing time. If the NAMES index file already exists, you can  achieve the same result using the commands: USE MAIL INDEX NAMES COPY TO TEMP Copying the contents of the indexed file only required about 326 seconds of processing time; about one-third the time. When you COPY an indexed file to another database, the records on the database you copy to will be physically sorted. FASTER SEARCHING Let's assume that the MAIL.DBF database already has 1,000 records on it. Ten individuals on this database have the last name (LNAME field) "Miller". The question is: Just how long does it take to LIST, COUNT, or COPY all the "Miller"'s to another database; or how long does it take to print a formatted REPORT with only "Miller"'s, or to SUM the amounts for the "Miller"'s? The answer, of course, is: It depends on how you do it. For our benchmark comparisons, we'll assume that the database has already been indexed on the LNAME field, using the commands: USE MAIL INDEX ON LNAME TO NAMES Let's begin by comparing processing times using two different command files and approaches. The first method will use the standard LIST FOR approach to fish out all the "Miller"'s. The command file looks like this: ********** Method 1: LIST FOR approach ERASE USE MAIL INDEX NAMES ACCEPT " List all with what last name? " to SEARCH LIST FOR LNAME=SEARCH When you DO this command file, it clears the screen and displays the prompt: List all with what last name? ---------------------------------------------------------------- Maximizing dBase II and III Performance - by Alan Simpson Page 4   Suppose you type in the name "Miller" and press the RETURN key. The program will then display the records of all ten "Miller"'s on the screen. The time required for the command file to display the "Miller"'s and return to the dot prompt is about 148 seconds on a floppy disk system. Almost two and a half minutes. A second approach to solve this problem is to use the FIND command to look up the first "Miller" in the NAMES index, then use the WHILE option to display the remaining "Miller"'s in the database, as in the program below: ********** Method 2: FIND and LIST WHILE approach ERASE ACCEPT " List all with what last name? " to SEARCH FIND &SEARCH LIST WHILE LNAME = SEARCH Processing time for the second method to display all 10 "Miller"'s then redisplay the dot prompt on the screen, is less than 9 seconds. Table 2 compares processing times for the two different methods. Both methods perform exactly the same task, but the processing times vary dramatically. ------------------------------------------------------- Method Commands Used Time Required 1 LIST FOR 148.75 seconds 2 FIND and LIST WHILE 8.94 seconds -------------------------------------------------------- Table 2: Comparison of Processing Times; Two Methods FASTER MATH The FIND and WHILE approach with indexed databases can offer significant time savings with dBase commands other than LIST. For example, if you want dBase to COUNT how many "Miller"'s are in the database, you can use the commands: USE MAIL COUNT FOR LNAME = "Miller" This approach requires about 55.5 seconds to display the fact that there are 10 "Miller"'s in the database, then redisplay the dot prompt. You can cut this time down significantly using the commands: USE MAIL INDEX NAMES FIND Miller COUNT WHILE LNAME = "Miller" This approach performs the same task in about 3.20 seconds; quite a significant time savings. ---------------------------------------------------------------- Maximizing dBase II and III Performance - by Alan Simpson Page 5 Suppose you wish to SUM the AMOUNT field for just the "Miller"'s? You could use these commands: USE MAIL SUM AMOUNT FOR LNAME = "Miller" Processing time using this method is about 58 seconds. The alternative approach uses these commands: USE MAIL INDEX NAMES FIND "Miller" SUM AMOUNT WHILE LNAME = "Miller" This approach takes 5.28 seconds; less than one-tenth the time. FASTER REPORTS You can use the WHILE command with the REPORT command, also. For example, suppose you've already created a formatted report called MAILIST using the REPORT command. To display all the "Miller"'s on the formatted report, you could use the commands: USE MAIL REPORT FORM MAILIST FOR LNAME = "Miller" This approach requires about 135.3 seconds to display all the "Miller"'s on the report, then redisplay the dot prompt. The faster approach uses these commands: USE MAIL INDEX NAMES FIND Miller REPORT FORM MAILIST WHILE LNAME = "Miller"  These commands perform the same job in a slim 14.03 seconds. FASTER COPYING For copying portions of the MAIL database to a database called TEMP, the commands: USE MAIL INDEX NAMES COPY TO TEMP FOR LNAME = "Miller" require a hefty 200.6 seconds; more than three minutes. You can perform the same job using these commands: USE MAIL INDEX NAMES FIND Miller COPY TO TEMP WHILE LNAME = "Miller" These commands trim the copying time down to a comfortable 18.7 seconds. ---------------------------------------------------------------- Maximizing dBase II and III Performance - by Alan Simpson Page 6 FASTER EDITS Indexed files can also speed up the editing process. For example, suppose you want to BROWSE through t he database to edit data for one of the "Miller"'s. One approach would be to type in the commands: USE MAIL BROWSE These commands will set up the dBase BROWSE screen with the names and addresses in their original order, as displayed in Figure 1: LNAME--------------------FNAME------------------ADDRESS Bond James 007 Spy St. Kenney Dave 123 Clark St. Newell Jeff 341 Lou Drive Mohr Richard 350 W. Leadora St. Rosiello Rick 999 Buddy Way Wallace Doug 345 Killer St. Miller Mike 601 Lemon Dr. Figure 1: An unindexed BROWSE screen. You will need to use lots of CTRL-C commands to scroll through the database to find the "Miller" you're looking for. There's no telling how long it might take you to find the particular "Miller" you wish to edit, because the "Miller"'s will be placed randomly throughout the database. If, on the other hand, you use these commands to BROWSE: USE MAIL INDEX NAMES FIND Miller BROWSE The BROWSE screen will display the first "Miller" on the database, and all the remaining "Miller"'s immediately beneath, as shown in Figure 2: LNAME--------------------FNAME------------------ADDRESS Miller Mollie 601 Mission Blvd. Miller Shiela 1234 Genessee Miller Ms. Stephanie S. 734 Rainbow Dr. Miller Patti 626 Mazda Way Miller George P.O. Box 2802 Miller Julie 999 Love St. Miller Caron 123 Princess Way Miller Ms. Chrissie 321 Hynde St. Miller Mrs. Sally S. 325 Seco Ct. Miller Dr. James T. 701 Newport Dr. Figure 2: A BROWSE screen with an indexed database ---------------------------------------------------------------- Maximizing dBase II and III Performance - by Alan Simpson Page 7 No need to go scrolling through pages and pages of BROWSE screens to find the "Miller" you wish to edit, because all ten "Miller"'s are displayed immediately and simultaneously on one BROWSE screen. Similarly, if you wish to use the EDIT command to change the  data for a particular "Miller", you can use the commands: USE MAIL INDEX NAMES FIND Miller EDIT WHILE LNAME = "Miller" These commands will quickly display the first "Miller" in the database on the EDIT screen. Each subsequent CTRL-C command will immediately position you to the next "Miller" in the database. So once again, you can save a great deal of time by not having to scroll around and search for individual "Miller"'s. SEARCHING FOR RANGES The FIND and WHILE approach can also be used for searching for ranges of data. For example, if a database had a DATE field with dates stored in MM/DD/YY format, and the database was indexed on the date field, the following command file would list all records between the requested starting and ending dates: USE file INDEX datefield STORE "  " TO START, FINISH @ 2,2 SAY "Enter Start Date " GET START PICTURE "99/99/99" @ 4,2 SAY "Enter End Date " GET FINISH PICTURE "99/99/99" READ FIND &START LIST WHILE DATE <= FINISH (This command file assumes that all dates have the same year. It's a little trickier when the data is spread across several years ESTIMATING PERFORMANCE Performance can be an important issue in developing a custom dBase II software system. Generally, processing times tend to increase linearly with the size of a database. Therefore, on a database with 5,000 records in it, displaying all the "Miller"'s could take as long as 740 seconds, a little over 12 minutes, with the LIST FOR approach. Using an indexed file with the FIND and LIST WHILE approach will perform the same task in about 45 seconds, less  than a minute. Double those times for a database with 10,000 record in it: A whopping 24 minutes (almost a half hour) with the FOR approach, vs. 88 seconds (under a minute and a half) with the FIND and WHILE approach. ---------------------------------------------------------------- Maximizing dBase II and III Performance - by Alan Simpson Page 8 Keep in mind that any dBase command that allows the FOR option will allow the WHILE option instead (e.g. LIST, DISPLAY, COPY, REPORT, SUM, COUNT, REPLACE, DELETE, TOTAL). Therefore, any of these processes can be greatly expedited with an index file and the FIND and WHILE commands. MANAGING MULTIPLE INDEX FILES In the previous examples, we compared processing times using an index file called NAMES. This index file contains only the LNAME field. Realistically, a mailing list will probably require two separate sort orders; 1) a sort by last name and first name for printing a directory listing, and 2) a sort by zip code for bulk mailings. In that case, you need to create two index files to manage the two different sort orders. One index file, which we'll call NAMES, will keep the mailing list data in last name and first name order. A second index file, which we'll call ZIPS, will maintain a zip code order for handling bulk mailings. To create both of these index files, you'll need to first CREATE the MAIL.DBF database with the CREATE command, then immediately create the two index files using the commands: USE MAIL INDEX ON LNAME + FNAME TO NAMES INDEX ON ZIP TO ZIPS The MAIL.DBF database now has two index files associated with it; NAMES.NDX and ZIPS.NDX. You can keep both index files active by using the command: USE MAIL INDEX NAMES,ZIPS By specifying two index files in this fashion, all future modifications to the database with the APPEND, EDIT, BROWSE, READ, or REPLACE commands will * * AUTOMATICALLY * * update both index files. If you LIST or DISPLAY ALL the records in the database, they will be displayed in last name order, since NAMES is the first- listed index file in the INDEX portion of the command line. Furthermore, you can only use the FIND command with the first listed index, NAMES. Therefore, to display all the records in the database in zip code order, you need not go through the INDEX ON ZIP TO ZIPS procedure again. Instead, you can simply type in the command: SET INDEX TO ZIPS This eliminates the time required to sort the file again.  Before adding new records or editing the database, be sure to use the commands: ---------------------------------------------------------------- Maximizing dBase II and III Performance - by Alan Simpson Page 9 USE MAIL INDEX NAMES,ZIPS or USE MAIL INDEX ZIPS,NAMES This is required to make both index files active again. Otherwise, you'll be likely to get a RECORD OUT OF RANGE error sometime in the not too distant future. TRADE-OFFS There are some trade-offs to contend with when using multiple index files. Generally, the more index files you have active at any given moment, the longer it takes to perform an APPEND, EDIT or REPLACE procedure. For example, if you want to add records to the MAIL database without any active index files, you can just use the commands: USE MAIL APPEND As you type in each new individual's data, the screen will immediately accept each new record and re-display the next APPEND screen. However, if you decide to get carried away and create four index files, and keep them all active as: USE MAIL INDEX NAMES, ZIPS, CITIES, STATE You will notice a definite delay between the time you fill one APPEND screen and the appearance of the next blank APPEND screen. On a large data file with over 1,000 records in it, the delay could be as much as 20 seconds, depending on how many fields are in each index file and the RAM capacity of your computer. In general, one or two active index files are sufficient for most databases. The delays caused by one or two active index files are relatively insignificant, and are more than compensated   for by the time savings that the FIND and WHILE commands offer, as well as by the time savings gained by avoiding re-indexing. Another disadvantage to indexed files occurs during global replaces. For example, if for some reason you wished to set all the AMOUNT fields back to zero in your hypothetical MAIL database, you could use the commands: USE MAIL INDEX NAMES,ZIPS REPLACE ALL AMOUNT WITH 0 On a database with 1000 records in it, this process could easily take 45 minutes. However, the commands above waste processing time by updating the index files when it is not necessary to do so. ---------------------------------------------------------------- Maximizing dBase II and III Performance - by Alan Simpson Page 10 Recall that the NAMES index contains the LNAME and FNAME fields, and the ZIPS index contains the ZIP field. The AMOUNT field is not used in either index file. Therefore you can use the NOUPDATE option (supplied in dBase Versions 2.4 and higher) to perform the replace. These commands: USE MAIL INDEX NAMES,ZIPS REPLACE NOUPDATE ALL AMOUNT WITH 0 perform the update in about six minutes. The NOUPDATE option informs dBase that, even though there are two active index files, there is no need to update them while performing this REPLACE command. There are some important points to keep in mind about the INDEX and FIND commands. First, the FIND command only works on an indexed field. If a database is in use with multiple index files, the FIND command only works with the first listed index file. For example, if you open the MAIL data base with the two index files as below: USE MAIL INDEX ZIPS, NAMES the FIND command can only be used to locate a zip code. If the data to look up in a database is stored in a variable, then the variable name must be "macro-ized" to be used with the FIND command, as below: ACCEPT "Look up whom? " to SEARCH FIND &SEARCH Also, FIND does not support functions or operators. That is, you cannot use the commands: FIND Miller .OR. Smith or FIND !(&SEARCH) nor FIND LNAME > &SEARCH. If you create two index files, but later add, edit, or delete data with only one or neither of the index files active, the index files will be corrupted, and you will most likely get a RECORD OUT OF RANGE error at a later time. In this case, both index files must be re-created by typing in the commands: USE MAIL INDEX ON LNAME + FNAME TO NAMES INDEX ON ZIP TO ZIPS or . . . USE MAIL INDEX NAMES,ZIPS REINDEX Again, you can avoid the re-indexing by always keeping both index files active with the command USE MAIL INDEX NAMES, ZIPS when working with the database. ---------------------------------------------------------------- Maximizing dBase II and III Performance - by Alan Simpson Page 11 TECHNICAL RATIONALE From a technical standpoint, the reason that the FIND and WHILE approach always dramatically outperforms the FOR approach is quite simple. Whenever you use the FOR option to perform a search, dBase always starts accessing the records from record number 1 and reads every single record directly from disk. Therefore, if you had a database with 10,000 names in it, ten of which were "Miller", dBase would perform 10,000 disk accesses to display the 10 "Miller"'s. Ten thousand disk accesses takes a very, very long time. Many unnecessary disk accesses can be avoided by the fact that dBase always stores an active index file in RAM (at least, as much of it as will fit in RAM). Furthermore, the index file is always in sorted order in RAM. When you use the FIND command with an index file, dBase finds the first "Miller" in the index file in RAM, which requires no disk accesses. Furthermore, the WHILE option only searches WHILE (as long as) the search condition is true. Therefore, dBase will stop searching as soon as it encounters the first non-"Miller" in the index file. Since the index is already in sorted order, "Miller"'s are all clumped together and disk accesses will stop as soon as all the "Miller"'s have been displayed. So the FOR command requires 10,000 disk accesses to display the ten "Miller"'s, while the FIND and WHILE approach only requires 10 disk accesses; thereby eliminating 9,990 unnecessary disk accesses and about 20 or 30 minutes of time depending on the size of the database, the amount of RAM your computer has, and the speed of your disk drives. - EOF - ---------------------------------------------------------------- Maximizing dBase II and III Performance - by Alan Simpson Page 12 ed order, "Miller"'s are all clumped together and disk accesses will stop as soon as all the "Miller"'s haveåZZRUi#e!bÕ>P  =WW. @[(:V?!Sͦ}7~ êR}M~>Xê!So$a{ A[ z{ɯ> w#€ɯWyr# É4#4+_͘~ɇ͘~#fo~ #ï ?A[?0:? ~#  w#  w+ x~# x~+ ssɹyɹy* }X`6 {:VXK 'X}`'X}`*}ʄ+++"V*"V!V~6#w:Vb"B>>24! +++:VODMC*}ʰRSCSC/ #m%-6DRaky$4EQ_m|No erroDisk i/o erroEnd filDisk fulFile not founDuplicate namParameter erroLock erroRead only filRead only disSelect erroReclen erroSystem erroFile not opeInvalid file namInvalid file numbeFile opeWrong file typMemory overfloInsufficient datNumeric overfloInvalid argumenArray index erroNext w/o foInvalid returStack overfloData type erroChain erroDivide by zerLog erroSquare root erroNumeric range erroDDIM erroUser function erroErro>> >>>>>>">2V?>!>!>"!>!>!>!>.V$ V+ :VO# ~3A*+w+ @p+ !%ڦ>%æV+ j2.Uɯ2-T*V"V*,Z+"*"V*V"ɯ>2VB>Øy͒y U Ԓͭ##ͭX6#6ͭ##ͭXs#r>I:O~A?͖S >͖S ! Z:Gy Z>I7 -:O@~U ~_ # > h ~~# R x! Z:O ~## u ! Z:GOy Z~ A Gڸ ³ #~2ڹ #y͘~ ~# ! ZGyOu x-&! Z:Gy<2 ! Z:Ou &! Z:Gy Z2 ! Z{- >@m M M M M  P _x/Gy/O {BѰx<*~#= ʌ =ʘ é *#^#"*#^#V#"*#*&"<*#*&"<*++"6#*+++"6#:*O}o|g+"6#: +6#*N! n`#>Ⱦ~y~#=$ + =  _Ͷ s^#V s#rm z6 >@ {6 c {2V?>2V>h =h ʋ =ʄ m" h ʢ =`"  6 sm s#ry #N * +6" +wO *#N# "#*}o|g++"6#q#m m Xy Yy X!YX͐ X͐ X!XX͐ Y͐ XY`i !9"Vo:=}ʍ ,ʖ |!R ͟>> !>!> !> *V>r :V%:  :=r r r r :V r :V2V= r >  !r !b ͟"I #r :*I +I .r *V##!Jar &S!VO+{ s~< 6 !ͼ'!'*V-:=*V*VQ Y& !Vq!.U4~ O r+s>.!.U~5O V+^!.U54>.m $ m + 6 m s s#r6 {2N_& 6 6 {2g} ^y& !S h ʝ=ʔX͛!X XͶÎXÎ:O# ­:=O~6 #60#6 6> >-~#@GG=.y&~0 ~0# 02.?> {w~0 ^>.~0# J>EG>+x= |:Gy0x?>-x/z>I> Ҫ->-:O~~# ²>0~0~0# > p&> R> {wɯ2V2\ >2V!"}!Zͬ*!Z͈*V*.Zs>:VF*0Z#"}Q*2Z*0Z͔*6Z*4Z͔*:Z*8Z͔*>Z*7>7?ͬڧ +}”}7 \G !}͒Z"V!V~6*2Z#*6Z#*V"V"V*:Z p#p#~^#V#N#F#͇^#V#~H T 1#~w#6#1!#N#h1^#V#ͪ}ʋcO##ͪ}ʋcO q#p# {*V#"V:ʜ=}Ü2V:V !V:V~6a&%_:4By4.:^4{<!V:Vw:V2V!V:Vw:V/2V!V ͤ ͤ!BF!  _>F_mͰâͰâmâ ~#q!4q͔>X24͔>ÅU 2V!"V:V7̮1:4:V 7G p"/ !S V$ & &   ~!Vq#w"V*V^#V#"V{ *V++"V>.*~#MFͧ:O 7>+'w 9~wm -m >m {/_z/W/ }_|W/ }_|W/ }_|W/ {/_z/W/ }/_|/W/ K !V~6CX͐ !VX`"VX!XV~ws!XV`"X *V#"V}'o|'g"V@ XK A{*~#?>I-~w#/ h nn=c>Iͧh~{h :4W@w#6:@ X*#{Nsi&O @ X*#{~O s+ @ XK *#~w+6"Ë_r+ 6 {   25*~#G ÁQ*~#A/~6e:==OO:o&&N$ a]$ F%h =+"#:=O~A#+:͘Oʛw+“p+ #6:O#T]~## «}o|g Sm>@G~aE=0  #:O6#~pT]##~ ,# GG~-^Z+># f# f/<~>~# 0W~0_~z؇# "V!"V`i"V!X:_ w#£DMX*V͝*VDM*V*V:GO+w+w͈!XG:Oxw# X͈ ;o`i,/<:=27@`"VX:=O#~ OXmO+ fy#T]~P+tF#:=O 7>'+ –:=Ox'w+ ?µT]:G#w:=O#~ 6 :=2x2X :OG :=Od":=O '+ ,A`">~~x>p:O :=o&~~P+:=O>É:O>'w+ >‰ :=o&T]շ'w+ª:G 7>'+ڽͧy ͈:o& DM!X:=͘6+= !X:͘:=!X͘ K:=GOͧ>w >o:G!X<͘Oͧ f+=+X:/_?zWa͕G~@ʶ>>G怰X:/_?zW`" >͈:o& w`i#"qX!X:G͘w+p!X:͘!X:͘Ww++:=W w+6rX:O!X:͘ͷG!X:<͘ͷ*qXw#"qX Fa͕goAʬ>>W{怲*#NA#X#~+"ɀ>G>Nw+{ozg "HX@ X{>*#~>o&TcOs*#Ns{G+}_|W "w#5  +*#JPN T]##~͘ +*#O + +y ~ڧ ~F#ʈ˜Y&  + +y G~<y͘#Y& >>>>2!7!"qW;)>)>)>)>2!!!qW6#6#6!SZ ~#foP>$.:O! *V=p!qWr+s+*~=#N "+ #ͦ#+w+6b*Vs>.#N#"#ͦ#+q+6b#N#F#"##ͦ#+p+q+6b#:O "+ ͦ#+6b#:O "+ ͦ#+6b!qW~ 2##N * !qW~ 2##N#Fyh++]+cc##w#w`i>.####N#Fyh+++O#++ڠG~ڠ™+~#ڠp+q###w#w~#h*#~J wQ:O*# # "P:OV+^w+w wQ:O*# # "P~#h*#~R  ́Q:O*# # "'P: ́Q:O*# # "'P: + !qW6yY͐ !yY~ Ҝ -?@2.W#"/W:=21Wx22WB!qW#~ 9 Z * $ V ù ù ù ù T]#:qW=2qWc"z!:.WO:2W-!y!xP" x!qWO P"Z#~,t! ʍ!9=!60W'!ZH!6 W'!$b! W'! +~$U!6 '!*k!W'! Z"'!z9'!6**'!6 $'!6$T!˜!$˜!#Wz23W*/W+#~Z"9!Z!$!*!,¢!+~-#¢!+:3W6 $!*!6*!6$+~$!6 #6-â!:2W-+"~9"."6-22Wâ!60+~0"."#~.%"+6-":1WK"=21W?"C"0wâ!60â!!qWF>?#}!qW :O~# d":O~# q"#ڂ"~O#~# ˆ"͘"ê :V2V͜©"<͘"ʪ "B=]B͘"ʪ "C]RS[:V="!FZ # # # #͜ʪ N#^#V# <# S# Y# _##N  # :#^.#$ {*#~<͘"%#+ ?# ?# ?#m !SZ s#rV+ m *Vs*Vs"V"VV$ K K ͜w#±#m  z#{>0w##m  z#{O#w#y#w#0:m  z${0w#$ ^y&  ^#V>/  :=`$6 :=T] O 6"6  sm  s#rXy :è$X͐ :O Xh/ R1G :R1G Rh/ :RV$ V$ V!V$V!V:4$ $ 6 6 y2V{2V!:4"%"V"VG=*#~<&%_%î? ͭ%=!X6!X4N w͑%ʌ%:X҇%:0GͪV\%!&w%y!XJP >Җ%!Z͜wͷ%T%=%%%Ҳ% %ò%_xҲ%#ò%ʭ%+'ò%ʭ%'%:Vw"Z!Z"Zx*.&*,&**}!+}&{&:V7&:V=>&:4Y&c&:V&%È&:V&%â&:V&%÷&K K:4ܘ&ܭ&:V/<,& y=Ž&â:Vҫ&/< =¤&:V&/<,&& B=¿&K K C:4'&:Vҁ&/<3&ʁ&=&Á&:VҮ&/<3&ʮ&= 'î&y2Vx2V ((&:4l'~':'V' :V=Ĥ!"Vâ!V:V<3&=b'â!ͼ'!"V&:'ʚ' :V=m!"V!V:V<3&ʯ'=¨'ͷ'&:4V#^4ý':4'V#^m'V#^ͤ'' 4:V='2V!sͼ'!z':`=y`O!ͼ'!@(G(:=,(>!ͼ'>!ü':K(:_:=4={^(df(z f(z/h(W4!ñ'!ñ'! ʉ( ͼ'&!Á(!&É(!Á(! Á(6 !ͼ' &î(6 >! cO;(J'â;(ü':)?!_6 !"V::)<.)a)Xa)X{_~w>?!_V!S> ʒ)= 'âV!EÅ)* 'PX X * ä) yͯ+)-)#2VyY!yY~< :V-  * }>.O/ IY͐ 1Y͐ 1YIY!yY:VXyY IY R 1Y iQ K m G{_zW+~#HO!LWp#q#s#r#y~#*y2RW *K *{2SW+*+*6+*PW*NW:SWO*PW!TWh!y͟2SW+*+*6+*PW*NW*JWDM*PWÇ>#.:LWO!SW m r+s+ +*TW*VWcO"\W*XWcO"^W*V"PW!PW]+"JW*PW*Vs"V"V###^#ͪ}s+cO##f+"NW^6#V6{"PW+]+*PW"JW*V͡O*PW"V"V*JWDM*PW*:Z######~++~+ngs+>͘+~w#~w>͘+*Vs#r#*V!-T4~, ͘r+s>͘s#r#~#͘%,`,H,:C,:C,*Vsq,>."V+V+^+~<ʨ,,ʿ,,,>*#N "x,6 {Ҩ,Xm s#r:Vʨ,X͐ ,y ,!-T~5,=ͪ͘"Vͪ>$.---!-T~=ͪ͘ ^#Vm >.!PW!PW~#72---(-*TWs--*SW&cO*PW2---(-*VWs--"fW(-*TWs--"dW*fWcO*dWU-2---(-*XWs--"hW(-*VWs--"fW(-*TWs--"dW*fWcO*dW*hW*\WcOU-2---(-*ZWs--"jW(-*XWs--"hW(-*VWs--"fW(-*TWs--"dW*fWcO*dW*\W*hWcO*^W*jWcOU-$ @ X@ X{2y2!qW ":*Vʮ.}oî.@ X{22!qW"*V"V {qWO.~#ͷ. .:Gy6:/!qW~./_#4.:/:_4#~.:*Vo"V71*+~ͷc/ɇ!͘ > ͟1:> ͟_x#~¬1> »1 ð:\_ 1####F:4WêG17*Z*Zs1>.:VO~ 22>.#1+2-2#2VyY:yY 2~=2 >2#/2#*ZsI2"Z!yY :V- *Z*Zs1:V™2͡Ox}2>Ҁ2 +A*+p+6"*Z"Z:V#Ÿ2"Zsҳ2"Z++x2>2A*+p+ >2$ >2+ :2 :2 O*Z*Z "Zs1N*Z*Z#s"Z+qN#F*Z*Z#s3#"Z+p+q:O*Z*Z{_zWi&DM "Z:>3*~#^#"*Z*Z͡O“3ړ3yO"Z**Z!Z"Z"Z*Z!Z͡Oy&%_& g3U XB 4X 4X###+ 4X+ 4U Bm "$W 4"&W:V \& *&W~W4*$W}+"(W!",W###ͪ""W*$W}#"$W͵9{4!Ã4:*Wƒ4+*$W+"$W͵9{ozg#",W41:4141:4:V42V1*(W"}*,W\t +}*}#"}4*(W"}*,W\o +}*}#"}54 X ^#V/ 4 5m 4Xq#p\5 B5\5 B5m {46 { KX!e{͙5͙5͙5\B Xܕ># 4X;5;5;5_& 45#U XqW k61 55 55>55y2qWU X:V5qW k61 66 55!V5>66U XK K k61f64 X6‚6:VB"&W6*&W>͘4~?ܠ6&͟ž65^#V, ~+¹6~6͒6>w! G 5>!qW :##~++=>͟66:VB#~6#~=:4! Y *&W#~#~=:g9B6#~6#~++f76>͘4~?{7&͘s'! Y گ7"^#Vr+s ͪs#r>w +U B7>͟75͟ 7:V G7 W _:VG77Ͷ7 :VG7 :VG771:V"8Ͷ7:V_8Ͷ7 84X"&W ͒ͪ"$W[8m "$W4X"&W:V*$W}*&W>ͧ*$Ws*&W~ʀ8###ͪ""W͵91͊91!Z"Z*"W"Z:Vw91:*WO>_*"W*"W}o|g""WK*&W:*W͘6*Z"Z*"W}9*(W#"(W͊9191*"W*"W}o|g""WK*&W8!Z"Z*&W#~D9>0ͧ*(WsD9:*&W##~=*&W#6!*(Ws#r#### G *&W#6!*(Ws#r#### Y *&W#~>0ͧ*(Ws*&W#6& Y *$W+*"WͯO}2*W|o{g#"(Wz*&W~+"(W4X"&W ͒ͪ"$W:m "$W4X"&W:V*$W}*&W ͪs#r*&W~D:###ͪ""W͵91͊91*"WZ*Zsq:͡O͇!Z"Z:*WŠ:*"Wsڐ:9:*WO>_*"W*"W}o|g""WK*&W:*W͘6*Z"Z*(W*&W#60 s#r*"W};g91*(W#"(W*"W*"W}o|g""W!s9*&Wö:471U XGN;1D;N;*;!V~16*;*V"Vx2VB;ʿ;=y;"&W#~+;1ͪ"(Wë;"&W#~;0ͪ"(Wg9*&W!"(W!3|ͳVg9*&W;:;;>͟;5͟ :VG7{7 6ym !͟o&"Wm *Ws"W͡O*Z*ZͨODM*Z*W*W͡OÇy* !Z"Z"Zm !͟o&"Wm *W"WsͨO* DMZ*W"Zɯ!>2W +"W "W"W*Z*Z͡O`i"W2W*W*Ws!W4N*W~= ^P*WM*Z*W~ 2W +"W "W"W* "W!Z"Z"Z2W*W*Ws!W4N*W~ ^P*WM*W*Zң=AOxG:W}"Z*WN "W*W}o|g"Wl=6#y:4Ww# {y*VJ*Vs>w"Vr+s>m #>**Z""Ws#>:}> U X^#V{="&W~>*"W*&W##:U>4:]>5#s#r###* s#r#* s#r \  :ĕ>#:ĕ>~w!""W! K/KK>(>=6D>*&W 1 ?*&W6!>}#> K/KKʮ>(>=:ʼ>6ü>*&W1 N6#F6##q#p!""W! K/K(>=D>*&W >?*&W6: R?6s?ڇ?^ ڇ?!!^6#V6 s#r &  G #>*&W : 7>!> K/K(>=D>*&W >?*&W:@6: ^ ڇ?!!^6#V6?ڄ? s#r s#r/ / R"W+ CRm s?ڇ?*&W!3^#V*"W}s„?**Zsڄ?*&W: [@w#w^#V s#rJ!lJfJ/K\fJ/Kl:\KXI\= XY͐ Y)B!CY͐ BY)B>"BY ÍQ!Aì@!Aì@!6Bì@!RBì@!Bì@!Bì@!Dì@yY͐ yYA ÍQ>!!Y`" +AFbk:Y!aYBKT]G=.A|!YcA}!1YcAY62VDMT]! DM:V=eA=Gbk͵A!IY}F!LA`i>wBK!IY1GB%G~AA G G!Y~APYbkFA>o PYbkBK`i!44:W2:Wo&6#6yY`"yY͍AͅAbiyYfBկ2VA~BFbk>2V!IYBKD!LADM:V=GT]~2Vw:V怶w> B:VDMIGBʳB>@ABKF!yY!Y`iyYBK!IYE!LA`iT]!yY:Gy@G!yY2Cwx/@w#p+DMx>G TC G!AcA!Y>cAY1YbkY!yY!YyY!YT]BK!Y~w!YY`"!FY`"} D|g}oҼDYY!Y} DYY!YßD?tQ3htB Pe`cIC0sU3gwyD%#c$AtD Yy(S@'PE3% &yEwr1x23tDPWuu@DFbABS& Q(Cvf`BFBDFGh"B&DvE ACE!WtVEUH%fEg6Q63S DPWuu@DF?@bQ2'FEpBtRs%q8'cYqC@g)G`tUD##tycg9DAB 6B&#Dr 'dEGD y`Hu`3@(3sg&3`drdt%xhaiPBS45RdwehePQ41dCE2T`&@xvbuSqubaxA''$1fCaWq4i$$E`uCQ2C$4RX)IiˆT!G$i[G2V KXU!S*6Z҄G:VXÄ*6ZsʙG:V>ڄ͛*BZrszͶGXGX{<24W y~J:4W_ X:4WêGm XG>G 4X>͟ HͶGX_:OH==H\ y VH*]))))):\o/ Go&cO/ ]H/ X1 ګH##~G###ͪ#!~#ڍH#O{ʜHyˆHÂH_cOGG7 "DW!"BW K/KKXI\1 X*DW*BW "BWs I \Y !}͒H\ X\ X>X m  K\ ^ !}N6#F6aIX\G mI!}͒ yEI}X}X4JÇI!J22 K>C2e!OM"f\ X2|!ͼ'!';I*V%! XJ!6 XJ:II-I*###*V!\\!\|w# 0*#~TO# K$\!yw#xw ÀJ #~+:Jy~J## yد25WͨJҒJ # ˜J~.¦J# ~*J.7?ºJ25W# ¨J>? J#25WaA<? KX\, X!\:4Ww# {y\ K: د:V72V:5W*K s{_zW!M > 2W +"W "W"Ws*W~ʝK*W{_zW*Wn&M*W#*W"W*W*W͡O:WÈ: WKLͨLIYy ͳL;L:LIYPLbLK X{!>2WͨL +"WͳL;L~<#L*WLLÑLy2 W!"W " W" W* W* WsͮK!W4#4o&" W:WGNLOLxQPyQPy2WK X{2N2O +"W " Ws"MDNO>,M2M:W=YMaMiMuMUNOOOMN*M~~M>!N~M>!N~M:2N!N~M:2N!N2M2M2BN"MO* W*MͨOi&O#"M*MzW{_>XN"M"N"ONyoxg",N!"(N"N!"M"EN "M&N*MG~p# M!}o|g'N"N*M"M}o|g"M*MM!#|;N¥M}ҥM"(N"N! "EN"M "MM!`N)fN)lN)rN)xN)~N)҄N)M#M+MJҭN~JڳNM~JMM# ³NM~NNMMM# NM#NON~NOy O#M OM7M#2JO*OO*O>2JO~0OOyHO#~aGaM 5OM*WN # ZO ~aSODM!yoOطxGyO)hO>DM!))ҏO#}o|gқO =†O{OzG{_zWDM>!)O O#=O))O#÷O:O +'w O:O 7+>'w OJP~JP~J:O# P~8P'w NQbkFbkG =QʩQ=ʁQ O = Y :VX#F##~#"_& / / / / wQ =QQ=Q O ÁQ#F##~#"_& & / Q {_zW/ {/_z/W/  1R cO)R/ / / = ÇQ= ÇQ ^R }>XO/ X͐ Y͐ XY!YY ÍQ*V*.Zs>*2Z*0ZR*6Z*4ZR*:Z*8ZR*>Z*0R)S~=S#~?GS 0͖S4Sa€S~S>$~SC{~S #~̓S~SwS#~̓SڀS ͶSoS~ɯ~a0 ړS ظ?bk)ڴS)ڴSڴS)ڴS_zWbkSS¾SíSBZO} at in line  Z nVsV,@4Vx@Ew"1qB1AGgwx!V6y*&W##~ï;B !ͼ'!h'!ͼ' [<24W }  H[!9"V~ 1!!":[[-[*###sV*2}*[*.%"V"V"V2\͈R:V„*BZê Sorry - Rev. #2.0 or later cp/m is required. $ BASIC/Z Compiled Object Program - Rev. #1.11 - Serial #33314 Portions of this program and/or data are Copyright (c) 1982, 1983 by System/z, inc. - Richton Park, IL USA $!ͯ&>\#S~ͷT\# y C\y2S!Z!]"FWR*%Z+cO+*V#"FW&0(u{u{[[ab&d"`d f`[[4\]^ _`a(-a(Wa(a(a(a(b a(-a(Wa(a(a(a( PZZZZ9Program Aborted++Enter NAME of dBASE II COMMAND (.CMD) File Enter QUIT to End QUIT..CMD55Do you desire a (C)ommand or (P)rint output (C or P) C.NEW.PRNInput file is Output File is PRETTY - VERSION 1.066Pretty printer program for dBASE2 programs (CMD Files)11by Joel Shapiro 8/13/84, inspired by Adam Green's recent work.11This program has been placed in the Public Domain33by the writer and may be freely distributed so long66as this message and the sign-on message remain intact. TESTFILE.$$$!!Copying your file to working fileCopying completed!Formatting your fileENDTEXT*DOWHILECASEENDCASEENDDOENDIFELSEIFTEXTPROGRAM COMPLETED!Copying completed!Formatting your filekúe- 4b eP- 6b eP̈́\1e4b - ñe- [ͽ & [ͽ & [ͽ !_e"[- [ & ͸6b eP\ʇeÜe[ [ ![[ͩ- [ ͂- - ,f[$ - !bd+ ͺP\e& [ͧ e& [ͧ [$ ,qf- !bd+ & ͺP- 6b ePu- 4b eP̈́\]f& [ͧ hf& [ͧ [$ ,ófh a 6b eP\ʟf& [ͧ êf& [ͧ [$ ,g4b ] -a 9b eP\f\+ & ;b fa f`b fa f`!" & \ͽ & \ͽ & \ͱ ` c f`"c f`Zc f`c f``c f`c f`d f``Gi !k"͊! y& ;d !#g" ͚>k& ͺP\k;d JÓk#g!#g"! y& a !l" !#g" ?(& & bn*&  \ͧ Id f`&  \ͽ (& [ͽ & [ͽ !Ml"[& 56 \ bC-  \Q[ [ ![ \ͩ&  \ͽ  \$ [ͽ & [ͽ !l"[&  \ bC- ͮ7[ [ ![ \ͩ&  \ͧ &l& ; \$ & ͺP\bm&  \ͽ  \$ [ͽ & [ͽ !0m"[&  \ bC- ͮ7[ [ ![ \ͩ& ;ld f``b́+! y& ;d !Aw" ?! y& a ?d f``!#g"& \ͧ \$ & ͺP\Aw& 56\ \$ \ & ͂d ePfu\Gn!(bf+\ ͮ _ g 8w\ ! bf+\}n!(bf+\ ͮ _ g 8w\ !bd+\ \ !,bAg+\ h & \ͧ \$ f\ !be+fu\o!$btf+f\n& \ͧ h i øn\$ \ !be+fu\Xo!$btf+f\Joh i Uo& \ͧ oWa Wa Wa d eP\ʷo\ \ !(bf+6b ͮ\ ͮ _ g 8w"& t$\ q& ͺP'& t$\ q& ͺPu[& t$\ q& ͺPu\&p\ \ Þs"& t$\ q& ͺP\Nq\ "& t$ͬ\ͧ \ \$ & iQ\ \$ ;Q͸"& t$ͬ\ͧ \$ & ͺP\ʱpNq\ \$ ͂\ \$ & iQ\$ ͸ͮ^ \ \$ \$ iQͺP\Bq^ \ \ \$ ;Q\$ ;Qͮ͠^ ^ \ '& t$\ q& ͺP\vr\ '& t$ͬ\ͧ \ \$ & iQ\ \$ ;Q͸'& t$ͬ\ͧ \$ & ͺP\qvr\ \$ ͂\ \$ & iQ\$ ͸ͮ^ \ \$ \$ iQͺP\jr^ \ \ \$ ;Q\$ ;Qͮ͠^ ^ \ [& t$\ q& ͺP\ʞs\ [& t$ͬ\ͧ \ \$ & iQ\ \$ ;Q͸]& t$ͬ\ͧ \$ & ͺP\sÞs\ \$ ͂\ \$ & iQ\$ ͸ͮ^ \ \$ \$ iQͺP\ʒs^ \ \ \$ ;Q\$ ;Qͮ͠^ ^ \ Wa d eP\!u!(bf+\ ͮWa ͮ6b ͮ _ & \ͧ \$ f\ !be+fu\=t!$btf+f\4t& \ͧ h i s\$ \ !be+fu\ʍt!$btf+f\th i Êt& \ͧ =tWa Wa  _ Wa ͮ\ [$ \ ͸ͮ _ Wa d ePWa d eP̈́\u\" \ iQ*ͽ g 8wWa d ePWa d eP̈́Wa d eP̈́Wa d eP̈́\u\" \ ;Q*ͽ !(bf+\ ͮ\ ͮ _ Wa d eP\u\" \ iQ*ͽ g 8wWa d eP\Mv!(bf+\ ͮ\ ͮ _ \" \ iQ*ͽ g 8wWa d eP\ʳv\ \ͽ & \ͧ & \ͽ !(bf+\ ͮ\ ͮ _ g 8wWa d eP\w& \ͧ !(bf+\ ͮ\ ͮ _ g \ \ͽ 8w!(bf+\ ͮ\ ͮ _ g \Qm& ;& ;;d J```d f`dͪ _ g \ \ͽ 8w!(bf+\ ͮ\ ͮ _ g \Qm& ;& ;;d J```d f` PRETTY - FORMATTING PROGRAM FOR dBASE II COMMAND FILES by Joel Shapiro August 13, 1984 The capability of formatting a dBASE command file so all structured operations can be matched has proven to be helpful in understanding and troubleshooting my programs. Adam B. Green demonstrates and provides code for such a program in his "Advanced dBASE II User's Guide" but the program lacks a few features and, most important, is extremely slow. I hope my version of the program takes care of both problems. The purpose of this program is, using a dBASE II command file (CMD) as a source, provide a file with the same program formatted in a special manner. Specifically, the program formats as follows: All REMARK lines denoted with an asterisk (*) are printed in lower case. Lines between DO WHILE, DO CASE, IF and their terminators; ENDDO, ENDCASE and ENDIF are indented three (3) additional spaces. All characters except those between single quotes, double quotes and brackets are capitalized. Lines between TEXT and ENDTEXT keywords are printed exactly as they appear in the file. The program is written in BASIC/Z, a compiled basic from System/z, Inc. and is provided in object code only. All run-time code is contained in the COM file. To use, type: PRETTY . When requested, enter the filename and drive. You don't have to add the filetype as the program expects to find a CMD file. You will the be asked to select a command file or print file output. Selecting a command file will cause the formatted output to be written to a file of the type ????????.NEW. Selecting a  print file output will provide a file of the type ????????.PRN. Additionally, line numbers are added to each line in the PRN file. No provision has been made to split lines longer than a formatted screen or printer line width. I suggest you use lines not exceeding 60% (48 characters for an 80 column screen/printer) which should format correctly. Output files can be printed directly or enhanced with your word processor. Joel Shapiro 1 . When requested, enter the filename and drive. You don't have to add the filetype as the program expects to find a CMD file. You will the be asked to select a command file or print file output. Selecting a command file will cause the formatted output to be written to a file of the type ????????.NEW. Selecting a +"6# x+:`i* ">"/##~>;+> 6*s#r w+͊1>2 u+#w+>36*s#rw+6*xDM"+ڍ+s#r#À+! >2:*ã+6*x+Á*~#ʽ+#~+ҽ+~+x 6*s#rw+ɯ2,x_O:*+2,x_O6*9w#w+x,+r+s=,w>#w+Á*~7^#VE,E,!~ѧ7x1P*x1~7!~#fo~ʁ,7,#~+~w}D#wx#1]*KÄ,!9*?!3"$$#̈́.!P8!3^e2! I!5I!C|/g}/o|`!͌'!a*!a͝4"0"d*d3f2fe2"!MD!Ê*i/ ́1*i)g1*i#"i*i|ښ)l#.!fb,#.! b,#.! .!b,#.! ͣ3b,#.!b,#.! b,#.!~b,#.!Mb,#.!,b,#.!b,#.!b,#.! ͣ3b,#.! b,!ͷ*!k*!"n"p"rt! e2k! 4k!4q! I!5It#.!fb,!ç!C|!͌'!w*#.!wb,*z#"z*z|ڷ)ڃ#.! b,#.!.!b,#.! .!q>,!͑L|e2!3!|4t!MDÝ!k|4"!k*i!X3e2!͆4|:)?go!͆4|O)go|g}o|q!͆43e2t!2te2!m4!"r*r|/g}/o|°!i4!"p*n|!e4*i###"n*i#"i*i*z|}|*n|)t*n&3te2t!X3!a4,!]t!ͯ2!t|4|got!X3!]3|g}o|i#.!fb,lÓt!W2e2#.!A>,!tb,!MHt!;3!;4#.!f>,! ͣ3b,#.!^>,!t>,!b,*n+++t&3e2!2e2!2e2!2e2! I!5I!MD#.!f>,! ͣ3>,!^b,#.!.!b,#.!.!b,#.!.!b,#.! b,#.! b,#.!>,!>,!b,#.!>,!b,#.! b,#.! b,#.!{>,!>,!j>,! ͷ*4)!p*!&3!f3!&3!b3|g}o|‘!&3!^3!&3!Z3|g}o|y!&3!i3!&3!V3|g}o|/!"! I!5I!MD!"! It!5I!R I!5I*p|#.! b,#.!;b,#.!fb,#.! b,#.!b,#.! b,!"z!C|/g}/o|ʷ*z#"z!͌'!*!|4|ʛ!;3!a4S !|4+&3e2V  !͌'!*!"*z#"z!|4"! *!X3͆4"*|go*|go|g}o| *!X32e2 !|4"*#"**z| }|~ + !e2!""!|4"*"! *!X3͆4"*|H )go*|Y )?go|g}o|ʀ *3*ͯ2*| *|go*|go|g}o|ʻ *#" *"**}o|g| ) *"*#"**z| }|( *| !e2 4 *#!X3!41 !"x*#!X3!3"!X3!3*|g}o|›*#!X3!4 !e2x! e2!"*#!X3!4 !32e2 !"è *#!X3!4 !32e2 1 *#!X3!4( !". !"è *#!X3!4] !32e2` i !"è ! *#*)^#V"X3*/ 4 *32e2*"*"!C" *#!X3*/ !&34 *32e2!"*"!C"*#"*|, )o *|go*|go|g}o*|go|g}o|x*|go*|/g}/o|g}o|ʘ !"*|ڥ )**#"*"*`*!X3͆4"*| )W**}o|go*|go|g}o"*|go|g}o*|g}o|\*!X3͆4}o|g32e2*#"**z|t}| *p|/g}/o|ʏ#.!b,!ͻ-!b,p'e2! 4*8!MD#.! b,*|!H#.!>,!b,*|!F#.!>,!>,!>,!b,!f3!b3|g}o|C!HFU#.!>,!b,!F#.!>,!>,!>,!b,#.! b,!ͷ*4)!p*!&3!f3!&3!b3|g}o|#!MD#.!^b,#.!m>,!^b,#.!-b,#.!b,#.!b,#.! b,#.!>,*z5,!>,!t>,!xb,#.! b,#.!t>,!>,!tb,#.! b,!H!MD#.!^b,#.!-b,#.!^b,#.!>,*z5,!>,!t>,!xb,#.! b,#.!t>,!>,!tb,!H#.! b,#.! b,!3!4!MD#.!^>,!b,!3!4p'! 4=8B.|goP.M/|g}o|I!MDLÍ#.!f>,! ͣ3b,#.!"3>,!t>,!"3>,!>,!^b,s.B.|goP.M/|g}o|ʻ!MDs.B.|goP.M/|g}o|!MDs.B.|goP.M/|g}o|!MD#.! ͣ3b,#.!^>,!b,#.!`b,#.!-b,#.!b,#.! b,!Æ#.!>,*i5,! ͷ*!*! 3*i|ړ)?go|g}o|™! 4`!|4|ھ)`!|4"!.*!X3͆4|)go*!X3͆4|)?go|g}o|*#.!^>,!b,`*#"**z|B}|*i|S)s! 32! 32e2!2e2*i#"i*i|ږ)`#.!>,!R I!5I!ͻ-!b,!MDs.B.|goP.M/|g}o|#.!f>,! ͣ3>, ##.!^>,!>,!^b,s.B.|8!MD;|#.!f>,! ͣ3b,#.!^>,!"3>,!t>,!"3>,!ab,s.͒. "IF",2,"ELSE",4,"ENDIF",5,"DO",2,"ENDDO",5,"CASE",4,"OTHERWISE",9 "ENDCASE",7,"DO WHILE",8,"DO CASE",7,"STORE",5,"?",1,"RELEASE",7Z_ "RETURN",6,"SELECT",6,"@",1,"ACCEPT",6,"APPEND",6,"BROWSE",6,"CALL",4Þ "CANCEL",6,"CHANGE",6,"CLEAR",5,"COPY",4,"COUNT",5,"CREATE",6 "DELETE",6,"DISPLAY",7,"CONTINUE",8,"EDIT",4,"EJECT",5,"ERASE",5,1 "GO",2,"FIND",4,"HELP",4,"INDEX",5,"INPUT",5,"INSERT",6,"JOIN",4uz "LIST",4,"LOAD",4,"LOCATE",6,"LOOP",4,"MODIFY",6,"PACK",4,"POKE",4ú "QUIT",4,"READ",4,"RECALL",6,"REINDEX",7,"REMARK",6,"RENAME",6 "REPLACE",7,"REPORT",6,"RESET",5,"RESTORE",7,"SAVE",4,"SET",3GL "SKIP",4,"SORT",4,"SUM",3,"TEXT",4,"TOTAL",5,"UNLOCK",6,"UPDATE",6^# "USE",3,"WAIT",4# d is a bad file name - try again./The Help file, ENCODE.HLP, is not on this disk!Writing CLS.DATWhole decimal numbers only.Clear Screen character+entries with a to generate CLS.DAT00one byte at a time in Decimal numbers. End your'cPlease enter your clear screen sequence/CLS.DAT, the clear screen data file, not found. not found - try again.<****ABORTING**** ^C entered from keyboard. No files changedThe error was in lineD0****ABORTING**** This file contains characters with the 8th bit set!w' {, it reads:of The error was found on line? word , '*' (remark) or '&' (macro character)>[]==============[] TEXT and ENDTEXT must begin with a reserved=0[] ABORTING [] dBASE II .CMD file. All lines not between UOYn]qaQeyiYm (Yes/No/Quit)~Do you wish to overwrite will be renamed to , already exists! If you answer NO, the old [] WARNING [] []=========[]OLDCMD TMP* must have the extension .SRC - try again.>SRCDDirectory of drive Z*.*`:d;h.lNp tPress to return to ENCODE - ENCODE.HLP?Filename.SRC or Drive:?  Redisplays this screen ? Read the Help file/ A: Displays directory of A:.P FOO.SRC Output to file with console display(Examples: B:FOO.SRC N No console display,Option: N No console display of input file#ENCODE - Version 1.05 3/20/85CLS.DAT I4\^6f (2<FPZdn"x3?K]`fl", 6@$J1TF^Qhtr}|*q0&D:NX,bll{v)/JYh w *4>HR\yh@fmpsz   +  jV b h $o .~ 8 B V L ` t ~( ;      4  1 xo       1 < (. 2i Z` Ff Po d x n/ n     W \5"6,J@U^FTr|'0ENT]f&o0x:DNXblvLa' 6? H*Q4Z>`HoR|\fpz*Fs# |. ; P w$ 8 B L ZV ` j ,t u~   G [[[[ BASLIB #000000 5.30 - OWNED BY MICROSOFT, 1980 @"K~#fDM*"4*Z%##"4*#>27"2:"*^#V"8"##^#V";" 2="!ʋ"!!"">"!#"#6#6P>2#>2#>2#7"":"""_^M!ͼLںL}0?)))صoüLM!LL}0L0? L?//!9""I% !ͪ#I%M#!ͪ#$#!"ͪ#!R"#!O"!#I%|~#> #6#s#r#=s#>2">2">2"2"!"""!$\"">&2"Y"76#}§#|§#n8 STO͵$#?%*".. . ........6*"|#:":$*"|:$@$I%  s#rI%  {͘%w#6""*"*">2"͙%ÿ#!9N#FI%~#~r$~+x$~#~r$+^#V###P$###P$|ʄ$~#fo!$n8 Internal Error - No Line Number "I%~#!%n8 at line@$$?%>%<$%$%<$0N%$}_|W!%͔O~#fo>n8 at address|͒8}͒8?%> N> N~#*X%͔O~#foY!9""!`%*"f%""!%*"?%!%~<ʳ%=ʳ%#~#%ß%#t8Syntax Error in DATRETURN without GOSU Type MismatcOut of DatIllegal Function CalOverfloOut of Memor Subscript Out of Rang Division By ZerOut of String SpacString Formula Too CompleRESUME without Erro2Field Overflo3Internal Erro4Bad File Numbe5File Not Foun6Bad File Mod7File Already Ope9Disk I/O Erro:File Already Exist=Disk Ful>Input Past En?Bad Record Numbe@Bad File NamCToo Many FileUnprintable Erro\%ͩ"!o'>ʆ'ͳ"w>ͣ6|#\%}͚ILʨ'L`i""!'"#!=("#( ,Q('(:9*P*P*P*P(:j:*P(:9*P*P ½',ZQ(~#"(xͣ6(m%!>#Q(͔6ͣ6h2)F4( a(Q("v(G{,xv(PX)F(!*Oz"yʯ( ( ¯(O{,y#))F( ¯({ ʾ(,> ʾ(ʾ(((#))F{("( ()F( (,( ()F( (*"( 4:##){,)6!*͔6O )+~ )#6!*ɷw#()!S)N#"2)!9"-)"/)y21)*"|V)*#!@*""A~#*+͈O:##v)~@*)ˆ):Ë):"+ʱ)ʽ)9*P*P*P*P)j:*P)9*P*P*+͈O)~#"+,^) @*:##@*^)~@*!""~,"*#"~**# *@*" *#"+x"5* 5*+~ **yͣ6)n8?Redo from Start *-)6!m*ͷ**2):1)O])*/)+~+ʛ*ʍ*ʍ* +w *æ*++~#foh2"/)!1)5*-)X~2*#~#^#V`8++6Mڶ#:*\%*"|*!*͔6ͣ6h2*#Y+TÿT W~w+TT!hT~w# TO:sM̀O5Vq1UGܒTTx UU)T!hT)UL} :iA^U:U!lPPT:hnU2h!OͦUb!lPPͦU;Sb!lPP>ͮUͺU;S!rU=‹UͦUͦU!i5M!s>5=³U>!lN#F#=U>\%k,O-\%v,O-\%́,O-\%A,O-\%k,q-\%v,q-\%́,q-\%,q-\%k,-\%v,-\%́,-\%,-PÌ,PÌ,"PÕ,H~# ,x28:#F--,<͔6<}-~ʾ,aN#ò,l-<~, aN#,>28:#F-F#~#fox-}- --~#aN, -6->"aNG:#x- O*#+~ aN->,aNW*##^ ̧-ʡ-+=ڡ-:#=ʡ- Oz{ڹ-{_ë-\%|-}͚I-L`i""++"#!." #!-"#2#9.m%#DRL}o|g.> aN+|. O!#"#!""2#9.!#~6#wI% n&I% ^#V{/|w%!o.pU:"#^#V2"^#V#""!"":"*"I% n#~!.̀8Nʽ.m%i&# +(/*#{<. O{.=> aN.|#}*#.<.(/}.|#}.|0/!*##n&͔/>!>!>!>!>!>^#V#!P\/g/ G0w/w%QW^#V#\%͡/\%͡/\%zʻ/|ʻ/|qWW^#VÉ/^#V#/ͽW2##\%\%/\%]O10(O|#\%(0\%100H0:##~0!%*STU0:##ʁ0!%pU:P2P:Pҝ0ͧ0:Pu0w0|/g}/oT:Pڧ0!P000!m%#:PgoW*P|7g0:P0+>0|/g}/o0!0G|00o& Gȯ|g}o0 1>1~+~?~!1+#.1+ .1\%29P>x1\%(2:>29P>x1\%2j:P>͙O\%(2~,"•1#"~ʬ1ʬ1# ˜1m%#"²1#>2x"1y͔O+~ 1 1yͣ6h2I%^#V#{1!""""">2"1N#F#*"~=2}|2P22(2:>2:"1*"͈O~=m%#͈O~,L2#""ɧ_2*"""+V+^""m%#\%}6Ԣ2~##++K7>͙O+V+^+ʕ2+r+s͕7\%h2~ʹ6po"2"2*2|#}# #+<2{*22~#^#V`i#N#F ͙O*26\%#;63366~#~#fo͙O\%|#BK`3PY\%|#BK Q3 o_43\%z#zh3 n3_t3o}`iʹ66DM\% ͦ3~##~#fon&6\%z3};6~ڿ3s#õ3m%#\%|#!9>ͣ6>3>3>3>3>3>.4!+>4>4>4>4>4>.4*4~#fo##GNZ4yZ4#~#fo~#foc4#Y4 I4 yc4y<.m4)m4)66~6o&~##^#V++6o&\%~<#;6~#~#fo͙O6+B:966#r44>4S44g44#4>4S44^4455>7_!4455*4"4~#N#F#W515 ͔O5yx<5 5+++6@#yw#xw+++6###!4~6h5}555*4#~#~5m%#!*4"4~#^#V#55͔OÊ5|¯5Ê5++~_w#~Ww#Ê5}5*4DM~#^#V#!655+z6+{6##{z~#q#p_5y6x6DM5~#65YP+++"46@###{_zW+r+sɷp6*4|N6m%#5^#V+"4w#s#r+++r+s##!w6|6*&8{z*(8?Ғ6}|~# ˜6yG;6x͙OG;6x#N#F& ì6}6K7Õ7*&8*(8ͧO676K7͕7###6 7n8 during G.C. " 7n8 "n8 Internal Error - String Space Corrup#N#F*4yxڐ7*4yxҐ7++`i+V+^ͧO7##6+6+~6  >@++*4"4s#r+5*4#~_#~WҾ7m%#r+s##6"4###!4~#fo7ͧO7<*4"4*4}o|g6@#s#r#6"4*(8*&8"4}w>#w##ͧO 8++6+645!"4!9""^#V#!"~w#!9""|#}#!#wɧ~N#=b8t8~N#t8G~#ʐ8#‚8++͛80:ڦ8N_4_:K_4_: K_4_:@K_4_*m#~4.B8*P}/o|/g#"P|)9QW8!P~w2P.B9T)9*P)9QW.B9ͰT>>:~ͼ"#.9ü"8!PL9>!PP2S9# R9!P*S!P3:P>>u9>|}+!:2R9W+6!P>sT2P!:U!:2R!P2R~_#~W#~O"YsU!ApU#W9ɇ<o&)9QW*P*P9"P`i"P!P^#V#N#F#!:qVYx{Y!P6Wwg>mY)Y7::8Gw#7:2:L:!P3:P.BP.B*:*P||<.B*P:F:!A@:\9 9É:9:P2P:P C ::Pª:ï::|/g}/o:! C:P: :"P>289aj: L}9&9B>28`h:~&IB- ;+ ;+B<.ʭ;e2;E\;BlJ;LJ;qJ;Q[;:8u;>u;~%ʺ;#;!;du;DŒ;;B?BBz<Œ;_{_;;;8.B!9:.B Œ;; ;B!9!j:Ì;;BÌ;99.B:9=.B99n>Z=_A!8F :8_ =x*={=AqB<=E<=D<=0=,=.?=+60{J=+:"w{+p28!86 9*P*P28>E~ʦ=:҆=0چ= #~w=>DGu="P`i"P#~+=-=0OxG=#~«=`xE=y Җ=>28=|Җ==Ö="P`i"P9#W@:8 >*>.>.>͠@60:@+~0=>.:o>.B>"w#6+`>6-/</ b>:#p#w#6!8#z>ړ?͘@zt@_A{}9=t@<ʥ>p#6!8#:8~ ʪ>*ʪ>+>B-+_:"{0>#B>++w>ë>>6%ښ??Ab9 ?<+6%9 ?*:@E?_xt@͋@@Ą@ij@Ò>_y;P?;R?{_xn?t@͋@?t@yͷ@Ot@GO@Š?*8=t@PÛ>9ѯʠ?*:7@y;OzWO;??/<Û>կ.B%@:P%@A!P3:ͨ9 @W@.B:@CO9@@Ab9S@;(@;W@.Bi@t#9o@Ab9K@=60#u@„@ͳ@60#=À@{ ͳ@/>I9@>I9p#=@!P9#A9> :9B?ͳ@9/{_#zW#yO++7Aͮ9#9p#)A>eA B>ͳ@N#F#*P/}o|gxA"Pp#=eAͳ@w1_cƤ~@zZrN vH Tʚ;@B''d #~: B B B0?<=:8;B7-++BBOZBHZB+fBoB:H#ʛBuBm%#M!͇BڅB}0?)))صoÇBM!ͭBګB}B0? B? ))))صoíBa{ j:.B:P:Pú9:82828m%#m%#ESLESGTSNES EQSLTTGETLETGTTNET(EQTSASPOSROWLPOTABSPCIN0xPR0oIPU UMFSGFPEKPOKRSTFLDLEN\%}͚ILL!' ~D D#~C`iEC>O #~goPY!' ůwF:?"HM=L=D!' ~DF8J\%}͚IL!&¯D! ~+ng\%}͚IL! n&*"~LKDM'~D4N#V pEzw w+s#r#6#6DM:="/E!" s#r#6tE! {zVlECw*"T]% N#F+q#p###6 EF:>"H>F>w+w!(ͯE7?*"' 6#67~M#^#fk_aFN#~:eF++@My@MMC #F~.F͢F7{F#|F2C6z MM> âFʖF> »FÖF\%DFCC ͙ODF:C!CMC ͙O66F~®G<MG.0N H:# W:#ھH> 0N0N-NCH~*6?# HO!!4H#4H#4y" IM><"C>2"!aL"":"<2"*""C!YI""\%"CG*"|WI##nUDFI.PD*C\%nI\%2C–J"CÖJ\%ÊI\%2C—J"C×JL!)J)#J)) K K#=J}_}la)M"K#xM"mJ! "oJ!) "qJ!}o|gLQKbk:sJʗKLfKʹKDM*qJ*oJK"oJPYͳK}o|g*mJ#"mJ4KʹKDM*oJ*qJK"oJPY|K2L*mJ! ~#foLs#rK:LK!K!& E~# xKDMTLLIL! w!( V6 !LzwRLLIL! ~!DL! ^#V! s#rDMAL;LL}͚ILtLL`i""!L""ñL)Fm%!>#\%|#,ʫL-:"L*"!"""{;6f$%L!L*"úL"|}!"">6>4>?>=>:>7>5>2>3>@>C>m%o&#w%!""!*"+$M:*5Mn8?5Mp[NiM:,N>\2,NOM4M0N+cM~0NwM+0NwM0N-N!*2,NzM[NO;M:,NʐM>\0N2,NyM3N7 !N M ´M5MM3N5MM5M0N> 0N>\MM>#cMM6-N!*ENwM wMx<>Nyq#0N wM> 0N[NN wMzM:*-Nwo?%N>^0N@0N-N~ TN> 0N0N#ENͳ"*# xN#~+ aN~=N*#!#"#aN"#> aN> aN:#=$O> "> "*_N!PDO!P?OPDOPDOw#w#w#w# DjO>PpO>PUO ~#=tO!UO#~ ʇO ʇOɅo$ɧGw#O{z͙  *ͥ ͫ ͱ !"*"!C"*#"*|, )o *|go*|go|g}o*|go|g}o|x*|go*|/g}/o|g}o|ʘ !"*|ڥ )**#"*"*`*! 6 "*| )W**}o|6#ҵPTPP)YOP!1Y!Py#P+P)Y?1YQXͰTQQͧTͼQ!PTzQ:P)Y:P/NsTS2P:PS)Yx/F+N+=Q!P R!P>q#p#=R!P2R"ORQQ*OTX:PX!PN#FV\TqoRGܡS͟Tx XRORS!P{TgRj0 TeB׳]h!I.k QXͰTöRQͧT!P2Rͯ.!Pq#~++w+qR)YDNn"~`35zr1{r1h!IT)YyO2P0ST)Y:PʼQBS/<ͼQ9)Y:POWG2P!PsT:P2Px!PPSͪSyS4͟T:PS!P~++w)Y!P4#’S4ʼR+6!PP# ªSɯ# ·SͷSS/!POyw#SG:PT!PVwz# SxSX!PTSxyS!PwXyS~w# TQXͰT7TQͧT!P*SQXͰTSTQͧTͼQ!PSy2P!PO~q+iTqڊTNsY+TuT W~w+”TÍT!PÑTQWðTX!Pw#¶T)YT}TTUTW!PF#^#V#NXU}P~#TG++Ny1YPT!PX>?UUͯ."YMUY;U!P6Wg>mY|ԦW!>UakX\UV\U)Y!P~+>w)YcWsUY)Y:PY҆U/<ʹW)YWgmY!PU~_#~W#~OX#4ʯX.̓YXG~_#~W#~OܠWXcWUY)Y>OvUcWUYʔW)YȯGV"Py2PFoͫWʹW!D*P:PO%VP4ʯX=VMVg.*P:POz&VMVg.*P:P3Vx<=dV{_zWxG)yOHGXcWtVYY)YVy+F+F+Fw`h|VgyҥV:PO|g}oxG-|™V}”VXElaOÓV!P~GxVƀXwWw+ɷXXYx{Y!P6WwgWzW >mY|X{>2PX/W#~+~+~+~LUX)!"PܠWXWQWʹWzʔWzBW|G||W9YWͯ.O_yW!P~/woG}_}W}OWY||DM!>))W =W!P~7w?##wy7O*P*P"P"PajSXIXXJS\E!PX/TY SY7>{_zW}o|g=JY|g}o|YCZQoY o-yOzW{_xGYP*PDM^#V#N#F#xy1Y:P:P7|/G}/O!>TY SY7>{_zW}o|g=JY|g}o|YCZQoY ooͫWʹW!D*P:PO%VP4ʯX=VMVg.*P:POz&VMVg.*P:P3Vx<=dV{_zWxG)yOHGXcWtVYY)YVy+F+F+Fw`h|VgyҥV:PO|g}oxG-|™V}”VXElaOÓV!P~GxVƀXwWw+ɷXXYx{Y!P6WwgWzW >mY|X{>2PX/W#~+~+~+~LUX)!"PܠWXWQWʹWzʔWzBW|G||W9YWͯ.O_yW!P~/woG}_}W}OWY||DM!>))W =W!P~7w?##wy7O*P*P"P"PajSXIXXJS\E!PX/ CLS.DAT will then be written and you will go directly to operation of ENCODE. If the title screen is preceeded by a clear screen, the installation was successful. If the title screen scrolls on, it failed. If it fails, exit the program, erase CLS.DAT, and run ENCODE again. If you don't like the clear screen function, simply enter 10 when asked for your clear screen sequence. For each 10 you enter ENCODE will scroll one line in place of the clear screen. My older program, CLEARSET, will still generate a correct CLS.DAT for this version of ENCODE. Calling a Directory Listing To call a directory from the title screen simply enter the drive you wish to list. Filename.SRC or Drive:? A: This will list the directory of drive A and give the prompt again. Directory of drive A: FOO .CMD DBSOURCE.BAS DBSOURCE.COM TEST2 .CMD A10 .CMD ENCODE .BAS ENCODE .COM MBASIC .COM D .COM SAMPLE .CMD BOOKS .DBF BOOKS .FRM DBASE .COM CLS .DAT CLEARSET.BAS CLEARSET.COM DBASEMSG.TXT DBASEOVR.COM B4 .CMD R2D2 .CMD DBINDENT.BAS DBINDENT.COM ELIZA .BAS A10 .SRC A10 .BAK CLONE .CMD TEST .CMD CLONE .SRC A10 .OLD DBSRC2 .BAS DBSRC2 .COM Filename.CMD or Drive:? The ZCPR like drive call of A; will also work to call the directory, even if you are not running ZCPR. The Filename.CMD may be entered here or a will redisplay the start screen. Encoding a File A file to be encoded MUST have the extension .SRC. Just rename your source file to .SRC. Then enter the .SRC at the ENCODE prompt: Filename.SRC or Drive:? SAMPLE.SRC ENCODE requires all characters in the input file have the 8th bit set low. You may have to run your source file through a filter, like UNSOFT. ENCODE creates a partially tokenized file that can not be listed with anything but DBSOURCE or a commercial decoder. It is also hard to modify a command file protected with ENCODE. The file is reduced in size as all indenting and comments preceded by * are removed. In addition comments after the END statements are removed. Example: ENDIF .NOT. green Becomes a single byte for the reserved word ENDIF. The ".NOT. green" is purely a comment that repeats the conditions that began the IF statement that should read: IF .NOT. green Such comments make a program easier to read but will slow down operation as dBASE II reads program lines from the disk as they are executed. The latest versions of Ashton-Tate's DBCODE and Gene Head's DB-SQZ5 that I have seen leave these comments in. You can label a file by enclosing a message between TEXT and ENDTEXT. This leaves all lines between TEXT and ENDTEXT as in the source file. ENDTEXT may be abbreviated to ENDT. Example: TEXT (C) 1985 by Croggle Software, Inc. ENDTEXT Caution should be taken that the ENDTEXT is included. If omitted, all of the remaining file will not be encoded. The command TEXT shuts off encoding, ENDTEXT turns it on again. Indentation within the TEXT area will be left as in the source file. Use this feature as little as you can. The extra lines will slow down the program a little for each line added. ENCODE requires that source files have initial reserved words written out in full. This insures a fully readable source file. dBASE looks for only the first four letters of a reserved word. Reserved words in any postion on a line but the first word may be abbreviated. ENCODE does not check syntax on anything but the first word in each line of dBASE command files. ENCODE also requires that you name the source file with the extension .SRC. This keeps the programmer from mistaking the pseudo compiled (.CMD) file for the source (.SRC) file. If a file is requested and the .CMD file already exists, you will be warned: []=========[] [] WARNING [] []=========[] SAMPLE.CMD already exists! If you answer NO, the old SAMPLE.CMD will be renamed to SAMPLE.OLD Do you wish to overwrite SAMPLE.CMD (Yes/No/Quit)? If you choose not to overwrite SAMPLE.CMD, the old file will be renamed SAMPLE.OLD. The .OLD extension is used to keep the encoded backup files distinct from the source backup which would have a .BAK extension. If you opt to quit, you will be taken to the end of the program and see: Are you finished? A , or any answer but yes, will return you to the start screen for another file. Macro Support Unlike Ashton-Tate's DBCODE, ENCODE provides full macro support. It is recommended that macros be used only when other means are not available. Macro operation is usually slower. A line starting with a macro will not be encoded. This will slow the program even more. You must retain the "&" as the macro symbol if you want to start a line with a macro. ENCODE will not recognize a different symbol at the start of a line, even if dBASE II can be configured to do so. If macros are confined to locations other than the start of a line, the "&" may be changed. If you do plan on using ENCODE to create a file for Ashton-Tate's RUNTIME, do not use an initial macro. RUNTIME will not accept it. Sub Files ENCODE requires separate encoding of any sub files you wish to use in a dBASE II program package. It is not required that all sub programs be encoded when operation is with dBASE II, but  it should be done for speed. Only the command files with the extension .CMD are encoded. Continuation Lines Continuation lines will be work with ENCODE, but are not recommended. They tend to add extra bytes to the file. The usual reason for the broken line is to handle 80 columns of display. A pair of lines like the following: @ 6,0 SAY '-----------------------------------------------------------------'; +'---------------' Could be written: @ 6,0 SAY '------------------------------------------------------------------- -------------' The line is allowed to wrap (without a ) and be longer than 80 columns. This is only possible if you use a word processor to generate the CMD file. dBASE II will amputate the lines at 80 columns. This method produces the shortest output. Another way to handle it is as follows: @ 6,0 SAY '----------------------------------------' @ 6,40 SAY '----------------------------------------'  This is 14 bytes longer than the previous example and 11 bytes longer than the first, when encoded. Abbreviated Reserved Words Reserved words may be abbreviated to four letters in your source file. For example: DO WHIL = DO WHILE OTHE = OTHERWISE STOR = STORE ENDI = ENDIF This produces a source file that is a little harder to read, but it allows faster code writing. You may also want to encode files already written in this style. It is often used to produce a dBASE II command file that will run slightly faster because of the shorter length of the file. There is no gain in ENCODE to abbreviate the initial reserved word in each line. ENCODE converts it to a single byte token anyway. Please note that only the full reserved word and the four letter abbreviation are supported by ENCODE for initial reserved words. OTHE for OTHERWISE is ok, but OTHER or OTHERW will not work. Help File The help file may be called from ENCODE by entering a "?" at the title screen. Filename.SRC or Drive:? ? Option N No console display of input file. This is the only option. The N option must preceded by a space: Filename.SRC or Drive:? SAMPLE.SRC N History Rev. 1.05 3/20/85 Fixed bug that doubled encoded bytes for reserved words with a length of 4. WAIT was encoded to WAIT =. In hex: C2 C2. Bug present from version 1.02 thru 1.04. Rev. 1.04 2/28/85 Minor correction to installation routine. Rev. 1.03 2/27/85 Changed to remove comments starting with NOTE and fixed bug in abbreviations of DO WHILE and DO CASE. Rev. 1.02 2/24/85 Added the ability to recognize four letter abbreviations of initial reserved words. Clear screen self installation added. ENCODE.COM distributed as a stand alone COM file, BRUN.COM no longer required. Rev. 1.01 2/17/85 Modified for compatibility with MBASIC 5.20 under Apple CP/M. This required changing TEXT$ to TXT$ as TEXT is a reserved word in the Apple CP/M basic. Added the ability to accept initial reserved words in lower case. Also modified to handle continuation lines and remove indentation at the start of the continued line. Blank lines will no longer abort the encoding, provided they contain no spaces or tabs. ENCODE version 1.00 released 1/6/85 LEGAL NOTICE ENCODE is NOT "Public Domain." Copyright is held by the author: Merlin R. Null P. O. Box 9422 N. Hollywood, CA 91609 (818) 762-1429 Permission is given only for private, nonprofit use of ENCODE. Feel free to make copies of the program for your own use or for your friends. However, ENCODE may NOT be sold or included with any collection of programs for sale or used as an inducement to buy another product or program without the written permission of the author. Permission is also given for nonprofit computer clubs to include this program in distribution disks, provided total charges for the entire disk of programs, copying and shipping do not exceed $20.00. My vote of thanks goes to those clubs that have kept their charges under $10.00. Donation If you like the program and use it, a small donation of about $5.00 would be appreciated, though it is not required to use ENCODE. I will do my part to keep ENCODE maintained. Please report any bugs to me at the above address or phone number. I can also be reached by leaving a message on the Glendale Literaria RCP/M (818) 956-6164. Other dBASE Utilities I have two other programs that may be of interest to dBASE II users. They are: DBSOURCE, a program to return encoded dBASE II command files to source code. And DBINDENT, to pretty print dBASE II source code. The current versions are in DBSRC102.LBR and DBINDENT.LBR. MBASIC and BRUN are Trademarks of Microsoft. dBASE II, DBCODE and RUNTIME are Trademarks of Ashton-Tate. d total charges for the entire disk of programs, copying and shipping do not exceed $20.00. My vote of thanks goes to those clubs that have kept their charges under $10.00. Donation If you like the program and use it, a small donation of about $5.00 would be appreciated, though it is not required to use ENCODE. I will do my part to keep ENCODE maintained. Please report any bugs to me at the above address or phone number. I can also be reached by leaving a message on the Glendale Literaria RCP/M (818) 956-6164. Other dBASE Utilities I have two other programs that may be of interest to dBASE II users. They are: DBSOURCE, a program to return encoded dBASE II command files to source code. And DBINDENT, to pretty print dBASE II source code. The current versions are in DBSRC102.LBR and DBINDENT.LBR. MBASIC and BRUN are Trademarks of Microsoft. dBASE II, DBCODE and RUNTIME are COPYRIGHT (C) 1984 BY GENE HEAD ALL RIGHTS RESERVED SCHEDULED TO APPEAR IN THE AUGUST ISSUE OF DDJ More dBASE II Programming Techniques Gene Head 6-13-84 In my last article (DDJ #92 - JUNE '84) I described a machine language subroutine called ZIP-CHK.ASM that partially validated zip codes and could be used by dBASE II using the LOAD FILE, SET CALL TO ADDRESS, and CALL VARIABLE commands. I now realize that older versions of dBASE II do not support the LOAD FILE command that facilitate the loading of machine language modules from assembled HEX files. However, most early versions of dBASE II (pre 2.4) WILL support the SET CALL TO ADDRESS and CALL VARIABLE even though these commands may be undocumented in the user's manual. In this article I will explain these and some other undocumented features of early versions of dBASE II. I only have access to versions 2.3 and 2.4 so other versions are untested and should be checked thoroughly to determine the feature actually works as I will describe it. I would appreciate feed back to my home address or phone number of any results you may have on versions prior to 2.3. I will catalog your findings and pass them on in future articles. In addition to the undocumented features I have included a description of the HEX file format and a dBASE II command file that will simulate the LOAD FILE command IF you can get the undocumented PEEK and POKE to work. After reviewing the format of the HEX file you should be able to write a LOAD simulator in any high level language using LOAD-HEX.CMD as a guideline. PRE-2.4 UNDOCUMENTED COMMANDS ----------------------------- PEEK(aaaaa) will return the contents of a decimal address. POKE aaaaa,nnn will fill a decimal address with a decimal value. SET CALL TO aaaaa will set the call address to a decimal value. CALL VARIABLE will call the address as defined in the SET CALL TO command and pass the string VARIABLE as follows: Upon entry of the subroutine the HL register pair will point to the location of the passed variable. The variable is stored in the format LENGTH BYTE followed by the actual string characters. For example if the variable ZIP represents the string '97330' then upon CALLing a subroutine HL would point to a series of locations with the following data bytes in hex: 05, 39, 37, 33, 33, 30. The HL pair points to the 05 and indicates there are five bytes in this string. The next 39, 37, 33, 33, 30 are the hex bytes that represent the ASCII string '97330'. You can modify the string but you must NOT increase the length of the variable. If the string becomes shorter you should fill it with trailing blanks. TEST(variable) will test the variable and return the following: -6 if the value is NUMERIC type 0 if the variable does not exist 1 if the variable is LOGICAL type nn (a number between 1 and 255) to indicate the length of a STRING type variable. LOADING A HEX FILE ------------------ The HEX file is simply an ASCII text file that holds information about what bytes go where. The LOAD.COM program usually is used with the HEX file to create an executable COM file. The format of any HEX file is as follows: :10A470002356235E22F0A401080021F2A47EFE07E9 <-- line 1 :10A48000CACFA4BACA8BA409C37DA4237EBBCA9633 <-- line 2 (30 lines were deleted in this example) :10A672005756323437323638574935333035343914 <-- line 33 :09A68200575938323038333100E9 <-- line 34 :0000000000 <-- line 35 In a HEX file every line ends with a carriage return followed by a line feed and begins with a colon. In the above example in line one the next two bytes following the colon, '10', are two ASCII characters that represent one HEX value in the range 00-FF (0 to 255 decimal). I will call this value the NUMBER OF BYTE-PAIRS value. We will get back to it in just a bit. (No pun intended.) The next four bytes 'A470' are ASCII characters that represent a HEX value in the range of 0000-FFFF (00000 to 65,535 decimal). I will call this value the FIRST LOAD ADDRESS. The next two bytes '00' are ASCII characters that are reserved. That means I don't know what they are for but in every HEX file I have ever looked at these two bytes are always '00' and for the scope of this article I don't think it is necessary to define them exactly. The same can be said for the last two bytes on each line ('E9' in line 1). A checksum maybe? The following bytes 02, 35, 62, 35 etc. should be viewed as byte-pairs. Remember the NUMBER OF BYTE-PAIRS mentioned earlier? Well that is exactly the number of these byte-pairs we will load into consecutive memory starting at the FIRST LOAD ADDRESS. Each of these byte-pairs are ASCII characters that represent a HEX value in the range of 00-FF (0 to 255 decimal). From the example of line 1 the address locations should be filled with the corresponding byte values as follows: A470 23 A478 08 A471 56 A479 00 A472 23 A47A 21 A473 5E A47B F2 A474 22 A47C A4 A475 F0 A47D 7E A476 A4 A47E FE A477 01 A47F 07 If your high level language does not support a LOAD function you can simulate one if you can read a text file and PEEK at and POKE into memory. The command file LOAD-HEX.CMD was written for dBASE II. dBASE II only understands decimal numbers and most of the code is converting two ASCII bytes to a decimal number to be POKED into memory. Understanding the format of the HEX file as outlined should enable you to write your own HEX loader simulator in any language. Using LOAD-HEX.CMD as guide, process line 1 of the HEX file. Extract the load address (position 4-7 in the string), the number of BYTE-PAIRS to POKE (position 2-3) and the individual BYTE-PAIRS (beginning at position 10). POKE each BYTE-PAIR then process the next line of the HEX file. Continue processing sequential lines until the NUMBER OF BYTE-PAIRS is equal to zero. The HEX file is now loaded into memory and ready to CALL as a machine language subroutine. < < < < end of manuscript program listing follows > > > > * LOAD-HEX.CMD * * File to simulate the LOAD feature of dBASE II 2.4 in * earlier versions that do not support this feature. * * Verify that PEEK and POKE commands work before typing * in this file and watch the syntax especially '(' & ')'. * * From: Head Quarters * 2860 NW Skyline Drive * Corvallis, Oregon 97330 * (503) 758-0279 * * Copyright 1984 by Gene Head - All rights reserved * For private, non-commercial use only. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SET TALK OFF * ---> First time initialization * * The following need be done only once * * First CREATE a file named HEXDATA.DBF with ONE * field NAMED DATA of CHARACTER type, forty-four * (44) characters in length. * * APPEND FROM the SUBROUTINE HEX file using the SDF option. * If you were going to use the Subroutine ZIP-CHK.HEX file then: * * . * .USE HEXLOAD * .APPEND FROM ZIP-CHK.HEX SDF * . * * <--- End of first time initialization * Each line of HEX data will be in the field named DATA USE HEXDATA * POSITION IN THIS STRING IS THE DECIMAL VALUE OF THE HEX CHARACTER * (SEARCHING FOR A '0' RETURNS 0) STORE '123456789ABCDEF' TO HEX * ---> COMPUTE THE BASE LOCATION OF THIS LOAD (THIS FUNCTION IS OPTIONAL) STORE STR(((@($(DATA,4,1),HEX)*16 + @($(DATA,5,1),HEX)) * 256) +; (@($(DATA,6,1),HEX)*16 + @($(DATA,7,1),HEX)),5) TO CALL:ADR SET CALL TO &CALL:ADR * <--- END OF LOCATION OPTION DO WHILE $(DATA,2,2) <> '00' * Compute how many bytes to POKE from this line of the HEX file STORE (@($(DATA,2,1),HEX)*16 + @($(DATA,3,1),HEX)) TO COUNT * Get the starting POKE address  STORE ((@($(DATA,4,1),HEX)*16 + @($(DATA,5,1),HEX)) * 256); + (@($(DATA,6,1),HEX)*16 + @($(DATA,7,1),HEX)) TO ADDRESS * We POKE the last BYTE-PAIR on the line of the HEX file * and work our way back to the first BYTE-PAIR on the line. DO WHILE COUNT STORE STR(ADDRESS+COUNT-1,5)+','+STR(@($(DATA,COUNT*2+8,1),; HEX)*16+@($(DATA,COUNT*2+9,1),HEX),3) TO BYTE POKE &BYTE STORE COUNT -1 TO COUNT ENDDO WHILE COUNT * GET NEXT LINE OF HEX DATA SKIP ENDDO WHILE $(DATA,2,2) <> '00' USE STORE STR(((@($(DATA,4,1),HEX)*16 + @($(DATA,5,1),HEX)) * 256) +; (@($(DATA,6,1),HEX)*16 + @($(DATA,7,1),HEX)),5) TO CALL:ADR SET CALL TO &CALL:ADR * <--- END OF LOCATION OPTION DO WHILE $(DATA,2,2) <> '00' * Compute how many bytes to POKE from this line of the HEX file STORE (@($(DATA,2,1),HEX)*16 + @($(DATA,3,1),HEX)) TO COUNT * Get the starting POKE address  * ADVERTISEMENT * * + + + + + + + + + + + + + + + + + + + + + * + + + IF YOU LIKE NEWBASEx.ASM YOU WILL LOVE DBSEX.LBR + + + + * + + + + + + + + + + + + + + + + + + + + + * *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::* * * * LEGAL STUFF UP FRONT * * * * NEWBASE.ASM * * * * 1984 (c) Copyright by * * Gene Head * * 2860 NW Skyline Drive * * Corvallis, Oregon 97330 (503) 758-0279 * * * * All rights reserved. * * * * Released for non-commercial, private use only. * * Released for no-profit use only. If you make any money * * using this overlay or use it in your business I expect * * fair compensation to be mailed to the address above. * * * * I also support the DBRUN, the dBASE II run-time * * package for a modest fee per installation. * * * *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::* * * * * * * * * * * * * E D I T O R I A L * * * * * * * * * * * * * This overlay is intended for the use of licensed users of * * dBASE II only. If you 'own' a copy of dBASE II that you * * did not purchase or receive legitimately you are a thief, * * it is that simple. Stealing software will only drive up * * prices for legal users and dry up the sources of quality * * software products. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *********************************************************************** * * PROGRAM DOCUMENTATION STUFF STARTS HERE * * PROGRAM NAME --> NEWBASEx.ASM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 07/20/85 <-- Last update (Added equates for version 2.43*) * NOTE: There is a big difference between version * 2.43* (notice the *) and plain 2.43. * * 04/22/85 <-- Last update (Partial support of version 2.3B restored) * Version 2.3B will NOT support full ZCPR operation. You * CAN specify a default drive where overlays will be found. * -Gene Head * * 03/20/85 <-- Last update (tried to fix all the ASM nesting problems) * ASM.COM will not consistantly recognize nested conditionals! * I tried to figure out all the logic to un-nest the nested * conditionals. Also added the ESCape key disable on all * supported versions. (VERSION 2.3B NO LONGER SUPPORTED) * -Gene Head * * 03/18/85 <-- Last update (added ESCape key disable option) * Added ESCape disable option so that users may * not abort a program file before it has time to * SET ESCAPE OFF. SET ESCAPE OFF should still be * one of the first lines in your command file. * -Ryan Katri * * 03/17/85 <-- Last update (added Z-80 2.43 equates) * Fixed a problem that ASM was having when dealing * with a nested IF near ZCPRFIX that caused problems * only when ZCPR was set FALSE. * -Ryan Katri * * 02/20/85 <-- Last update (added 2.43 equates for Paul Foote) * Skip-sign-on will no longer skip the copyright stuff. * Ashton-Tate went to some lengths to make sure it stayed * in place so I decided it must be pretty important to * them. However, the long list of threats and legal * mumbo-jumbo can be skipped. * -Gene Head * * 10/25/84 <-- Last update (define the label delimiter character) * Gary Knapp asked for this one to make labels more * readable. THIS_LABEL instead of the old THIS:LABEL * -Gene Head * * 09/21/84 <-- Last update (added PREDEFINED option) * Force dBASE II to execute a pre-defined command file. * -Gene Head * * 08/10/84 <-- Last update (added equates for Z-80 version 2.41) * Re-ordered these updates to reflect most recent first. * -Ryan Katri * * 07/25/84 <-- Last update (added version 2.41 equates) * Removed ELSE conditionals so this can be assembled * with ASM and added version 2.41 equates. * (Also added assembly error messages) * -Gene Head * * 07/23/84 <-- Last update (force command file execution) * Some folks want to keep un-trained users from the * dot-prompt. This patch will do a warm boot if a * valid command file was not specified when DBASE.COM * was executed. * -Gene Head * * 07/18/84 <-- Last update (skip date option installed) * Some folks have time and date functions available * and do a date and time set as part of an initiali- * zation command so want to skip the ENTER DATE stuff. * -Gene Head * * 06/20/84 <-- Last update * Some folks want to skip the sign-on messages. * -Gene Head * * 05/25/84 <-- Last update * Some folks run ZCPR or a ZCPR look-alike and would * like dBASE II to run from drive A: regardless of the * default drive it was executed from. * -Gene Head * * 05/01/84 <-- Last update * Moved the KEYIN cubby hole from low memory in * the screen defination area to high memory * so that INSTALL.COM does not disturb it. * -Gene Head * * 04/01/84 <-- Last update * Some folks need a way to exit a long or forever * DO WHILE loop from a keyboard command. (Like the * INKEY$ function found in most BASIC's) * -Gene Head * * If you happen to transport any of these features to the * MS-DOS version of dBASE II please let me know how you did it. * * I'm also interested in supporting 2.3 and earlier versions. * If you have an earlier version and want this modification * installed please contact me at the above address or phone. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SKIPDATE: * * SKIPDATE will skip the ENTER DATE question at sign-on. * * SKIPSIGNON: * * SKIPSIGNON will skip all the sign-on stuff and go directly * to the dot-prompt. (To skip the sign-off message simply * SET CONSOLE OFF just prior to the * QUIT or QUIT TO command. * * SKIPOPT: * * SKIPOPT option allows a list of selected options to be * displayed at sign-on. * * FORCE: * * FORCE option forces a warm boot if a valid command file * was not specified when DBASE.COM was executed. Keeps * undesireables from the dot-prompt. * * PREDEFINED: * * PREDEFINED option forces dBASE II to execute a pre-defined * command file. This simulates an auto-start mode without * a submit file AND prevents command level operation. * * KEYIN: * * The KEYIN option will allow you to PEEK at the last key * press at the keyboard. Useful for aborting DO WHILE loops. * * PEEK(337) will hold the last key pressed. * * ESCAPE: * * Disables the ESCape (abort) function so that users may * not break out of a .CMD file. The problem arises even * with SET ESCAPE OFF, because between the time that the * file is being loaded and ESCAPE is SET OFF, a user could * hit ESCape and dBASE would recognize it and respond * accordingly. The ESCAPE option is available for for all * supported versions. * * ZCPR: * * ZCPR compatibility allows execution from the A: drive if * the program can't be located on the default drive. * * NOTE: This fixes only the access to the DBASEOVR.COM * file and NOT the DBASEMSG.TXT file. If you use * the on-line HELP command the DBASEMSG.TXT file * must be on the default drive. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * BE SURE YOU HAVE A BACK-UP COPY OF DBASE.COM BEFORE YOU * * * ATTEMPT TO USE THIS OVERLAY * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Simply SET the proper equates, assemble this file then * integrate it using the following DDT commands: * * A>DDT DBASE.COM * DDT VERS 2.2 * NEXT PC * 4D00 0100 * -INEWBASE.HEX * -R * NEXT PC * 4D00 0000 * -G0 * A>SAVE 76 DBASE.COM OR SAVE 77 DBASE.COM if you install * a forced, predefined command file * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * BE SURE YOU HAVE A BACK-UP COPY OF DBASE.COM BEFORE YOU * * * ATTEMPT TO USE THIS OVERLAY * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * PROGRAM STUFF STARTS HERE * TRUE EQU 0FFH ;'YES' FALSE EQU NOT TRUE ;'NO' * * * INITIAL JUMP LIST * ***************** * * To help identify supported versions I have developed the * following list of the jump instruction that must be found at * location 100H for each supported version. * * Version Jump instruction at location 100h * ------- --------------------------------- * * 2.3B JMP 4473 * 2.4 JMP 46C9 * 2.41 JMP 477A * 2.41Z JMP 467F * 2.43 JMP 49B5 * <-- ABANDONED VERSION * 2.43Z JMP 5200 * <-- ABANDONED VERSION * 2.43* JMP 4C0F * * If your version of DBASE.COM is not listed call me for help. * * * THE FOLLOWING ARE THE ONLY USER SELECTABLE OPTIONS IN THIS OVERLAY * *  Choose ONE AND ONLY ONE of the following versions to be * 'TRUE'. All others MUST be 'FALSE'. * VER23B EQU FALSE ;SET TO 'TRUE' IF RUNNING VERSION 2.3B VER24 EQU FALSE ;SET TO 'TRUE' IF RUNNING VERSION 2.4 VER241 EQU FALSE ;SET TO 'TRUE' IF RUNNING VERSION 2.41 VER241Z EQU FALSE ;SET TO 'TRUE' IF RUNNING Z-80 2.41 VER243 EQU TRUE ;SET TO 'TRUE' IF RUNNING VERSION 2.43* * * SET THE FOLLOWING EQUATES TO TRUE OR FALSE FOR YOUR ENVIRONMENT * SKIPDATE EQU TRUE ;SET TO 'TRUE' TO SKIP DATE SET AT SIGN-ON SKIPSIGNON EQU TRUE ;SET TO 'TRUE' TO SKIP SIGN-ON MESSAGE SKIPOPT EQU FALSE ;SET TO 'TRUE' TO SKIP OPTIONS AT SIGN-ON FORCE EQU FALSE ;SET TO 'TRUE' TO FORCE A COMMAND FILE KEYIN EQU TRUE ;SET TO 'TRUE' TO ALLOW KEY-IN FEATURE ZCPR EQU TRUE ;SET TO 'TRUE' IF RUNNING ZCPR OR LOOK-ALIKE PREDEFINED EQU FALSE ;SET TO 'TRUE' FOR PRE-DEFINED COMMAND FILE ESCAPEOFF EQU FALSE ;SET TO 'TRUE' TO DISABLE THE ESCape FUNCTION DEFAULT EQU 'A'-40H ;DEFAULT DRIVE IF RUNNING ZCPR CDELIMIT EQU ':' ; PUT YOUR FAVORITE DELIMIT CHARACTER HERE * ; ie. STORE 9 TO THIS:ONE can be changed * ; to STORE 9 TO THIS_ONE by setting this * ; equate to '_' * * ---> * * * NOTE: If you set PREDEFINED to TRUE then you MUST * ---> * * * put your command line at label COMMAND near the * ---> * * * end of this overlay. Currently 'MENU.CMD' * * END OF USER SELECTED EQUATES. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * KEYPATCH EQU 14AH ;PUT INKEY PATCH HERE FOR ALL VERSIONS ;TO MAINTAIN TRANSPORTABILITY. PEEK(337) ;ON ANY NEWBASE INSTALLATION WILL NOW ;RETURN THE LAST KEY PRESSED. IF VER23B * DBASE II VERSION 2.3B SIGN-ON DATE 22 FEB 1982 BEGIN EQU 4473H ;JUMP AROUND INSTALLED PARAMETERS SKIP1 EQU 461AH ;SKIP DATE HOOK SKIP2 EQU 46AFH ;SKIP DATE DESTINATION DATEFIX EQU 00FEH ;DATE FIX FOR RE-ENTRY CONSIO EQU 39F0H ;KEYIN HOOK SAVE1 EQU 39DFH ;DIRECT BIOS HOOK MESSAGE EQU 46BBH ;FIRST BYTE OF SIGN-ON MESSAGE MESS1 EQU 46E1H ;NEWBASE MESSAGE HOOK FCB1 EQU 42F3H ;FCB1 FOR DBASEOVE.COM FCB2 EQU 4314H ;FCB2 FOR DBASEOVR.COM BUFFERS EQU 46C0H ;START OF BUFFERS HELLO EQU 47D0H ;HELLO MESSAGE DELIMIT EQU 2AE4H ;LOCATION OF DELIMIT CHARACTER DISABLE EQU 39AEH ;ZERO OUT FOR ESCAPE DISABLE (CPI 1BH) NEWREC EQU 4B00H ;ADDED RECORD FOR PREDEFINED OPTION ;SHOULD BE THE SAME AS NEXT LOAD ;WHEN DDT LOADS DBASE.COM ENDIF ;VER23B IF VER24 * DBASE II VERSION 2.4 SIGN-ON DATE APRIL 1, 1983 BEGIN EQU 46C9H ;JUMP AROUND INSTALLED PARAMETERS SKIP1 EQU 4876H ;SKIP DATE HOOK SKIP2 EQU 4892H ;SKIP DATE DESTINATION DATEFIX EQU 00FEH ;DATE FIX FOR RE-ENTRY CONSIO EQU 3A8AH ;KEYIN HOOK SAVE1 EQU 4378H ;dBASE II CUBBY-HOLE MESSAGE EQU 495AH ;FIRST BYTE OF SIGN-ON MESSAGE MESS1 EQU 46B5H ;NEWBASE MESSAGE HOOK FCB1 EQU 4331H ;FCB1 FOR DBASEOVE.COM FCB2 EQU 4352H ;FCB2 FOR DBASEOVR.COM XZCPR EQU 3BA6H ; ZCPR HOOK ZCPRRET EQU 3BA9H ;JUMP-BACK LOCATION BUFFERS EQU 497EH ;START OF BUFFERS HELLO EQU 4AE1H ;HELLO MESSAGE FREE EQU 44C9H ;UN-USED PROGRAM SPACE ENDCODE EQU 44FFH ;END OF SAFE AREA DELIMIT EQU 2B3BH ;LABEL DELIMITER POSITION DISABLE EQU 3A47H ;ZERO OUT FOR ESCAPE DISABLE (CPI 1BH) NEWREC EQU 4D00H ;ADDED RECORD FOR PREDEFINED OPTION ;SHOULD BE THE SAME AS NEXT LOAD ;WHEN DDT LOADS DBASE.COM ENDIF ;VER24 IF VER241 * DBASE II VERSION 2.41 SIGN-ON DATE FEBRUARY 1, 1984 BEGIN EQU 477AH ;JUMP AROUND INSTALLED PARAMETERS SKIP1 EQU 4927H ;SKIP DATE HOOK SKIP2 EQU 4943H ;SKIP DATE DESTINATION DATEFIX EQU 00FEH ;DATE FIX FOR RE-ENTRY CONSIO EQU 3B25H ;KEYIN HOOK SAVE1 EQU 4429H ;dBASE II CUBBY-HOLE MESSAGE EQU 4A0BH ;FIRST BYTE OF SIGN-ON MESSAGE MESS1 EQU 4A58H ;NEWBASE MESSAGE HOOK FCB1 EQU 43E2H ;FCB1 FOR DBASEOVE.COM FCB2 EQU 4403H ;FCB2 FOR DBASEOVR.COM XZCPR EQU 3C49H ;ZCPR HOOK ZCPRRET EQU 3C4CH ;JUMP-BACK LOCATION BUFFERS EQU 4A37H ;START OF BUFFERS HELLO EQU 4B77H ;HELLO MESSAGE FREE EQU 457AH ;UN-USED PROGRAM SPACE ENDCODE EQU 46FFH ;END OF SAFE AREA DEFDRV EQU 0165H ;DEFAULT DRIVE STORAGE DELIMIT EQU 2B99H ;LABEL DELIMITER POSITION DISABLE EQU 3AE2H ;ZERO OUT FOR ESCAPE DISABLE (CPI 1BH) NEWREC EQU 4D00H ;ADDED RECORD FOR PREDEFINED OPTION ;SHOULD BE THE SAME AS NEXT LOAD ;WHEN DDT LOADS DBASE.COM ENDIF ;VER241 IF VER241Z * Z-80 DBASE II VERSION 2.41 SIGN-ON DATE APRIL 1, 1983 BEGIN EQU 467FH ;JUMP AROUND INSTALLED PARAMETERS SKIP1 EQU 482CH ;SKIP DATE HOOK SKIP2 EQU 4904H ;SKIP DATE DESTINATION DATEFIX EQU 00FEH ;DATE FIX FOR RE-ENTRY CONSIO EQU 3A75H ;KEYIN HOOK SAVE1 EQU 3A64H ;DIRECT BIOS HOOK MESSAGE EQU 4910H ;FIRST BYTE OF SIGN-ON MESSAGE MESS1 EQU 495DH ;NEWBASE MESSAGE HOOK FCB1 EQU 42E7H ;FCB1 FOR DBASEOVE.COM FCB2 EQU 4308H ;FCB2 FOR DBASEOVR.COM XZCPR EQU 3B90H ;ZCPR HOOK ZCPRRET EQU 3B93H ;JUMP-BACK LOCATION BUFFERS EQU 493CH ;START OF BUFFERS HELLO EQU 4A7CH ;HELLO MESSAGE FREE EQU 4480H ;UN-USED PROGRAM SPACE ENDCODE EQU 44FFH ;END OF SAFE AREA DEFDRV EQU 0165H ;DEFAULT DRIVE STORAGE DELIMIT EQU 2B25H ;LABEL DELIMITER POSITION DISABLE EQU 3A48H ;ZERO OUT FOR ESCAPE DISABLE (CPI 1BH) NEWREC EQU 4D00H ;ADDED RECORD FOR PREDEFINED OPTION ;SHOULD BE THE SAME AS NEXT LOAD ;WHEN DDT LOADS DBASE.COM ENDIF ;VER241Z IF VER243 * DBASE II VERSION 2.43* SIGN-ON DATE APRIL 30, 1985 BEGIN EQU 4C0FH ;JUMP AROUND INSTALLED PARAMETERS SKIP1 EQU 4DD6H ;SKIP DATE HOOK SKIP2 EQU 4DF2H ;SKIP DATE DESTINATION DATEFIX EQU 4941H ;DATE FIX FOR RE-ENTRY CONSIO EQU 3F24H ;KEYIN HOOK SAVE1 EQU 4867H ;dBASE II CUBBY-HOLE MESSAGE EQU 4EC8H ;FIRST BYTE OF SIGN-ON MESSAGE 1 MESS1 EQU 4F1BH ;NEWBASE MESSAGE HOOK MESS2 EQU 5049H ;FIRST BYTE OF SIGN-ON MESSAGE 2 FCB1 EQU 4820H ;FCB1 FOR DBASEOVE.COM FCB2 EQU 4841H ;FCB2 FOR DBASEOVR.COM XZCPR EQU 404DH ;ZCPR HOOK ZCPRRET EQU 4050H ;JUMP-BACK LOCATION BUFFERS EQU 4ECDH ;START OF BUFFERS HELLO EQU 5339H ;HELLO MESSAGE FREE EQU 4A0FH ;UN-USED PROGRAM SPACE ENDCODE EQU 4A7FH ;END OF SAFE AREA DEFDRV EQU 0165H ;DEFAULT DRIVE STORAGE DELIMIT EQU 2E36H ;LABEL DELIMITER POSITION DISABLE EQU 3ED9H ;ZERO OUT FOR ESCAPE DISABLE (CPI 1BH) NEWREC EQU 5480H ;ADDED RECORD FOR PREDEFINED OPTION ;SHOULD BE THE SAME AS NEXT LOAD ;WHEN DDT LOADS DBASE.COM ENDIF ;VER243* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * WBOOT EQU 0 ;WARM BOOT BDOS EQU 5 ;BDOS ENTRY OPEN EQU 0FH ;OPEN FILE FUNCTION FAILED EQU 0FFH ;DISK I-O FAILED * * IF CDELIMIT ORG DELIMIT DB CDELIMIT ENDIF IF ESCAPEOFF ORG DISABLE DB 0 ;ZERO OUT BYTE 1 (FE=CPI INSTRUCTION) DB 0 ;ZERO OUT BYTE 2 (1B=ASCII CODE FOR ESC) ENDIF ;ESCAPEOFF * * Patch here if either SKIPDATE or COMMAND options are true. * Note COMMAND option has highest priority IF SKIPDATE ORG SKIP1 LXI H,0 SHLD DATEFIX JMP SKIP2 ;. . . BYPASS DATE STUFF AT SIGN-ON ENDIF ;SKIPDATE * OR IF FORCE ORG SKIP1 JMP WBOOT ;. . . FORCE A COMMAND FILE ENDIF ;FORCE * IF PREDEFINED ORG 100H JMP CLINE ENDIF ;PREDEFINED * IF SKIPSIGNON ORG MESSAGE DB 0 ;CANCEL SIGN ON MESSAGE ORG MESS1 LXI H,HELLO ;NEWBASE OPTIONS MESSAGE ENDIF ;SKIPSIGNON IF VER243 AND SKIPSIGNON ORG MESS2 ;MORE TO SKIP THE SIGN-ON DB 0 ENDIF ; AND SKIP SIGNON * * patch for new KEYIN psudo-function IF KEYIN ORG CONSIO JMP XKEYIN ENDIF ;KEYIN IF KEYIN AND (VER241Z OR VER23B) ORG SAVE1 ;Fix direct BIOS hook SHLD XKEYIN+1 ENDIF ;KEYIN AND (VER241Z OR VER23B) * * FIX THE BUFFERS ORG BUFFERS IF VER24 OR VER241 OR VER243 OR VER23B SBB H ;BUMP BUFFER 1 POINTER ADC D ;ADD OFFSET XRA M ;ADJUST BY BUFFER 1 VALUE ENDIF ;VER24 OR VER241 OR VER243 OR VER23B IF VER241Z ORA H ;FIX BUFFER OFFSET IN Z-80 VERSION MOV E,M ENDIF ;VER241Z ADD H ; ... BUMP !AGAIN ADD D ; ... AND AGAIN ANA M ;NOW DO BUFFER 2 ADC D DB 40H,40H * IF SKIPOPT ORG HELLO DB 0 ENDIF ;SKIPOPT IF NOT SKIPOPT ORG HELLO DB 0DH,0AH,0AH ENDIF ;NOT SKIPOPT IF ZCPR AND NOT SKIPOPT DB 'ZCPR Compatible' ENDIF ;ZCPR AND NOT SKIPOPT IF ZCPR AND KEYIN AND NOT SKIPOPT DB ' + ' ENDIF ;ZCPR AND KEYIN AND NOT SKIPOPT IF KEYIN AND NOT SKIPOPT DB 'KEYIN at --> 337' ENDIF ;KEYIN AND NOT SKIPOPT IF (KEYIN OR ZCPR) AND NOT SKIPOPT DB 0DH,0AH,0 ENDIF ;(KEYIN OR ZCPR) AND NOT SKIPOPT * new, added code begins here and must end before 44FFH * IF KEYIN XKEYIN: ORG KEYPATCH ENDIF ;KEYIN IF (VER24 OR VER241 OR VER243) AND KEYIN STA SAVE1 ;SAVE FOR dBASE.COM ENDIF ;(VER24 OR VER241 OR VER243) AND KEYIN IF (VER241Z OR VER23B) AND KEYIN CALL 0 ;PATCHED BY Z-80 DBASE II ENDIF ;(VER241Z OR VER23B) AND KEYIN IF KEYIN STA SAVE2 ;SAVE FOR KEYIN RET SAVE2 DS 1 ;KEYIN CUBBY-HOLE (decimal value) ENDIF ;KEYIN *  IF ZCPR AND (NOT VER23B) ORG XZCPR JMP ZCPRFIX ORG FREE ZCPRFIX CPI FAILED JNZ ZCPRRET ;FILE OPEN OK SO RETURN LXI D,FCB1 MVI A,DEFAULT ;SET UP FOR DEFAULT DRIVE STAX D STA FCB2 ENDIF ;ZCPR AND (NOT VER23B) IF (VER241 OR VER241Z OR VER243 ) AND ZCPR STA DEFDRV ;DEFAULT DRIVE STORAGE ENDIF ;(VER241 OR VER241Z OR VER243 ) AND ZCPR IF ZCPR AND (NOT VER23B) MVI C,OPEN CALL BDOS ;TRY TO OPEN DBASEOVR.COM CPI FAILED ; . .ON DEFAULT DRIVE JNZ ZCPRRET ;GO BACK IF FOUND RET ;RETURN WITH ZERO SET IF ENDIF ;ZCPR IF ZCPR AND VER23B ORG FCB1 DB DEFAULT ORG FCB2 DB DEFAULT ENDIF BODYEND EQU $ * IF PREDEFINED ORG NEWREC CLINE LXI H,COMMAND ;POINT TO PRE-DEFINED COMMAND LINE LXI D,80H ;DEFAULT COMMAND LINE BUFFER MOV B,M ;LENGTH OF COMMAND LINE CLINE1 MOV A,M STAX D ;MOVE IT TO BUFFER AS THO IT INX H ;...IT HAD BEEN ENTERED FROM INX D ;......THE KEYBOARD DCR B JM CLINE2 JMP CLINE1 CLINE2 LXI H,5CH LXI D,XFCB MVI B,12 CLINE3 LDAX D MOV M,A INX H INX D DCR B JNZ CLINE3 JMP BEGIN * * Try to keep the command line short as there isn't much room left * if all the options are installed. * COMMAND DB CMDEND-COMMAND DB 'MENU.CMD' ;<-- PUT COMMAND LINE HERE IN SINGLE ; . . . JUST AS YOU WOULD TYPE IT. CMDEND EQU $ XFCB: DB '@'-40H ;<-- DRIVE '@' FOR DEFAULT DRIVE DB 'MENU CMD' ;<-- MUST BE 11 CHARACTERS EXACTLY ;<-- LIKE 'MYFILE CMD' NO PERIOD ;<-- JUST FILENAME OF EXACTLY EIGHT ;<-- CHARACTERS FOLLOWED BY THREE FILE ;<-- TYPE CHARACTERS. ENDIF ;PREDEFINED F BODYEND EQU $ * IF PREDEFINED ORG NEWREC CLINE LXI H,COMMAND ;POINT TO PRE-DEFINED COMMAND LINE LXI D,80H ;DEFAULT COMMAND LINE BUFFER MOV B,M ;LENGTH OF COMMAND LINE CLINE1 MOV A,M STAX D ;MOVE IT TO BUFFER AS THO IT INX H ;...IT HAD BEEN ENTERED FROM INX D ;......THE KEYBOARD DCR B JM CLINE2 JMP CLINE1 CLINE2 LXI H,5CH LXI D,XFCB MVI B,;---------------------------------------------------------------------- ; VDBTYPE.ASM VERSION 1.0 MAY 9, 1985 (C) Norman H. Strassner ; ; This assembly language subroutine will, when assembled by ASM.COM and ; loaded into high memory by Dbase][, permit the typing of text files ; using a simple 'CALL' from Dbase][. These files may be standard ASCII or ; squeezed text files and may reside inside a Novieleski library, in any ; drive or user area. ; ; ****** THIS FILE IS NOT AN INDEPENDENTLY EXECUTABLE .COM FILE ****** ; ****** IT MUST BE USED AS A CALLED FUNCTION UNDER DBASE][ ****** ;---------------------------------------------------------------------- ; To assemble: ; A>REN VDBTYPE.ASM=VDBTYP10.ASM ;(make it an easier name) ; A>ASM VDBTYPE.AAZ ;You won't need a .PRN file ; ; In Dbase][, the format would be as follows: ; ; 1. Load the hex file: (Dbase][ assumes an extension of .HEX) ; LOAD VDBTYPE ; ; 2. Establish a "SET CALL TO": ; ; SET CALL TO 41984 (This may be changed according to the ; 'ORG' statement at start of the program) ; ; 3. Store the filename, including optional drive/user and library name ; information to a memory variable: ; ; STORE '[DRIVE] [USER] [:] [LIBRARY] ' TO ; ^^^^^^^^^^^^^^^^^^(see note below)^^^^^^^^^^^^^^^^^^^^^^^ ; ; 4. Use the "CALL" instruction to pass the variable to VDBTYPE ; CALL ; ; The filename will now be typed on your screen, with pauses every ; 23 lines. A ^C will abort the listing and return you to Dbase][. ; ;----------------------------------------------------------------------- ; * Notes on filenames: ; Examples of valid filenames to store to a dbase][ memory variable: ; if the dbase variable name is 'FNAME' ; ; This will type 'TEST.DAT' from the default drive/user ; STORE 'TEST.DAT' TO FNAME ; CALL FNAME ; ; This will unsqueeze 'TEST.DQT' from drive B, user 5 and type it ; STORE 'B5:TEST.DQT' TO FNAME ; CALL FNAME ; ; This will get 'TEST.DQT' from the library 'TEST"LBR', unsqueeze it, ; and type it out. ; STORE 'A1:TESTLBR TEST.DQT' TO FNAME ; CALL FNAME ;------------------------------------------------------------------- ; ; SAMPLE DBASE][ PROGRAM FOR USE WITH VDBTYP ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ; *VDBTYPE.CMD ; SET TALK OFF ; ERASE ; LOAD VDBTYPE ; SET CALL TO 41984 ; DO WHILE T ; ? ; ? 'Text typing program for Dbase][.' ; ? ; ? 'Any text file, squeezed or not, even residing in a library,' ; ? 'may be listed on your computer screen directly from Dbase][.' ; ? ; ? 'At the prompt below, you may enter any valid filename in the forms:' ; ? ; ? 'FILENAME.EXT ---> types FILENAME.EXT' ; ? 'FILENAME.EQT ---> unsqueezes and types FILENAME.EXT' ; ? 'A3:FILNAME.EXT ---> types the file from drive A, User 3' ; ? 'LBRNAME FILENAME.EXT ---> types the file from within a library' ; ? ; ACCEPT 'Enter the file to display, or RETURN to exit ' TO FNAME ; IF FNAME=' ' ; RETURN ; ENDIF ; CALL FNAME ; ENDDO ; ;------------------------------------------------------------------- ; ; From the original TYPEL32.MAC by ESKAY. All required subroutines that ; were originally called using the M80 assembler (SYSLIB.REL and USQB.REL ; files) were disassembled and incorporated into this .ASM file for easier ; assembly with ASM.COM or LASM.COM ; ; ; Revision History: ;--May 9, 1985-- ; Original writing. Donated to the public domain for free ; distribution and use. No one may charge for the use of this program ; without the express written permission of the author. ; ; Please report any bugs or updates to: ; ; Norman H. Strassner c/o ; VIDEOMAN RCP/M, XBBS, and DATABASES ; 1950 N. Normandie Ave. ; Los Angeles, Ca. 90027 ; Voice: (213) 661-5000 ; BBS: (213) 666-8588 1200/300bd ; ;------------------------------------------------------------------ ; ;some needed equates: CR EQU 0DH LF EQU 0AH BDOS EQU 0005H ; MXDRV: EQU 1+'P'-40H ;highest accessible drive + 1 (a=2) MXUSR: EQU 1+15 ;highest accessible user + 1 MXLPS: EQU 23 ;max lines per screen -1 (0= no page) ; ;------------------------------------------------------------------------- ; ; This program is 6k of .HEX file on disk, but will actually use ; about 4608 bytes (1200H bytes) of memory. For an 'ORG' of A400H, the ; last byte used for buffer space is at B5FFH, so do not locate any other ; program in high memory less than B600H for an ORG of A400H. ; ; 0A400H IS THE LOWEST POSSIBLE FREE MEMORY ADDRESS THAT DBASE][ DOES NOT ; USE FOR ANYTHING EXCEPT SORT ROUTINES. ** IF A SORT IS USED FROM DBASE][, ; THIS PROGRAM WILL BE WIPED OUT AND WOULD NEED TO BE LOADED AGAIN ; ORG 0A400H ;change this to suite your requirments ;dbase][ call set to 41984 for org at A400H ; ;------------------------------------------------------------------------- ; ;Start of program: ; TYPE: CALL PRINT DB CR,LF,'VDBTYPE 1.0 (C)1985 Norman H. Strassner',CR,LF,0 SKIPC: SHLD STRING ;save the string pointer ; LXI H,0 ;set up a local stack DAD SP SHLD STACK LXI SP,STACK ; LXI D,DBUF ;set up our own default buffer CALL SETDMA ; MVI A,MXLPS DCR A ;first page is one less than normal STA LPS CALL PUTUD ;save default du LXI H,BUFF+1024 ;...buffer size MOV A,H STA TOPRAM CALL RETUD ;get current drive/user MOV H,B MOV L,C SHLD USERNO ;save current du LHLD STRING MOV A,M INX H DCR A ;see if any file??? a=1=no=z JZ WHAT ; LXI D,FCB CALL FNAME ;parse file name JZ WHAT ;not a valid file name MOV A,M ;get delimiter STA FFLAG ;set flag lbr/non-lbr PUSH H ;save command line ptr INX B ;check if current du: MOV A,B ORA C DCX B ;restore du: value JZ CURRDU ;skip this if current MOV A,B ;get specified drive DCR B ;get into range 0..f CPI 0FFH ;ff means current drive MVI H,MXDRV MVI L,MXUSR JNZ NEWDSK ;skip if different LDA DRIVENO MOV B,A JMP CURDSK ; NEWDSK: CMP H JNC ILLDU ;yes - complain CURDSK: MOV A,C ;get specified user area CPI '?' ;all user areas??? JZ ILLDU ;yes - complain CPI 0FFH ;current user area? JNZ NEWUSR LDA USERNO MOV C,A JMP CURUSR ; NEWUSR: CMP L ;illegal user specified? JNC ILLDU ;yes - complain CURUSR: CALL LOGUD ;log into specified du: CURRDU: LDA FFLAG ;get flag CPI ' ' ;lbr member request? POP H ;get cmd line ptr back JNZ NOLBF ;nope, must be singlefile INX H ;get next char LXI D,MEMFCB ;point to member fcb CALL FNAME ;parse member name LXI H,FCB+9 ;default to .lbr MVI M,'L' INX H MVI M,'B' INX H MVI M,'R' LXI D,FCB CALL F$OPEN ;attempt to open file INR A JZ NOFILE ;not a lbr file CALL F$READ ;read directory into default buffer LXI H,DBUF ;point to dbuf LXI D,DIRNAME ;point to 8 blanks CALL CPFN ;compare JNZ NOLBR ;not equal LXI D,14 DAD D MOV A,M STA DIRSIZ ;directory size XRA A STA MEMFCB JMP C00 ;skip into directory check ; DIRLP: LXI D,FCB CALL F$READ C00: LXI B,20H LXI H,DBUF LXI D,MEMFCB CALL CPFN JZ FOUND CALL CPFN0 # JZ FOUND CALL CPFN0 JZ FOUND CALL CPFN0 JZ FOUND LDA DIRS INR A STA DIRS MOV B,A LDA DIRSIZ CMP B JNZ DIRLP CALL PRINT DB CR,LF DB 'Member file not found',CR,LF,0 JMP EREXT ; ; found the member file name in the ldir ; FOUND: LXI D,12 DAD D PUSH H ;save pointer for now, INX H ;point to size INX H MOV A,M ;get low byte INX H ORA M ;if a=0 then file is 0k JZ NULLEN ;go complain POP H ;get pointer back MOV A,M ;get file address INX H MOV H,M MOV L,A ; ; enter here from non-lbr routine with hl=0000 ; DOTYP: SHLD FCB+33 ;set random record LXI D,FCB ;get fcb... CALL RNDREAD ;...and read random LXI B,DBUF ;point to buffer LDAX B ;get first byte CPI 76H ;if not 76h (=not squeezed)... JNZ PLAIN ;...then process as text INX B ;point to and... LDAX B ;...get next byte CPI 0FFH ;if ff then squeezed.. JNZ PLAIN ;...else plain text (?) ; CALL UINIT CALL USQ ;now unsqueeze and print JMP GOTEOF ; ; this routine fills the buffer then calls the print routine ; PLAIN: MVI B,8 ;(bufsz*1024)/128 ;128 bytes each for 8 buffers=1024 bytes LXI D,BUFF ;this is the destination MLP: LXI H,DBUF ;this is the dbuf PUSH D LXI D,FCB CALL F$READ POP D JNZ GOTEOF ;...in unsqueezed single files MVI C,80H MMV1: MOV A,M ;get a dbuf character STAX D ;and move it to buff INX H ;increment buff ptr INX D ;increment dbuf ptr DCR C ;move bc number of bytes total JNZ MMV1 ;buffer is full, print it ; DCR B ;for 8 times JNZ MLP CALL BUFULL ;print the buffer JMP PLAIN ; GOTEOF: MVI M,1AH ;definitely eof CALL BUFULL JMP FINISHED ; ; this is the print buffer routine (bufull) ; BUFULL: PUSH H PUSH D PUSH B PUSH PSW LXI H,BUFF BUFLP: MOV A,M CPI 1AH JZ FINISHED CPI 'I'-40H JZ PROCTAB ANI 7FH ;strip high bits CALL CCOUT CPI LF JZ EOLN CALL CONDIN ;get keybd char if available JZ GOON ;none there, go on CPI 'C'-40H ;if ^c... JZ ABORT ;...then finished CPI 'S'-40H ;if not ^s... JNZ GOON ;...then go on, else... CALL CIN ;...wait for keypress CPI 'C'-40H JZ ABORT JMP GOON ; ; this is not the syslib routine by same name... ; CONDIN: PUSH H PUSH D PUSH B MVI C,6 MVI E,0FFH CALL BDOS ORA A POP B POP D POP H RET ; EOLN: MVI A,0FFH ;reset tab counter STA TAB MVI A,MXLPS ;get max lines per screen ORA A JZ GOON ;skip if no page mode LDA LPS DCR A STA LPS JNZ GOON CALL PRINT DB '[more]',CR,0 CALL CIN CPI 'C'-40H JZ ABORT CALL PRINT DB ' ',CR,0 MVI A,MXLPS STA LPS JMP GOON ; PROCTAB: LDA TAB ;get current tab value MOV B,A ;save current ANI 0F8H ;round down to last full 8 ADI 8 ;make next tab stop TABLP: CALL SPOUT ;put space INR B ;continue spaces to.. CMP B ;...next tab stop JNZ TABLP STA TAB ;save next tab stop JMP GO1 ; ; print a space ; SPOUT: PUSH PSW MVI A,' ' CALL CCOUT POP PSW RET ; GOON: LDA TAB ;increment... INR A STA TAB ;...tab counter GO1: INX H ;increment buffer pointer LDA TOPRAM ;get top of ram CMP H ;if not yet reached... JNZ BUFLP ;...then get next char POP PSW ;else return to caller... POP B ;...to get more POP D POP H RET ; ; read random record, save all regs ; RNDREAD: PUSH D PUSH H MVI C,33 CALL BDOS POP H POP D RET ; ; process non-lbr file NOLBF: LXI D,FCB CALL F$OPEN ;open the file JNZ NOFILE ;not found... CALL F$READ ;read first sector ORA A LXI H,0 JZ DOTYP ;type it now... CALL PRINT DB CR,LF DB 'Empty file?',CR,LF,0 JMP WHAT ; here are the messages ; ILLDU: CALL PRINT DB CR,LF DB 'Bad drive/user',CR,LF,0 JMP WHAT ; NOFILE: CALL PRINT DB CR,LF DB 'No such file',CR,LF,0 JMP EREXT ; CPFN0: DAD B ; CPFN: PUSH H PUSH D PUSH B MVI B,12 ;12 characters CLPCP: LDAX D CMP M ;check file name JNZ QCPFN ;no match - quit INX D INX H DCR B JNZ CLPCP QCPFN: POP B POP D POP H RET ; NOLBR: CALL PRINT DB CR,LF DB 'LBR directory may be damaged',CR,LF,0 JMP EREXT ; NOMEM: CALL PRINT DB CR,LF DB 'Specify member file',CR,LF,0 JMP WHAT ; NULLEN: CALL PRINT DB CR,LF DB '0k - cannot type.',CR,LF,0 JMP EREXT ; NOAMB: CALL PRINT DB CR,LF DB 'Bad filename.',CR,LF,0 ; WHAT: CALL PRINT DB ';;ERROR!',CR,LF,0 DB CR,LF,0 JMP EREXT ; ABORT: CALL PRINT DB CR,LF,'+++ABORTED+++',CR,LF,0 JMP EREXT ; FINISHED: CALL PRINT DB CR,LF,'[--End of File--] Press any key>',7,0 CALL CIN MVI A,CR CALL CO EREXT: CALL GETUD ;restore default du LXI D,80H CALL SETDMA LHLD STACK SPHL RET ; SETDMA: MVI C,1AH JMP 5 ; ;unsqueeze routine USQ: XRA A STA X0345 STA X0346 LHLD X033B SHLD X033F SHLD X0341 CALL X0267 CALL X0267 SHLD X0347 X013A: CALL X0216 JNZ EREXT ORA A JNZ X013A CALL X0267 SHLD X034B LXI D,0102H CALL CMP$HLDE JC X0180 CALL PRINT DB CR,LF,'Illegal decode size.',0 JMP WHAT ; X0180: LXI D,TABLE X0183: SHLD $X034D MOV A,H ORA L JZ X01A7 PUSH D CALL X0267 POP D XCHG MOV M,E INX H MOV M,D INX H PUSH H CALL X0267 XCHG POP H MOV M,E INX H MOV M,D INX H XCHG LHLD X034D DCX H JMP X0183 X01A7: LXI H,0 X01AA: PUSH H CALL X02A2 POP H JNZ X01D2 MOV E,A MVI D,0 DAD D PUSH H PUSH PSW LHLD X0343 LDA TOPRAM CMP H JNZ X01C8 CALL BUFULL LXI H,BUFF X01C8: POP PSW MOV M,A INX H SHLD X0343 POP H JMP X01AA X01D2: XCHG LHLD X0347 CALL CMP$HLDE RZ CALL PRINT DB CR,LF,'File checksum error',0 JMP WHAT ; CMP$HLDE: MOV A,H CMP D RNZ MOV A,L CMP E RET ; X0216: LHLD X0341 XCHG LHLD X033F CALL CMP$HLDE JZ X022A MOV A,M INX H SHLD X033F CMP A RET X022A: LHLD X033B SHLD X033F SHLD X0341 X0233: PUSH H XCHG MVI C,1AH CALL BDOS$CALL LXI D,FCB MVI C,14H CALL BDOS$CALL POP H ORA A JNZ X0256 LXI D,80H DAD D XCHG LHLD X033D CALL CMP$HLDE XCHG JNC X0233 X0256: SHLD X0341 XCHG LHLD X033F CALL CMP$HLDE JNZ X0216 MVI A,0FFH ORA A RET X0267: CALL X0216 JNZ PREM$EOF PUSH PSW CALL X0216 JNZ PREM$EOF MOV H,A POP PSW MOV L,A RET PREM$EOF: CALL PRINT DB CR,LF,'Premature EOF',0 JMP WHAT X02A2: LDA X0346 ORA A JZ X02B2 DCR A STA X0346 LDA X0349 CMP A RET X02B2: CALL X02D4 CPI 90H JNZ X02CF CALL X02D4 ORA A JNZ X02C5 MVI A,90H CMP A RET X02C5: DCR A DCR A STA X0346 LDA X0349 CMP A RET X02CF: STA X0349 CMP A RET X02D4: LXI D,0 LDA X034A MOV C,A X02DB: LDA X0345 ORA A JNZ X02ED PUSH D CALL X0216 JNZ PREM$EOF POP D MOV C,A MVI A,8 X02ED: DCR A STA X0345 MOV A,C RRC MOV C,A LXI H,TABLE JNC X02FC INX H INX H X02FC: DAD D DAD D DAD D DAD D MOV E,M INX H MOV D,M MOV A,D ANI 80H JZ X02DB MOV A,C STA X034A MOV A,D CPI 0FEH MVI A,1AH JZ X0319 MOV A,E CMA CMP A RET X0319: POP H ORA A RET ; UINIT: LXI H,DBUF SHLD X033B SHLD X033F SHLD X0341 LXI H,X0345 MVI A,9 X032D: MVI M,0 INX H DCR A JNZ X032D LXI H,BUFF SHLD X0343 RET ; FNAME: PUSH D MVI A,0FFH STA L0485 STA L0486 MVI B,'$' PUSH D XRA A L03A0: STAX D INX D DCR B JNZ L03A0 POP D PUSH H L03A8: MOV A,M INX H CPI ':' JZ L03BC CPI ',' JZ L0417 ; CPI '!' JC L0417 JMP L03A8 L03BC: POP H MOV A,M CALL MAKEUCASE CPI 'A' JC L03D5 SUI 'A' CPI 10H JC L03D0 L03CD: XRA A POP D RET L03D0: INR A STA L0485 INX H L03D5: MOV A,M CPI ':' JZ L0418 CPI '?' JNZ L03ED STA L0486 INX H MOV A,M CPI ':' JZ L0418 JMP L03CD L03ED: XRA A MOV B,A L03EF: MOV A,M INX H CPI ':' JZ L040B SUI '0' JC L03CD CPI LF JNC L03CD MOV C,A MOV A,B ADD A ADD A ADD B ADD A ADD C MOV B,A JMP L03EF L040B: MOV A,B CPI ' ' JNC L03CD STA L0486 JMP L0418 L0417: POP H L0418: MOV A,M CPI ':' JNZ L041F INX H L041F: MOV A,M CPI ',' JZ L042A CPI '!' JNC L0442 L042A: INX D MVI B,0BH MVI A,'?' L042F: STAX D INX D DCR B JNZ L042F L0435: LDA L0485 MOV B,A LDA L0486 MOV C,A POP D MVI A,0FFH ORA A RET L0442: MVI B,8 CALL L045C MVI B,3 MOV A,M CPI '.' JNZ L0456 INX H CALL L045C JMP L0435 L0456: CALL L047C JMP L0435 L045C: CALL CHAR$CHK JZ L047C INX D CPI '*' JNZ L046E MVI A,'?' STAX D JMP L0470 L046E: STAX D INX H L0470: DCR B JNZ L045C L0474: CALL CHAR$CHK RZ INX H JMP L0474 L047C: INX D MVI A,' ' STAX D DCR B JNZ L047C RET ; CHAR$CHK: MOV A,M CALL MAKEUCASE ORA A RZ CPI '!' JC L04AA CPI '=' RZ CPI '_' RZ CPI '.' RZ CPI ':' RZ CPI ';' ;3bh RZ CPI ',' RZ CPI '<' RZ CPI '>' RET L04AA: CMP M RET ; F$OPEN: ; open file: PUSH B PUSH D PUSH H MVI C,0FH CALL BDOS CPI 0FFH JNZ L04BF L04B9: MVI A,0FFH ORA A JMP L04C0 L04BF: XRA A L04C0: POP H POP D POP B RET ; F$READ: ; file read: PUSH H PUSH B MVI C,14H CALL BDOS$CALL ORA A POP B POP H RET ; PRINT: ;in line print routine XTHL CALL PRINT1 XTHL RET PRINT1: PUSH D PUSH B PUSH PSW MVI C,0 PRINT$LP: MOV A,M INX H ORA A JZ L0543 CPI 9 JZ L052D INR C CALL CCOUT CPI CR JZ L051A CPI LF JZ L051F CPI 7 JZ L051F CPI 8 JZ L0523 JMP PRINT$LP L051A: MVI C,0 JMP PRINT$LP L051F: DCR C JMP PRINT$LP L0523: MOV A,C ORA A JZ PRINT$LP DCR C DCR C JMP PRINT$LP L052D: MOV A,C ANI 7 MOV B,A MVI A,8 SUB B MOV B,A ADD C MOV C,A MVI A,' ' L0539: CALL CO DCR B JNZ L0539 JMP PRINT$LP L0543: POP PSW POP B POP D RET ; CCOUT: ; character out (convert ctl chars): CPI ' ' JNC CO CPI 0 JZ CO CPI 7 JZ CO CPI 8 JZ CO CPI LF JZ CO CPI CR JZ CO PUSH PSW PUSH PSW MVI A,'^' CALL CO POP PSW ADI '@' CALL CO POP PSW RET ; CIN: ; character in: PUSH B PUSH H MVI C,1% CALL BDOS$CALL POP H POP B RET ; CO: PUSH PSW PUSH B PUSH D PUSH H MOV E,A MVI C,2 CALL BDOS POP H POP D POP B POP PSW RET ; PUTUD: ; save current du: PUSH PSW PUSH B PUSH D PUSH H MVI C,19H CALL BDOS STA CURNTDSK MVI E,0FFH MVI C,' ' CALL BDOS STA CURNTUSR JMP L05C8 ; GETUD: ; restore default du: PUSH PSW PUSH B PUSH D PUSH H LDA CURNTDSK MOV E,A MVI C,0EH CALL BDOS LDA CURNTUSR MOV E,A MVI C,' ' CALL BDOS L05C8: POP H POP D POP B POP PSW RET ; LOGUD: PUSH PSW PUSH B PUSH D PUSH H MOV E,C MVI C,' ' PUSH B CALL BDOS POP B MOV E,B MVI C,0EH CALL BDOS POP H POP D POP B POP PSW RET RETUD: PUSH PSW PUSH D PUSH H MVI C,19H CALL BDOS PUSH PSW MVI E,0FFH MVI C,' ' CALL BDOS MOV C,A POP PSW MOV B,A POP H POP D POP PSW RET ; BDOS$CALL: ; bdos call: PUSH B PUSH D CALL BDOS POP D POP B RET ; DIVHD: PUSH PSW PUSH B PUSH H LXI H,0 SHLD L0662 POP H MOV A,H CMP D JC L0647 JNZ L061C MOV A,L CMP E JC L0647 L061C: MVI B,10H L061E: CALL L064D PUSH H LHLD L0662 CALL L065E SHLD L0662 MOV A,L SUB E MOV L,A MOV A,H SBB D MOV H,A JC L063F SHLD L0662 POP H MOV A,L ORI 1 MOV L,A JMP L0640 L063F: POP H L0640: DCR B JNZ L061E L0644: POP B POP PSW RET L0647: LXI H,0 JMP L0644 L064D: PUSH PSW ANA A L064F: MOV A,L RAL MOV L,A MOV A,H RAL MOV H,A JNC L065B POP PSW STC RET L065B: POP PSW ORA A RET L065E: PUSH PSW JMP L064F ; MAKEUCASE: ANI 7FH CPI 61H RC CPI 7BH RNC ANI '_' RET ; ;storage for unsqueeze routines CURNTDSK: DB 0 CURNTUSR: DB 0 ; L0485: DB 0 L0486: DB 0 L0662: DW 0 ;divide storage X033B: DW 0 X033D: DW 0 X033F: DW 0 X0341: DW 0 X0343: DW 0 X0345: DB 0 X0346: DB 0 X0347: DW 0 X0349: DB 7EH X034A: DB 0FEH X034B: DW 0 X034D: DW 0 ; FFLAG: DB 0 ;flag for lbr/non-lbr TOPRAM: DB 0 ;hi byte of buffer end DIRS: DB 0 ;# of dir sectors processed DIRSIZ: DB 0 ;# of total dir sectors TAB: DB 0 ;current line tab LIN: DB 0 ;line count LPS: DB 0 ;line count for page mode USERNO: DB 0 ;current user # DRIVENO:DB 0 ;current drive DIRNAME:DB 0,' ' STRING: DW 0 STORDMA:DW 0 ; DS 50 ;25 level stack STACK: DW 0 ;save cp/m stack pointer here ; MEMFCB EQU $ FCB EQU MEMFCB+37 DFCB EQU FCB+37 DBUF EQU DFCB+37 TABLE EQU DBUF+129 BUFF EQU ((TABLE + 1034) OR 0FFH) + 1 ;set on page boundry ; END 7 DFCB EQU FCB+37 DBUF EQU DFCB+37 TABLE EQU DBUF+129 BUFF EQU ((TABLE + 1034) OR 0FFH) + 1 ;set on pa 7BH RNC ANI '_' RET ; ;storage for unsqueeze routines CURNTDSK: DB 0 CURNTUSR: DB 0 ; L0485: DB 0 L0486: DB 0 L0662: DW 0 ;divide storage X033B: DW 0 X033D: DW 0 X033F: DW 0 X0341: DW 0 X0343: DW 0 X0345: DB 0 X0346: DB 0 X0347: DW 0 X0349: DB 7EH X034A: DB 0FEH X034B: DW 0 X034D: DW 0 ; FFLAG: DB 0 ;flag for lbr/non-lbr TOPRAM: DB 0 ;hi byte of  This is the release date of the disk. !&*+,13456789:;<=>?@ABCDEFGHIJKLMNOPQRTZ[\]^_`fgpqrvwxz{|}~NEWBAS11.ASM 28 FA 20096 157 VDBTYPE .ASM 77 87 20096 157  Fog Library Disk FOG-CPM.006 Copyright (1985) by Fog International Computer Users Group to the extent not copyrighted by the original author for the exclusive use and enjoyment of its members. Any reproduction or distribution for profit or personal gain is strictly forbidden. For information, contact FOG, P. O. Box 3474, Daly City, CA. 94015-0474. as part of the description of a file indicates that the program is distributed on a "try first, pay if you like it" basis. If you find the program(s) meet your need, please refer to the author's documentation for information on becoming a registered user. Only by registering and paying for the programs you like and use will the authors of such programs continue development. Often, more complete documentation, additional modules, and new releases are available only to registered users. A collection of dBASE programs and hints. Most of these were written specifically for dBASE II but some are also fo&r dBASE III or can be converted to dBASE III (using dCONVERT). Filename Description -10-00 .85 This is the release date of the disk. -CPM006 .DOC This is the description of the disk contents. CALC .CMD 53E3 5K Add a calculator to your dBASE programs. Written for Televideo arrow keys, modify for other computers. DB2BAKUP.CMD E9D9 2K A dBASE utility to backup up your files quickly. MATHLIB .CMD FBB5 14K Add mathematical functions to your dBASE programs. DB2&3MAX.INF 5D79 32K Information on how to maximize your dBASE code. DBPRETTY.COM 5110 29K [dBASE Pretty 1 of 2] Fix the indents and otherwise clean up dBASE program code so that it is easier to read and to locate errors in the code. DBPRETTY.DOC 44FD 3K [dBASE Pretty 2 of 2] ENCODE .COM 28AC 23K ver. 1.05 [Encode dBASE 1 of 2] A pseudo-compiler for dBASE II to shrink and tokenize .CMD source code. Two files (MBasic sou This is the release date of the disk. VDBTYPE ASM NDBTYPE ASM   FOG LIBRARY DISK FOG-CPM.006 Copyright (1987) by FOG (First Osborne Group) to the extent not copyrighted by the original author for the exclusive use and enjoyment of its members. Any reproduction or distribution for profit or personal gain is strictly forbidden. For information, contact FOG, P. O. Box 3474, Daly City, CA. 94015-0474. as part of the description of a file indicates that the program is distributed on a "try first, pay if you like it" basis. Irce and help file) are missing. They will be added to this disk if located. ENCODE .DOC 8C56 13K ver. 1.05 [Encode dBASE 2 of 2] LOAD-HEX.DOC 1474 9K Discussion and instructions for using .HEX files from a dBASE program. NEWBAS11.ASM 28FA 20K ver. 1.0 A custom patcher for all versions of dBASE II. Allows you to easily control some of the dBASE options so that a user can not override you or so that dBASE is faster. VDBTYPE .ASM 7787 20K Add CP/M TYPE command to your dBASE programs and be able to read normal and squeezed files.  STOR diskf-fn-"."-ft TO malt STOR SUBST(ft,1,2) TO mdate SET ALTE TO &malt SET ALTE ON ? filedesc SET ALTE OFF SET ALTE TO SELE A STOR diskf-"-"-SUBST(dfile,5,3)-"&mdiskno"-".DOC" TO malt SET ALTE TO &malt SET ALTE ON DO WHILE diskno="&mdiskno".AND. .NOT. EOF() IF diskno="000" IF dfile="FOG-DOS" ? " '