Exclusive mode seems to work without deadlocks
[mirrors/Programs.git] / turbobasic / 1998 / 3RD-PA.RTY / REMLINE.BAS
... / ...
CommitLineData
1'\r
2' Microsoft RemLine - Line Number Removal Utility\r
3' Copyright (C) Microsoft Corporation 1985-1990\r
4'\r
5' REMLINE.BAS is a program to remove line numbers from Microsoft Basic\r
6' Programs. It removes only those line numbers that are not the object\r
7' of one of the following statements: GOSUB, RETURN, GOTO, THEN, ELSE,\r
8' RESUME, RESTORE, or RUN.\r
9'\r
10' When REMLINE is run, it will ask for the name of the file to be\r
11' processed and the name of the file or device to receive the\r
12' reformatted output. If no extension is given, .BAS is assumed (except\r
13' for output devices). If filenames are not given, REMLINE prompts for\r
14' file names. If both filenames are the same, REMLINE saves the original\r
15' file with the extension .BAK.\r
16'\r
17' REMLINE makes several assumptions about the program:\r
18'\r
19' 1. It must be correct syntactically, and must run in BASICA or\r
20' GW-BASIC interpreter.\r
21' 2. There is a 400 line limit. To process larger files, change\r
22' MaxLines constant.\r
23' 3. The first number encountered on a line is considered a line\r
24' number; thus some continuation lines (in a compiler-specific\r
25' construction) may not be handled correctly.\r
26' 4. REMLINE can handle simple statements that test the ERL function\r
27' using relational operators such as =, <, and >. For example,\r
28' the following statement is handled correctly:\r
29'\r
30' IF ERL = 100 THEN END\r
31'\r
32' Line 100 is not removed from the source code. However, more\r
33' complex expressions that contain the +, -, AND, OR, XOR, EQV,\r
34' MOD, or IMP operators may not be handled correctly. For example,\r
35' in the following statement REMLINE does not recognize line 105\r
36' as a referenced line number and removes it from the source code:\r
37'\r
38' IF ERL + 5 = 105 THEN END\r
39'\r
40' If you do not like the way REMLINE formats its output, you can modify\r
41' the output lines in SUB GenOutFile. An example is shown in comments.\r
42DEFINT A-Z\r
43\r
44' Function and Subprocedure declarations\r
45DECLARE FUNCTION GetToken$ (Search$, Delim$)\r
46DECLARE FUNCTION StrSpn% (InString$, Separator$)\r
47DECLARE FUNCTION StrBrk% (InString$, Separator$)\r
48DECLARE FUNCTION IsDigit% (Char$)\r
49DECLARE SUB GetFileNames ()\r
50DECLARE SUB BuildTable ()\r
51DECLARE SUB GenOutFile ()\r
52DECLARE SUB InitKeyTable ()\r
53\r
54' Global and constant data\r
55CONST TRUE = -1\r
56CONST false = 0\r
57CONST MaxLines = 400\r
58\r
59DIM SHARED LineTable!(MaxLines)\r
60DIM SHARED LineCount\r
61DIM SHARED Seps$, InputFile$, OutputFile$, TmpFile$\r
62\r
63' Keyword search data\r
64CONST KeyWordCount = 9\r
65DIM SHARED KeyWordTable$(KeyWordCount)\r
66\r
67KeyData:\r
68 DATA THEN, ELSE, GOSUB, GOTO, RESUME, RETURN, RESTORE, RUN, ERL, ""\r
69\r
70' Start of module-level program code\r
71 Seps$ = " ,:=<>()" + CHR$(9)\r
72 InitKeyTable\r
73 GetFileNames\r
74 ON ERROR GOTO FileErr1\r
75 OPEN InputFile$ FOR INPUT AS 1\r
76 ON ERROR GOTO 0\r
77 COLOR 7: PRINT "Working"; : COLOR 23: PRINT " . . .": COLOR 7: PRINT\r
78 BuildTable\r
79 CLOSE #1\r
80 OPEN InputFile$ FOR INPUT AS 1\r
81 ON ERROR GOTO FileErr2\r
82 OPEN OutputFile$ FOR OUTPUT AS 2\r
83 ON ERROR GOTO 0\r
84 GenOutFile\r
85 CLOSE #1, #2\r
86 IF OutputFile$ <> "CON" THEN CLS\r
87\r
88END\r
89\r
90FileErr1:\r
91 CLS\r
92 PRINT " Invalid file name": PRINT\r
93 INPUT " New input file name (ENTER to terminate): ", InputFile$\r
94 IF InputFile$ = "" THEN END\r
95FileErr2:\r
96 INPUT " Output file name (ENTER to print to screen) :", OutputFile$\r
97 PRINT\r
98 IF (OutputFile$ = "") THEN OutputFile$ = "CON"\r
99 IF TmpFile$ = "" THEN\r
100 RESUME\r
101 ELSE\r
102 TmpFile$ = ""\r
103 RESUME NEXT\r
104 END IF\r
105\r
106'\r
107' BuildTable:\r
108' Examines the entire text file looking for line numbers that are\r
109' the object of GOTO, GOSUB, etc. As each is found, it is entered\r
110' into a table of line numbers. The table is used during a second\r
111' pass (see GenOutFile), when all line numbers not in the list\r
112' are removed.\r
113' Input:\r
114' Uses globals KeyWordTable$, KeyWordCount, and Seps$\r
115' Output:\r
116' Modifies LineTable! and LineCount\r
117'\r
118SUB BuildTable STATIC\r
119\r
120 DO WHILE NOT EOF(1)\r
121 ' Get line and first token\r
122 LINE INPUT #1, InLin$\r
123 Token$ = GetToken$(InLin$, Seps$)\r
124 DO WHILE (Token$ <> "")\r
125 FOR KeyIndex = 1 TO KeyWordCount\r
126 ' See if token is keyword\r
127 IF (KeyWordTable$(KeyIndex) = UCASE$(Token$)) THEN\r
128 ' Get possible line number after keyword\r
129 Token$ = GetToken$("", Seps$)\r
130 ' Check each token to see if it is a line number\r
131 ' (the LOOP is necessary for the multiple numbers\r
132 ' of ON GOSUB or ON GOTO). A non-numeric token will\r
133 ' terminate search.\r
134 DO WHILE (IsDigit(LEFT$(Token$, 1)))\r
135 LineCount = LineCount + 1\r
136 LineTable!(LineCount) = VAL(Token$)\r
137 Token$ = GetToken$("", Seps$)\r
138 IF Token$ <> "" THEN KeyIndex = 0\r
139 LOOP\r
140 END IF\r
141 NEXT KeyIndex\r
142 ' Get next token\r
143 Token$ = GetToken$("", Seps$)\r
144 LOOP\r
145 LOOP\r
146\r
147END SUB\r
148\r
149'\r
150' GenOutFile:\r
151' Generates an output file with unreferenced line numbers removed.\r
152' Input:\r
153' Uses globals LineTable!, LineCount, and Seps$\r
154' Output:\r
155' Processed file\r
156'\r
157SUB GenOutFile STATIC\r
158\r
159 ' Speed up by eliminating comma and colon (can't separate first token)\r
160 Sep$ = " " + CHR$(9)\r
161 DO WHILE NOT EOF(1)\r
162 LINE INPUT #1, InLin$\r
163 IF (InLin$ <> "") THEN\r
164 ' Get first token and process if it is a line number\r
165 Token$ = GetToken$(InLin$, Sep$)\r
166 IF IsDigit(LEFT$(Token$, 1)) THEN\r
167 LineNumber! = VAL(Token$)\r
168 FoundNumber = false\r
169 ' See if line number is in table of referenced line numbers\r
170 FOR index = 1 TO LineCount\r
171 IF (LineNumber! = LineTable!(index)) THEN\r
172 FoundNumber = TRUE\r
173 END IF\r
174 NEXT index\r
175 ' Modify line strings\r
176 IF (NOT FoundNumber) THEN\r
177 Token$ = SPACE$(LEN(Token$))\r
178 MID$(InLin$, StrSpn(InLin$, Sep$), LEN(Token$)) = Token$\r
179 END IF\r
180 \r
181 ' You can replace the previous lines with your own\r
182 ' code to reformat output. For example, try these lines:\r
183 \r
184 'TmpPos1 = StrSpn(InLin$, Sep$) + LEN(Token$)\r
185 'TmpPos2 = TmpPos1 + StrSpn(MID$(InLin$, TmpPos1), Sep$)\r
186 '\r
187 'IF FoundNumber THEN\r
188 ' InLin$ = LEFT$(InLin$, TmpPos1 - 1) + CHR$(9) + MID$(InLin$, TmpPos2)\r
189 'ELSE\r
190 ' InLin$ = CHR$(9) + MID$(InLin$, TmpPos2)\r
191 'END IF\r
192\r
193 END IF\r
194 END IF\r
195 ' Print line to file or console (PRINT is faster than console device)\r
196 IF OutputFile$ = "CON" THEN\r
197 PRINT InLin$\r
198 ELSE\r
199 PRINT #2, InLin$\r
200 END IF\r
201 LOOP\r
202\r
203END SUB\r
204\r
205'\r
206' GetFileNames:\r
207' Gets a file name by prompting the user.\r
208' Input:\r
209' User input\r
210' Output:\r
211' Defines InputFiles$ and OutputFiles$\r
212'\r
213SUB GetFileNames STATIC\r
214\r
215 CLS\r
216 PRINT " Microsoft RemLine: Line Number Removal Utility"\r
217 PRINT " (.BAS assumed if no extension given)"\r
218 PRINT\r
219 INPUT " Input file name (ENTER to terminate): ", InputFile$\r
220 IF InputFile$ = "" THEN END\r
221 INPUT " Output file name (ENTER to print to screen): ", OutputFile$\r
222 PRINT\r
223 IF (OutputFile$ = "") THEN OutputFile$ = "CON"\r
224\r
225 IF INSTR(InputFile$, ".") = 0 THEN\r
226 InputFile$ = InputFile$ + ".BAS"\r
227 END IF\r
228\r
229 IF INSTR(OutputFile$, ".") = 0 THEN\r
230 SELECT CASE OutputFile$\r
231 CASE "CON", "SCRN", "PRN", "COM1", "COM2", "LPT1", "LPT2", "LPT3"\r
232 EXIT SUB\r
233 CASE ELSE\r
234 OutputFile$ = OutputFile$ + ".BAS"\r
235 END SELECT\r
236 END IF\r
237\r
238 DO WHILE InputFile$ = OutputFile$\r
239 TmpFile$ = LEFT$(InputFile$, INSTR(InputFile$, ".")) + "BAK"\r
240 ON ERROR GOTO FileErr1\r
241 NAME InputFile$ AS TmpFile$\r
242 ON ERROR GOTO 0\r
243 IF TmpFile$ <> "" THEN InputFile$ = TmpFile$\r
244 LOOP\r
245\r
246END SUB\r
247\r
248'\r
249' GetToken$:\r
250' Extracts tokens from a string. A token is a word that is surrounded\r
251' by separators, such as spaces or commas. Tokens are extracted and\r
252' analyzed when parsing sentences or commands. To use the GetToken$\r
253' function, pass the string to be parsed on the first call, then pass\r
254' a null string on subsequent calls until the function returns a null\r
255' to indicate that the entire string has been parsed.\r
256' Input:\r
257' Search$ = string to search\r
258' Delim$ = String of separators\r
259' Output:\r
260' GetToken$ = next token\r
261'\r
262FUNCTION GetToken$ (Search$, Delim$) STATIC\r
263\r
264 ' Note that SaveStr$ and BegPos must be static from call to call\r
265 ' (other variables are only static for efficiency).\r
266 ' If first call, make a copy of the string\r
267 IF (Search$ <> "") THEN\r
268 BegPos = 1\r
269 SaveStr$ = Search$\r
270 END IF\r
271 \r
272 ' Find the start of the next token\r
273 NewPos = StrSpn(MID$(SaveStr$, BegPos, LEN(SaveStr$)), Delim$)\r
274 IF NewPos THEN\r
275 ' Set position to start of token\r
276 BegPos = NewPos + BegPos - 1\r
277 ELSE\r
278 ' If no new token, quit and return null\r
279 GetToken$ = ""\r
280 EXIT FUNCTION\r
281 END IF\r
282\r
283 ' Find end of token\r
284 NewPos = StrBrk(MID$(SaveStr$, BegPos, LEN(SaveStr$)), Delim$)\r
285 IF NewPos THEN\r
286 ' Set position to end of token\r
287 NewPos = BegPos + NewPos - 1\r
288 ELSE\r
289 ' If no end of token, return set to end a value\r
290 NewPos = LEN(SaveStr$) + 1\r
291 END IF\r
292 ' Cut token out of search string\r
293 GetToken$ = MID$(SaveStr$, BegPos, NewPos - BegPos)\r
294 ' Set new starting position\r
295 BegPos = NewPos\r
296\r
297END FUNCTION\r
298\r
299'\r
300' InitKeyTable:\r
301' Initializes a keyword table. Keywords must be recognized so that\r
302' line numbers can be distinguished from numeric constants.\r
303' Input:\r
304' Uses KeyData\r
305' Output:\r
306' Modifies global array KeyWordTable$\r
307'\r
308SUB InitKeyTable STATIC\r
309\r
310 RESTORE KeyData\r
311 FOR Count = 1 TO KeyWordCount\r
312 READ KeyWord$\r
313 KeyWordTable$(Count) = KeyWord$\r
314 NEXT\r
315\r
316END SUB\r
317\r
318'\r
319' IsDigit:\r
320' Returns true if character passed is a decimal digit. Since any\r
321' Basic token starting with a digit is a number, the function only\r
322' needs to check the first digit. Doesn't check for negative numbers,\r
323' but that's not needed here.\r
324' Input:\r
325' Char$ - initial character of string to check\r
326' Output:\r
327' IsDigit - true if within 0 - 9\r
328'\r
329FUNCTION IsDigit (Char$) STATIC\r
330\r
331 IF (Char$ = "") THEN\r
332 IsDigit = false\r
333 ELSE\r
334 CharAsc = ASC(Char$)\r
335 IsDigit = (CharAsc >= ASC("0")) AND (CharAsc <= ASC("9"))\r
336 END IF\r
337\r
338END FUNCTION\r
339\r
340'\r
341' StrBrk:\r
342' Searches InString$ to find the first character from among those in\r
343' Separator$. Returns the index of that character. This function can\r
344' be used to find the end of a token.\r
345' Input:\r
346' InString$ = string to search\r
347' Separator$ = characters to search for\r
348' Output:\r
349' StrBrk = index to first match in InString$ or 0 if none match\r
350'\r
351FUNCTION StrBrk (InString$, Separator$) STATIC\r
352\r
353 Ln = LEN(InString$)\r
354 BegPos = 1\r
355 ' Look for end of token (first character that is a delimiter).\r
356 DO WHILE INSTR(Separator$, MID$(InString$, BegPos, 1)) = 0\r
357 IF BegPos > Ln THEN\r
358 StrBrk = 0\r
359 EXIT FUNCTION\r
360 ELSE\r
361 BegPos = BegPos + 1\r
362 END IF\r
363 LOOP\r
364 StrBrk = BegPos\r
365 \r
366END FUNCTION\r
367\r
368'\r
369' StrSpn:\r
370' Searches InString$ to find the first character that is not one of\r
371' those in Separator$. Returns the index of that character. This\r
372' function can be used to find the start of a token.\r
373' Input:\r
374' InString$ = string to search\r
375' Separator$ = characters to search for\r
376' Output:\r
377' StrSpn = index to first nonmatch in InString$ or 0 if all match\r
378'\r
379FUNCTION StrSpn% (InString$, Separator$) STATIC\r
380\r
381 Ln = LEN(InString$)\r
382 BegPos = 1\r
383 ' Look for start of a token (character that isn't a delimiter).\r
384 DO WHILE INSTR(Separator$, MID$(InString$, BegPos, 1))\r
385 IF BegPos > Ln THEN\r
386 StrSpn = 0\r
387 EXIT FUNCTION\r
388 ELSE\r
389 BegPos = BegPos + 1\r
390 END IF\r
391 LOOP\r
392 StrSpn = BegPos\r
393\r
394END FUNCTION\r
395\r
This page took 0.260129 seconds and 4 git commands to generate.