'=========================================================================== ' Subject: OPTIMIZED COLORED SOURCE LISTER Date: 02-23-98 (15:08) ' Author: Jonathan L. Leger Code: QB, QBasic, PDS ' Origin: leger@earthlink.net Packet: TEXT.ABC '=========================================================================== DEFINT A-Z '---------------------------------------------------------------------------- ' Colored Source Lister v1.0 (c) Sami Ky”stil„ 1997 ' Optomized by Jonathan Leger '---------------------------------------------------------------------------- ' Here's a program that parses a QBasic source code file for statements, ' strings, numbers, etc. and then displays them in color. It's still a ' little slow, but it seems to work fine. Pass a line of source to ' FUNCTION Parseline, and it'll return a color-coded version of it. ' Then you can display the returned string with SUB ColPrint, or maybe ' store it into a second file for later use. '---------------------------------------------------------------------------- ' This version scans the files for the following keywords: ' ' + QBasic statements - 268 of 'em, check the DATA lines below ' + Comments ' + Numbers - 1-9, and also HEX numbers, ie &H60 ' + Strings ' + Mathematical operators - (+,-,/,\,<,>,^,*,=) '---------------------------------------------------------------------------- ' You may use this program freely, as long as you give me some credit too. '---------------------------------------------------------------------------- '************************************************* '*** Optomization Notes *** by Jonathan Leger *** '********************************************************************* '*** First of all, let me say that I think Sami wrote an execllent *** '*** program. I really like the way he handled some of the many *** '*** difficulties this kind of program requires tackeling. But in *** '*** order to speed it up, first of all I simply made all of the *** '*** variables default to integers--that in itself gave quite a *** '*** boost to the program. I re-wrote the ColPrint() sub, which *** '*** gave a _small_ increase in speed, but the major speed boost *** '*** comes from the coloring of statements. All of the coloring *** '*** for math, numbers and comments are Sami's original code, but *** '*** I completely rewrote the coloring for statements. Sami's *** '*** original code was checking each line, character by character, *** '*** for all 286 statements, which (although it worked quite well) *** '*** was very slow. I replaced this seach by using INSTR() to find*** '*** which statements were in each line, and coloring them accord- *** '*** ingly. *** '********************************************************************* '*** Again, thanks to Sami for a great program, and I hope these *** '*** optomizations come in handy. *** '********************************************************************* DECLARE SUB ColPrint (Text$) DECLARE FUNCTION ParseLine$ (Line$) TYPE ColType Comment AS INTEGER Statement AS INTEGER Number AS INTEGER CString AS INTEGER Math AS INTEGER Default AS INTEGER END TYPE DIM SHARED Words AS INTEGER DIM SHARED Col AS ColType '---------------------------------------------------------------------------- ' Define colors '---------------------------------------------------------------------------- Col.Comment = 15 'Comment Col.Statement = 9 'QBasic statement Col.Number = 13 'a Number Col.CString = 14 'a String expression Col.Math = 10 'a Mathematical operator Col.Default = 7 'Default color RESTORE QData READ Words DIM SHARED QWord$(1 TO Words), Commands$ FOR i = 1 TO Words READ QWord$(i): Commands$ = Commands$ + QWord$(i) + " " NEXT '---------------------------------------------------------------------------- ' Open file '---------------------------------------------------------------------------- Filename$ = UCASE$("colrcode.bas") 'Filename$ = UCASE$("liteview.bas") 'Filename$ = UCASE$("test.bas") OPEN Filename$ FOR INPUT AS #1 CLS COLOR 15, 4 LOCATE 1, 1 PRINT STRING$(80, " ") LOCATE 1, 1 PRINT " ž Parsing file "; Filename$ VIEW PRINT 2 TO 25 COLOR 7, 0 LOCATE 25, 1 '---------------------------------------------------------------------------- ' Parse file '---------------------------------------------------------------------------- DO UNTIL EOF(1) OR INKEY$ <> "" LINE INPUT #1, Line$ Line$ = ParseLine(Line$) ColPrint Line$ PRINT VIEW PRINT COLOR 15, 4 LOCATE 1, 60 PRINT RTRIM$(STR$(INT(SEEK(1) / LOF(1) * 100))); "%" COLOR Col.Default, 0 VIEW PRINT 2 TO 25 LOCATE 25, 1 LOOP CLOSE #1 QData: '---------------------------------------------------------------------------- ' QBasic keyword data '---------------------------------------------------------------------------- DATA 268 DATA "REM" DATA "XOR" DATA "ABS" DATA "APPEND" DATA "ACCESS" DATA "AS" DATA "ALIAS" DATA "ASC" DATA "AND" DATA "ATN" DATA "ANY" DATA "BASE" DATA "BLOAD" DATA "BSAVE" DATA "BEEP" DATA "BYVAL" DATA "BINARY" DATA "CALL" DATA "CLS" DATA "CALLS" DATA "COLOR" DATA "CALL" DATA "ABSOLUTE DATA "COM" DATA "CALL" DATA "INTERRUPT" DATA "COMMAND$" DATA "CASE" DATA "COMMON" DATA "CDBL" DATA "CONST" DATA "CDECL" DATA "COS" DATA "CHAIN" DATA "CSNG" DATA "CHDIR" DATA "CSRLIN" DATA "CHR$" DATA "CVD" DATA "CINT" DATA "CVDMBF" DATA "CIRCLE" DATA "CVI" DATA "CLEAR" DATA "CVL" DATA "CLNG" DATA "CVS" DATA "CLOSE" DATA "CVSMBF" DATA "DATA" DATA "DEFINT" DATA "DEFLNG" DATA "DATE$" DATA "DEFSNG" DATA "DATE$" DATA "DEFSTR" DATA "DECLARE" DATA "DIM" DATA "DO" DATA "LOOP" DATA "DEF FN" DATA "DOUBLE" DATA "DEF SEG" DATA "DRAW" DATA "DEFDBL" DATA "$DYNAMIC" DATA "ELSE" DATA "ERDEV" DATA "ELSEIF" DATA "ERDEV$" DATA "END" DATA "ERL" DATA "END" DATA "IF" DATA "ERR" DATA "ENVIRON" DATA "ERROR" DATA "ENVIRON$" DATA "EXIT" DATA "EOF" DATA "EXP" DATA "EQV" DATA "ERASE" DATA "FIELD" DATA "FOR" DATA "NEXT" DATA "FILEATTR" DATA "FRE" DATA "FILES" DATA "FREEFILE" DATA "FIX" DATA "FUNCTION" DATA "GET" DATA "GOSUB" DATA "GET" DATA "GOTO" DATA "HEX$" DATA "IF" DATA "THEN" DATA "INPUT$" DATA "IMP" DATA "INSTR" DATA "$INCLUDE" DATA "INT" DATA "INKEY$" DATA "INTEGER" DATA "INP" DATA "IOCTL" DATA "INPUT" DATA "IOCTL$" DATA "INPUT #" DATA "IS" DATA "KEY" DATA "KILL" DATA "KEY" DATA "LBOUND" DATA "LOCATE" DATA "LCASE$" DATA "LOCK" DATA "UNLOCK" DATA "LEFT$" DATA "LOF" DATA "LEN" DATA "LOG" DATA "LET" DATA "LINE" DATA "LONG" DATA "LINE DATA "INPUT" DATA "LOOP" DATA "LPOS" DATA "LIST" DATA "LPRINT" DATA "LOC" DATA "LSET" DATA "LOCAL" DATA "LTRIM$" DATA "MID$" DATA "MKL$" DATA "MID$" DATA "MKS$" DATA "MKD$" DATA "MKSMBF$" DATA "MKDIR" DATA "MOD" DATA "MKDMBF$" DATA "MKI$" DATA "NAME" DATA "NOT" DATA "NEXT" DATA "OCT$" DATA "UEVENT" DATA "OFF" DATA "ON" DATA "GOSUB" DATA "GOTO" DATA "COM" DATA "OPEN" DATA "ERROR" DATA "OPEN" DATA "COM" DATA "KEY" DATA "OPTION BASE" DATA "PEN" DATA "OR" DATA "PLAY" DATA "OUT" DATA "STRIG" DATA "OUTPUT" DATA "TIMER" DATA "PAINT" DATA "POINT" DATA "PALETTE" DATA "POKE" DATA "PCOPY" DATA "POS" DATA "PEEK" DATA "PRESET" DATA "PEN" DATA "PRINT" DATA "PEN" DATA "PRINT" DATA "USING" DATA "PLAY" DATA "PRINT" DATA "PLAY" DATA "PSET" DATA "PLAY" DATA "PUT" DATA "PMAP" DATA "PUT" DATA "RANDOM" DATA "RETURN" DATA "RANDOMIZE" DATA "RIGHT$" DATA "READ" DATA "RMDIR" DATA "REDIM" DATA "RND" DATA "RSET" DATA "RESET" DATA "RTRIM$" DATA "RESTORE" DATA "RUN" DATA "RESUME" DATA "SADD" DATA "SPC" DATA "SCREEN" DATA "SQR" DATA "SCREEN" DATA "STATIC" DATA "SEEK" DATA "$STATIC" DATA "SEEK" DATA "STEP" DATA "SELECT" DATA "CASE" DATA "STICK" DATA "SETMEM" DATA "STOP" DATA "SGN" DATA "STR$" DATA "SHARED" DATA "STRIG" DATA "SHELL" DATA "STRIG" DATA "SIGNAL" DATA "STRING" DATA "SIN" DATA "STRING$" DATA "SINGLE" DATA "SUB" DATA "SLEEP" DATA "SWAP" DATA "SOUND" DATA "SYSTEM" DATA "SPACE$" DATA "TAB" DATA "TIMER" DATA "TAN" DATA "TO" DATA "THEN" DATA "TROFF" DATA "TIME$" DATA "TRON" DATA "TIME$" DATA "TYPE" DATA "TIMER" DATA "UBOUND" DATA "UNLOCK" DATA "UCASE$" DATA "UNTIL" DATA "UEVENT" DATA "USING" DATA "VAL" DATA "VARSEG" DATA "VIEW" DATA "VARPTR" DATA "VIEW" DATA "VARPTR$" DATA "WAIT" DATA "WINDOW" DATA "WEND" DATA "WRITE" DATA "WHILE" DATA "WEND" DATA "WRITE" DATA "WIDTH" SUB ColPrint (Text$) amploc = INSTR(Text$, "&") DO WHILE amploc > 0 PRINT LEFT$(Text$, amploc - 1); IF amploc + 1 <= LEN(Text$) THEN nextletter$ = MID$(Text$, amploc + 1, 1) IF INSTR("0123456789ABCDEF", nextletter$) THEN COLOR VAL("&H" + nextletter$) Text$ = RIGHT$(Text$, LEN(Text$) - amploc - 1) ELSE PRINT "&"; : Text$ = RIGHT$(Text$, LEN(Text$) - amploc) END IF END IF amploc = INSTR(Text$, "&") LOOP PRINT Text$; END SUB FUNCTION ParseLine$ (Line$) '---------------------------------------------------------------------------- ' Parses a QBasic source code line and returns a color-coded version of it, ' which can be printed with ColPrint. '---------------------------------------------------------------------------- Comment = 0 'Reset flags CharSt = -1 Found = 0 Math = 0 Number = 0 Hex = 0 OldChar$ = " " Parsed$ = "&" + HEX$(Col.Default) Pcolor = Col.Default OldPColor = Col.Default '**** This section of code added by Jonathan Leger. *** Remark = 0 FOR ii = 1 TO Words Changed = 0 QWloc = INSTR(Line$, QWord$(ii)) DO IF QWloc > 0 AND NOT Remark THEN '*** Check to see if statement is within quotes. qcount = 0 ql = INSTR(Line$, CHR$(34)) IF ql > 0 AND ql < QWloc THEN FOR lloc = 1 TO QWloc IF MID$(Line$, lloc, 1) = CHR$(34) THEN qcount = qcount + 1 END IF NEXT lloc END IF '*** Change the color only if the statement is not within quotes. IF (qcount MOD 2) = 0 THEN '*** Run through some tests to make sure that the statement '*** is an individual word and not part of another statement. IF QWloc = 1 THEN IF LEN(QWord$(ii)) = LEN(Line$) THEN Okay = -1 ELSE IF MID$(Line$, QWloc + LEN(QWord$(ii)), 1) = " " THEN Okay = -1 ELSE Okay = 0 END IF END IF ELSE IF MID$(Line$, QWloc - 1, 1) = " " THEN IF (QWloc + LEN(QWord$(ii)) - 1) = LEN(Line$) THEN Okay = -1 ELSE IF MID$(Line$, QWloc + LEN(QWord$(ii)), 1) = " " THEN Okay = -1 ELSE Okay = 0 END IF END IF ELSE Okay = 0 END IF END IF sqloc = INSTR(Line$, "'") IF sqloc > 0 THEN IF sqloc < ql OR ql = 0 THEN Pcolor = Col.Comment ParseLine$ = "&" + HEX$(Pcolor) + Line$ EXIT FUNCTION END IF END IF '*** Looks good, change the color. IF Okay THEN IF QWord$(ii) = "REM" THEN Pcolor = Col.Comment Remark = -1 ELSE Pcolor = Col.Statement END IF WrdLen = LEN(QWord$(ii)) l$ = LEFT$(Line$, QWloc - 1) Wrd$ = MID$(Line$, QWloc, WrdLen) r$ = RIGHT$(Line$, LEN(Line$) - (QWloc + WrdLen - 1)) IF Remark THEN ParseLine = "&" + HEX$(Pcolor) + Line$ EXIT FUNCTION ELSE Line$ = l$ + "&" + HEX$(Pcolor) + Wrd$ + "&" + HEX$(Col.Default) + r$ Changed = 2 END IF END IF END IF END IF QWloc = INSTR(QWloc + 1, Line$, QWord$(ii)) LOOP UNTIL QWloc = 0 NEXT ii '**** End of code added by Jonathan Leger. *** FOR i = 1 TO LEN(Line$) IF Math = 1 THEN Pcolor = Col.Default: Math = 0 IF Number = 1 THEN Pcolor = Col.Default: Number = 0 Char$ = MID$(Line$, i, 1) 'Read byte/word Word$ = MID$(Line$, i, 2) IF Comment = 0 THEN 'Check for string IF Char$ = CHR$(34) THEN Pcolor = Col.CString: CharSt = -CharSt END IF IF Comment = 0 AND CharSt = -1 THEN IF Char$ = " " THEN Pcolor = Col.Default: Hex = 0 'Check for numbers IF ASC(Char$) >= 48 AND ASC(Char$) <= 57 THEN IF i > 1 THEN IF MID$(Line$, i - 1, 1) <> "&" THEN Pcolor = Col.Number: Number = 1 END IF ELSE Pcolor = Col.Number: Number = 1 END IF END IF IF Word$ = "&H" THEN Pcolor = Col.Number: Hex = 1 IF Word$ = "&O" THEN Pcolor = Col.Number: Hex = 1 'Check for math IF INSTR("+-/\<>^*=", Char$) > 0 THEN Pcolor = Col.Math: Math = 1 END IF IF CharSt = -1 THEN 'Check for comments IF Char$ = "'" THEN Pcolor = Col.Comment: Comment = 1 END IF IF Hex = 1 THEN Pcolor = Col.Number 'Check for a hex number IF Pcolor <> OldPColor THEN Parsed$ = Parsed$ + "&" + HEX$(Pcolor) OldPColor = Pcolor OldChar$ = Char$ Parsed$ = Parsed$ + Char$ Found = Found - 1 NEXT ParseLine$ = Parsed$ END FUNCTION