Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

395 lines
12 KiB

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