- ' 
- '   Microsoft RemLine - Line Number Removal Utility 
- '   Copyright (C) Microsoft Corporation 1985-1990 
- ' 
- '   REMLINE.BAS is a program to remove line numbers from Microsoft Basic 
- '   Programs. It removes only those line numbers that are not the object 
- '   of one of the following statements: GOSUB, RETURN, GOTO, THEN, ELSE, 
- '   RESUME, RESTORE, or RUN. 
- ' 
- '   When REMLINE is run, it will ask for the name of the file to be 
- '   processed and the name of the file or device to receive the 
- '   reformatted output. If no extension is given, .BAS is assumed (except 
- '   for output devices). If filenames are not given, REMLINE prompts for 
- '   file names. If both filenames are the same, REMLINE saves the original 
- '   file with the extension .BAK. 
- ' 
- '   REMLINE makes several assumptions about the program: 
- ' 
- '     1. It must be correct syntactically, and must run in BASICA or 
- '        GW-BASIC interpreter. 
- '     2. There is a 400 line limit. To process larger files, change 
- '        MaxLines constant. 
- '     3. The first number encountered on a line is considered a line 
- '        number; thus some continuation lines (in a compiler-specific 
- '        construction) may not be handled correctly. 
- '     4. REMLINE can handle simple statements that test the ERL function 
- '        using  relational operators such as =, <, and >. For example, 
- '        the following statement is handled correctly: 
- ' 
- '             IF ERL = 100 THEN END 
- ' 
- '        Line 100 is not removed from the source code. However, more 
- '        complex expressions that contain the +, -, AND, OR, XOR, EQV, 
- '        MOD, or IMP operators may not be handled correctly. For example, 
- '        in the following statement REMLINE does not recognize line 105 
- '        as a referenced line number and removes it from the source code: 
- ' 
- '             IF ERL + 5 = 105 THEN END 
- ' 
- '   If you do not like the way REMLINE formats its output, you can modify 
- '   the output lines in SUB GenOutFile. An example is shown in comments. 
-   
-   
-   
- REM ***-  NOTE: I like Veranda ,-  but you can remove it  or-  replace it with your favorite font. 
 
- fontpath$ = "Veranda.tff" 
-   
-   
- ' Function and Subprocedure declarations 
-   
- ' Global and constant data 
-   
- DIM SHARED-  Seps$ ,-  InputFile$ ,-  OutputFile$ ,-  TmpFile$ 
 
-   
- ' Keyword search data 
-   
- KeyData: 
-   
- ' Start of module-level program code 
- Seps$  = " ,:=<>()" + CHR$(9)
- InitKeyTable 
- GetFileNames 
- BuildTable 
- GenOutFile 
-   
-   
- FileErr1: 
- INPUT "      New input file name (ENTER to terminate): ",-  InputFile$ 
 
- FileErr2: 
- INPUT "      Output file name (ENTER to print to screen) :",-  OutputFile$ 
 
- IF (- OutputFile$  = "") THEN-  OutputFile$  = "CON"
 
-     TmpFile$ = "" 
-   
- ' 
- ' BuildTable: 
- '   Examines the entire text file looking for line numbers that are 
- '   the object of GOTO, GOSUB, etc. As each is found, it is entered 
- '   into a table of line numbers. The table is used during a second 
- '   pass (see GenOutFile), when all line numbers not in the list 
- '   are removed. 
- ' Input: 
- '   Uses globals KeyWordTable$, KeyWordCount, and Seps$ 
- ' Output: 
- '   Modifies LineTable! and LineCount 
- ' 
-   
-         ' Get line and first token 
-         Token$ = GetToken$(InLin$, Seps$) 
-             FOR-  KeyIndex  = 1 TO-  KeyWordCount 
 
-                 ' See if token is keyword 
-                     ' Get possible line number after keyword 
-                     Token$ = GetToken$("", Seps$) 
-                     ' Check each token to see if it is a line number 
-                     ' (the LOOP is necessary for the multiple numbers 
-                     ' of ON GOSUB or ON GOTO). A non-numeric token will 
-                     ' terminate search. 
-                         LineCount = LineCount + 1 
-                         LineTable! (- LineCount ) = VAL(- Token$ )
-                         Token$ = GetToken$("", Seps$) 
-                         IF-  Token$  <> "" THEN-  KeyIndex  = 0
 
-             ' Get next token 
-             Token$ = GetToken$("", Seps$) 
-   
-   
- ' 
- ' GenOutFile: 
- '  Generates an output file with unreferenced line numbers removed. 
- ' Input: 
- '  Uses globals LineTable!, LineCount, and Seps$ 
- ' Output: 
- '  Processed file 
- ' 
-   
-     ' Speed up by eliminating comma and colon (can't separate first token) 
-             ' Get first token and process if it is a line number 
-             Token$ = GetToken$(InLin$, Sep$) 
-                 LineNumber!  = VAL(- Token$ )
-                 FoundNumber = false 
-                 ' See if line number is in table of referenced line numbers 
-                 FOR-  index  = 1 TO-  LineCount 
 
-                     IF (- LineNumber!  =-  LineTable! (- index )) THEN
 
-                         FoundNumber = TRUE 
-                 ' Modify line strings 
-                     MID$(- InLin$ ,-  StrSpn (- InLin$ ,-  Sep$ ), LEN(- Token$ )) =-  Token$ 
 
-   
-                 ' You can replace the previous lines with your own 
-                 ' code to reformat output. For example, try these lines: 
-   
-                 'TmpPos1 = StrSpn(InLin$, Sep$) + LEN(Token$) 
-                 'TmpPos2 = TmpPos1 + StrSpn(MID$(InLin$, TmpPos1), Sep$) 
-                 ' 
-                 'IF FoundNumber THEN 
-                 '   InLin$ = LEFT$(InLin$, TmpPos1 - 1) + CHR$(9) + MID$(InLin$, TmpPos2) 
-                 'ELSE 
-                 '   InLin$ = CHR$(9) + MID$(InLin$, TmpPos2) 
-                 'END IF 
-   
-         ' Print line to file or console (PRINT is faster than console device) 
-   
-   
- ' 
- ' GetFileNames: 
- '  Gets a file name by prompting the user. 
- ' Input: 
- '  User input 
- ' Output: 
- '  Defines InputFiles$ and OutputFiles$ 
- ' 
-   
-     PRINT " Microsoft RemLine: Line Number Removal Utility" 
-     PRINT "       (.BAS assumed if no extension given)" 
-     INPUT "      Input file name (ENTER to terminate): ",-  InputFile$ 
 
-     INPUT "      Output file name (ENTER to print to screen): ",-  OutputFile$ 
 
-     IF (- OutputFile$  = "") THEN-  OutputFile$  = "CON"
 
-   
-         InputFile$ = InputFile$ + ".BAS" 
-   
-             CASE "CON", "SCRN", "PRN", "COM1", "COM2", "LPT1", "LPT2", "LPT3" 
-                 OutputFile$ = OutputFile$ + ".BAS" 
-   
-         TmpFile$  = LEFT$(- InputFile$ , INSTR(- InputFile$ , ".")) + "BAK"
-         IF-  TmpFile$  <> "" THEN-  InputFile$  =-  TmpFile$ 
 
-   
-   
- ' 
- ' GetToken$: 
- '  Extracts tokens from a string. A token is a word that is surrounded 
- '  by separators, such as spaces or commas. Tokens are extracted and 
- '  analyzed when parsing sentences or commands. To use the GetToken$ 
- '  function, pass the string to be parsed on the first call, then pass 
- '  a null string on subsequent calls until the function returns a null 
- '  to indicate that the entire string has been parsed. 
- ' Input: 
- '  Search$ = string to search 
- '  Delim$  = String of separators 
- ' Output: 
- '  GetToken$ = next token 
- ' 
-   
-     ' Note that SaveStr$ and BegPos must be static from call to call 
-     ' (other variables are only static for efficiency). 
-     ' If first call, make a copy of the string 
-         BegPos = 1 
-         SaveStr$ = Search$ 
-   
-     ' Find the start of the next token 
-     NewPos  =-  StrSpn (MID$(- SaveStr$ ,-  BegPos , LEN(- SaveStr$ )),-  Delim$ )
-         ' Set position to start of token 
-         BegPos = NewPos + BegPos - 1 
-         ' If no new token, quit and return null 
-         GetToken$ = "" 
-   
-     ' Find end of token 
-     NewPos  =-  StrBrk (MID$(- SaveStr$ ,-  BegPos , LEN(- SaveStr$ )),-  Delim$ )
-         ' Set position to end of token 
-         NewPos = BegPos + NewPos - 1 
-         ' If no end of token, return set to end a value 
-         NewPos  = LEN(- SaveStr$ ) + 1
-     ' Cut token out of search string 
-     GetToken$  = MID$(- SaveStr$ ,-  BegPos ,-  NewPos  --  BegPos )
-     ' Set new starting position 
-     BegPos = NewPos 
-   
-   
- ' 
- ' InitKeyTable: 
- '  Initializes a keyword table. Keywords must be recognized so that 
- '  line numbers can be distinguished from numeric constants. 
- ' Input: 
- '  Uses KeyData 
- ' Output: 
- '  Modifies global array KeyWordTable$ 
- ' 
-   
-     FOR-  Count  = 1 TO-  KeyWordCount 
 
-         KeyWordTable$(Count) = KeyWord$ 
-   
-   
- ' 
- ' IsDigit: 
- '  Returns true if character passed is a decimal digit. Since any 
- '  Basic token starting with a digit is a number, the function only 
- '  needs to check the first digit. Doesn't check for negative numbers, 
- '  but that's not needed here. 
- ' Input: 
- '  Char$ - initial character of string to check 
- ' Output: 
- '  IsDigit - true if within 0 - 9 
- ' 
-   
-         IsDigit = false 
-         IsDigit  = (- CharAsc  >= ASC("0")) AND (- CharAsc  <= ASC("9"))
-   
-   
- ' 
- ' StrBrk: 
- '  Searches InString$ to find the first character from among those in 
- '  Separator$. Returns the index of that character. This function can 
- '  be used to find the end of a token. 
- ' Input: 
- '  InString$ = string to search 
- '  Separator$ = characters to search for 
- ' Output: 
- '  StrBrk = index to first match in InString$ or 0 if none match 
- ' 
-   
-     BegPos = 1 
-     ' Look for end of token (first character that is a delimiter). 
-             StrBrk = 0 
-             BegPos = BegPos + 1 
-     StrBrk = BegPos 
-   
-   
- ' 
- ' StrSpn: 
- '  Searches InString$ to find the first character that is not one of 
- '  those in Separator$. Returns the index of that character. This 
- '  function can be used to find the start of a token. 
- ' Input: 
- '  InString$ = string to search 
- '  Separator$ = characters to search for 
- ' Output: 
- '  StrSpn = index to first nonmatch in InString$ or 0 if all match 
- ' 
-   
-     BegPos = 1 
-     ' Look for start of a token (character that isn't a delimiter). 
-             StrSpn = 0 
-             BegPos = BegPos + 1 
-     StrSpn = BegPos 
-   
-