home *** CD-ROM | disk | FTP | other *** search
AMOS Source Code | 1992-02-26 | 16.3 KB | 548 lines |
- '****************************************************************************
- '** Variable Checker V1.01 - By Paul Hickman (ph@doc.ic.ac.uk) **
- '** **
- '** Requires AMOS Pro & Easylife V1.4+ Distributed as freeware **
- '****************************************************************************
- Set Accessory
-
- '
- 'MXVARS is the maximum number of variable names in your program
- 'NUMCOMMANDS is the number of commands which may be confused with
- 'variable names (See Line 34).
- '
- Set Buffer 80
- MXVARS=300 : NUMCOMMANDS=6
- '
-
- Dim NAME$(MXVARS,1),NAME(MXVARS,4),TYPE$(4),COMMAND$(NUMCOMMANDS)
- Global AL$,NAME$(),NAME(),LAST,GLO,SHA,LOC,FLP,COMMAND$()
- 'NAME(N,0)=Type (See Below)
- 'NAME(N,1)=Number of local uses.
- 'NAME(N,2)=Number of global assignments.
- 'NAME(N,3)=Number of global references.
- 'NAME(N,4)=Line Number of definition.
- '
- GLO=1 : TYPE$(1)="Global"
- SHA=2 : TYPE$(2)="Shared"
- LOC=3 : TYPE$(3)="Local"
- FLP=4 : TYPE$(4)="For Loop"
- LAST=0
-
- For A=1 To NUMCOMMANDS : Read COMMAND$(A) : Next
-
- '************************************************************************
- 'These are the commands to ignore - Set NUMCOMANDS at the top of the code
- 'to the number of them.
-
- Data "Scene X","Scene Y","Imouse X","Imouse Y","Jd Char X","Jd Char Y"
-
- '************************************************************************
-
- INIT_SCREEN
-
- ' Make sure we are an accessory
- If Prg Under<>1
- If Exist("VarChecker.Doc")
- Read Text "VarChecker.Doc"
- Else
- NULL=Dialog Box(AL$,1,"This program must be run as an accessory!")
- End If
- MN_QUIT
- End If
-
- ' Initialise Program Listing
- '
- TITLE
- Clear Key
-
- ' Open all procedures
- Call Editor 89 : Rem Equ("AEd_UnfoldAll")
-
- ' Ask number of lines
- Ask Editor 5 : NLINES=Param : Rem Equ("AEdAsk_NumberOfLines")
-
- ' Top of text
- Call Editor 17 : RemEqu("AEd_TopOfText")
-
- SCOPE$="MAIN PROGRAM"
- For N=1 To NLINES
- Ask Editor 1,N : LINE$=Param$ : Rem Equ("AEdAsk_CurrentLine")
- SP= Extension_16_00C8(LINE$,32)
- LINE$=Mid$(LINE$,SP)
- If Left$(LINE$,7)="Shared "
- _DECLARE[Mid$(LINE$,8),SCOPE$,SHA,N,False]
- End If
- Next
-
- For N=1 To NLINES
-
- 'Read the current line
-
- Ask Editor 1,N : LINE$=Param$ : Rem Equ("AEdAsk_CurrentLine")
-
- 'Ignore whole line comments
-
- SP= Extension_16_00C8(LINE$,32)
- LINE$=Mid$(LINE$,SP)
- If(SP>0) and(Asc(LINE$)<>39)
-
- 'Replace all quoted strings with 0.
-
- Repeat
- A1= Extension_16_00AA(LINE$,"'") : If A1=0 : A1=Len(LINE$)+1 : End If
- A2= Extension_16_00AA(LINE$,'"') : If A2=0 : A2=Len(LINE$)+1 : End If
- A=Min(A1,A2)
- If A<Len(LINE$)+1
- If A=A1
- AA= Extension_16_00BC(LINE$,"'",A)
- Else
- AA= Extension_16_00BC(LINE$,'"',A)
- End If
- If AA
- LINE$=Left$(LINE$,A-1)+"0"+Mid$(LINE$,AA+1)
- Else
- LINE$=Left$(LINE$,A-1)
- End If
- End If
- Until A=Len(LINE$)+1
-
- 'Check for procedure definition
-
- If Left$(Upper$(LINE$),9)="PROCEDURE"
-
- 'Get procedure name for scope of local variables
-
- P= Extension_16_008C(LINE$,91)
- If P
- SCOPE$=Mid$(LINE$,11,P-11)
- Else
- SCOPE$=Mid$(LINE$,11)
- End If
-
- 'Record declaration of parameters as local variables
-
- _DECLARE[Mid$(LINE$,P+1,Len(LINE$)-P-1),SCOPE$,LOC,N,False]
-
-
-
- Else If Left$(LINE$,8)="End Proc"
-
- 'Pass End Proc's argument string for references
-
- If Mid$(LINE$,9,1)="["
- PARSE_ARGS[Mid$(LINE$,10,Len(LINE$)-10),SCOPE$,False,N]
- End If
-
- 'Scan for local variables/parameters were not refered to, and
- 'shared variables that were not refered to, or set to a value.
-
- A=0 : While A<LAST
- If NAME$(A,1)=SCOPE$
- If NAME(A,1)=0
- If NAME(A,0)=LOC
- 'Allow NULL to be unreferenced
- If(NAME$(A,0)<>"NULL") and(NAME$(A,0)<>"NULL#") and(NAME$(A,0)<>"NULL$")
- DLOG["Unreferenced Local Variable: "+NAME$(A,0)]
- End If
- Else
- If NAME(A,0)=SHA
- DLOG["Unused Shared Variable: "+NAME$(A,0)]
- End If
- End If
- End If
- If NAME(A,0)>=LOC
- 'Remove all local/for loop variables from array
- For AA=A To LAST+1
- For XX=0 To 4 : NAME(AA,XX)=NAME(AA+1,XX) : Next
- NAME$(AA,0)=NAME$(AA+1,0)
- NAME$(AA,1)=NAME$(AA+1,1)
- Next
- Dec LAST
- Else
- NAME(A,1)=0
- Inc A
- End If
- Else
- Inc A
- End If
- Wend
-
- 'Change scope to outside procedure
-
- SCOPE$="MAIN PROGRAM"
-
-
-
-
- Else If Left$(LINE$,7)="Shared "
- 'Record declaration of shared variables
- _DECLARE[Mid$(LINE$,8),SCOPE$,SHA,N,False]
-
- Else If Left$(LINE$,7)="Global "
- 'Record declaratino of global variables
- _DECLARE[Mid$(LINE$,8),SCOPE$,GLO,N,False]
-
- Else
- 'Splitup the line into it's statements, and parse each in turn.
-
- While LINE$<>""
- Exit If Left$(LINE$,4)="Rem "
- SEP= Extension_16_00AA(LINE$,":")
- If SEP
- STATE$=Left$(LINE$,SEP-2)
- LINE$=Mid$(LINE$,SEP+2)
- Else
- STATE$=LINE$ : LINE$=""
- End If
- '
- PARSE_STAT[STATE$,N,False]
- Wend
-
- End If
- End If
-
- 'Move to the next line of program source.
-
- Call Editor 2 : Rem Equ("AEd_Down")
-
- Next
-
- For A=0 To LAST
- If(NAME$(A,0)<>"") and(NAME(A,0)<>FLP) and(NAME$(A,0)<>"NULL") and(NAME$(A,0)<>"NULL#") and(NAME$(A,0)<>"NULL$")
- If(NAME(A,2)=0) and(NAME(A,3)=0)
- Call Editor 76,NAME(A,4)
- DLOG["Unused "+TYPE$(NAME(A,0))+" Variable: "+NAME$(A,0)]
- Else If(NAME(A,2)=0) and(NAME(A,0)<>LOC)
- Call Editor 76,NAME(A,4)
- DLOG["Undefined "+TYPE$(NAME(A,0))+" Variable: "+NAME$(A,0)]
- Else If NAME(A,3)=0
- Call Editor 76,NAME(A,4)
- T$=TYPE$(NAME(A,0))
- If(NAME(A,0)=LOC) and(NAME$(A,1)="MAIN PROGRAM") : T$="Main Program" : End If
- DLOG["Unreferenced "+T$+" Variable: "+NAME$(A,0)]
- End If
- End If
- Next
- NULL=Dialog Box(AL$,1,"Scan completed. No more undeclared or unreferenced variables")
- MN_QUIT
-
- Procedure INIT_SCREEN
-
- 'Generates code to draw requesters.
-
- Restore ALT
- Repeat
- Read A$ : AL$=AL$+A$
- Until A$=""
- For A=1 To 7 : Trap Screen Close A : Next
- Resource Screen Open 0,640,40,0
- Curs Off : Flash Off : Cls 0
- Screen Display 0,,60,,
- Wait Vbl
-
- Paper 0 : Pen 1
- Pop Proc
-
- ' QUICK RUN DIALOG BOXES
- ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ALT: Data " "
- ' One button, CANCEL
- ' ~~~~~~~~~~~~~~~~~~
- Data "SIze SW,SH;"
- Data "BAse SWidth SX -2/,SHeight SY- 2/;"
- Data "IF 0VA 0=;"
- Data "["
- Data "BOx 0,0,1,SX,SY;"
- Data "POut 1VACX,16,1VA,0,7;"
- Data "BU 0,0,0,SX,SY,0,0,0;[][SM;]"
- Data "]"
- Data "IF 0VA 1=;"
- Data "["
- Data "BOx 0,0,1,SX,SY;"
- Data "POut 1VACX,8,1VA,0,7;"
- Data "BU 1,SX112-,SY16-,96,16,0,0,1;[LI 0,0,41BP3*+,SX;PR 'Quit' CXBP+,1,'Quit',7;][BR0;BQ;]"
- Data "KY 27,0;"
- Data "BU 0,0,0,SX,SY,0,0,0;[][SM;]"
- Data "RUn 0,3;"
- Data "]"
- Data "IF 0VA 2=;"
- Data "["
- Data "BOx 0,0,1,SX,SY;"
- Data "POut 1VACX,8,1VA,0,7;"
- Data "BU 1,16,SY16-,96,16,0,0,1;[LI 0,0,41BP3*+,SX;PR 'Continue'CXBP+,1,'Continue',7;][BR0;BQ;]"
- Data "KY 13,0;"
- Data "BU 2,SX112-,SY16-,96,16,0,0,1;[LI 0,0,41BP3*+,SX;PR 'Stop'CXBP+,1,'Stop',7;][BR0;BQ;]"
- Data "KY 27,0;"
- Data "BU 0,0,0,SX,SY,0,0,0;[][SM;]"
- Data "RUn 0,3;"
- Data "]"
- Data "EXit;"
- Data ""
-
- End Proc
- Procedure MN_QUIT
- 'Closes everything
-
- Trap Dialog Close
- Trap Screen Close 0
- Erase All : Close
- Edit
- End Proc
- Procedure _DECLARE[L$,SCOPE$,TYPE,N,REF]
- 'Records the declaration of a list of variables.
-
- While L$<>""
-
- 'Get variables from list
- A=0
- Repeat
- A= Extension_16_00BC(L$,",;",A)
- Until Extension_16_051C(Left$(L$,A),40)= Extension_16_051C(Left$(L$,A),41)
- If A
- A$=Left$(L$,A-1)
- L$=Mid$(L$,A+1)
- Else
- A$="" : Swap A$,L$
- End If
-
- 'A$=Next variable
- 'Check for brackets after, which means it is an array, or the
- 'last word of a command, and should be ignored, however, the
- 'contents of the brackets show be checked for references.
-
- B1= Extension_16_008C(A$,40)
- If B1>0
- If Mid$(A$,B1+1,1)<>")"
- PARSE_ARGS[Mid$(A$,B1+1,Len(A$)-B1-1),SCOPE$,False,N]
- End If
- Else
- If A$=Upper$(A$)
- 'Ignore reserved variables / bits of command names, which
- 'will contain lower case variables.
-
- 'Check if this name is already declared in this scope.
- _SEARCH[A$,SCOPE$,False,TYPE=SHA] : R=Param
-
- If R=>0
- 'It is. That means this is a use, for non-local variables
- If TYPE=GLO
- 'A Global command occurs after variable use
- If NAME(R,0)=SHA
- DLOG["Global Variable "+A$+" Is Shared In Some Procedures "]
- Else
- DLOG["Variable "+A$+" Made Global AFTER Use"]
- End If
- NAME(R,0)=GLO
- Else If(NAME(R,0)<>LOC)
- Inc NAME(R,1) : Inc NAME(R,2)
- End If
- Else
- 'Otherwise, record the declaration.
- A=0
- If LAST>0
- While NAME$(A,0)<A$ : Inc A : Exit If A=LAST : Wend
-
- For AA=LAST To A Step -1
- NAME$(AA+1,0)=NAME$(AA,0)
- NAME$(AA+1,1)=NAME$(AA,1)
- For XX=0 To 4 : NAME(AA+1,XX)=NAME(AA,XX) : Next
- Next
- End If
- NAME$(A,0)=A$
- NAME$(A,1)=SCOPE$
- NAME(A,0)=TYPE
- If REF
- NAME(A,1)=1
- NAME(A,2)=0
- NAME(A,3)=1
- Else
- NAME(A,1)=0
- NAME(A,2)=1
- NAME(A,3)=0
- End If
- NAME(A,4)=N
- Inc LAST
- End If
- End If
- End If
-
-
- Wend
- End Proc
- Procedure PARSE_STAT[STATE$,N,FSTAT]
- Shared SCOPE$
- If Left$(STATE$,5)="Trap "
- PARSE_STAT[Mid$(STATE$,6),N,False]
-
- Else If(Left$(STATE$,7)="Input #") or(Left$(STATE$,12)="Line Input #")
- HASH= Extension_16_008C(STATE$,35)
- SEP=0
- Repeat
- SEP= Extension_16_009E(STATE$,44,SEP)
- Until Extension_16_051C(Left$(STATE$,SEP),40)= Extension_16_051C(Left$(STATE$,SEP),41)
- PARSE_ARGS[Mid$(STATE$,HASH+1,SEP-HASH),SCOPE$,False,N]
- _DECLARE[Mid$(STATE$,SEP+1),SCOPE$,LOC,N,False]
-
- Else If Left$(STATE$,6)="Input "
- SEP= Extension_16_010C(STATE$,59)
- If SEP
- PARSE_ARGS[Mid$(STATE$,6,SEP-6),SCOPE$,False,N]
- _DECLARE[Mid$(STATE$,SEP+1),SCOPE$,LOC,N,False]
- Else
- _DECLARE[Mid$(STATE$,6),SCOPE$,LOC,N,False]
- End If
-
-
- Else If Left$(STATE$,4)="For "
- PARSE_STAT[Mid$(STATE$,5),N,True]
-
- Else If(Left$(STATE$,5)="Read ") and(Left$(STATE$,10)<>"Read Text$")
- _DECLARE[Mid$(STATE$,6),SCOPE$,LOC,N,False]
- Else If(Left$(STATE$,5)="Goto ") or(Left$(STATE$,6)="Gosub ") or(Left$(STATE$,5)="Proc ")
- 'Do Nothing
- Else If(Left$(STATE$,8)="Restore ") or(Left$(STATE$,7)="Resume ") or(Left$(STATE$,6)="Def Fn")
- 'Also Do nothing
-
- Else If(Left$(STATE$,3)="On ")
- A=Instr(STATE$," Proc ")
- If A>0 : PARSE_ARGS[Mid$(STATE$,4,A-4),SCOPE$,False,N] : End If
- A=Instr(STATE$," Goto ")
- If A>0 : PARSE_ARGS[Mid$(STATE$,4,A-4),SCOPE$,False,N] : End If
- A=Instr(STATE$," Gosub ")
- If A>0 : PARSE_ARGS[Mid$(STATE$,4,A-4),SCOPE$,False,N] : End If
-
- Else If(Left$(STATE$,6)="Every ")
- A=Instr(STATE$," Proc ")
- If A>0 : PARSE_ARGS[Mid$(STATE$,6,A-6),SCOPE$,False,N] : End If
- A=Instr(STATE$," Gosub ")
- If A>0 : PARSE_ARGS[Mid$(STATE$,6,A-6),SCOPE$,False,N] : End If
-
- Else If(Left$(STATE$,3)="If ") or(Left$(STATE$,3)="If(")
- A=Instr(STATE$," Then ",A+1)
- If A>0
- PARSE_ARGS[Mid$(STATE$,3,A-3),SCOPE$,False,N]
- PARSE_STAT[Mid$(STATE$,A+6),N,False]
- Else
- PARSE_ARGS[Mid$(STATE$,3),SCOPE$,False,N]
- End If
-
- Else
- A=Instr(STATE$,"Else ",A+1)
- If A
- If Asc(Mid$(STATE$,A-1))=32
- PARSE_STAT[Left$(STATE$,A-2),N,False]
- Else
- PARSE_STAT[Left$(STATE$,A-1),N,False]
- End If
- PARSE_STAT[Mid$(STATE$,A+5),N,False]
- Else
-
-
- 'Check for '=' outside brackets, before any spaces, and before commas
- EQ=0
- Repeat
- EQ= Extension_16_009E(STATE$,61,EQ)
- Exit If EQ=0
- NAME$=Left$(STATE$,EQ-1)
- Until( Extension_16_051C(NAME$,40)= Extension_16_051C(NAME$,41)) and( Extension_16_008C(NAME$,32)=0) and( Extension_16_008C(NAME$,44)=0)
-
-
- If EQ
- PARSE_ARGS[Mid$(STATE$,EQ+1),SCOPE$,False,N]
- If FSTAT
- _DECLARE[NAME$,SCOPE$,FLP,N,False]
- Else
- _DECLARE[NAME$,SCOPE$,LOC,N,False]
- End If
- Else
- PARSE_ARGS[STATE$,SCOPE$,True,N]
- End If
- End If
- End If
- End Proc
- Procedure PARSE_ARGS[ARG$,SCOPE$,WHOLE,N]
- Shared NUMCOMMANDS,NUMINLINES
-
- If ARG$="" Then Pop Proc
- A=0 : L1$="ABCDEFGHIJKLMNOPQRSTUVWXYZ_"
- L2$="1234567890#$"
- FL$="<>=+-*/^,]) "
- PRE$="$1234567890"
- Do
- Repeat
- Inc A
- B=Asc(Mid$(ARG$,A))
- Exit If A>Len(ARG$),2
- Until Extension_16_008C(L1$,B)>0
- '
- If A>1
- Exit If Extension_16_008C(PRE$,Asc(Mid$(ARG$,A-1)))>0
- End If
-
- A1=0 : IGNORE=False
- Repeat
- Inc A1
- Exit If A+A1>Len(ARG$)
- B1=Asc(Mid$(ARG$,A+A1))
- Until Extension_16_008C(L1$+L2$,B1)=0
-
- If A1=1
- If(Asc(Mid$(ARG$,A+A1,1))=32)
- X$=Mid$(ARG$,A+A1+1,1)
- If X$=Upper$(X$)
- IGNORE=True
- End If
- End If
- For X=1 To NUMCOMMANDS
- If A>=Len(COMMAND$(X))-1
- If Mid$(ARG$,A-Len(COMMAND$(X))+1,Len(COMMAND$(X)))=COMMAND$(X)
- IGNORE=True : Exit
- End If
- End If
- Next
-
- End If
-
- If Not IGNORE
- If(A+A1>Len(ARG$)) or( Extension_16_008C(FL$,B1)>0) or(Mid$(ARG$,A+A1,4)=" and") or(Mid$(ARG$,A+A1,3)=" or") or(Mid$(ARG$,A+A1,3)=" To") or(Mid$(ARG$,A+A1,3)=" As")
- If Not((A=1) and(A1=Len(ARG$)) and(WHOLE=True))
- _REFERAL[Mid$(ARG$,A,A1),SCOPE$,N]
- End If
- End If
- End If
- A=A+A1
- Loop
- End Proc
- Procedure _REFERAL[ARG$,SCOPE$,N]
- _SEARCH[ARG$,SCOPE$,True,False]
- If Param=True
- DLOG["Undefined Variable: "+ARG$]
- _DECLARE[ARG$,SCOPE$,LOC,N,True]
- End If
- End Proc
- Procedure _SEARCH[NAME$,SCOPE$,REFER,NEWSHARED]
-
- R=-1 : A=0
- While A<LAST
- If NAME$(A,0)=NAME$
- If(NAME(A,0)=SHA) and NEWSHARED
- NAME$(A,1)=SCOPE$
- End If
- If(NAME(A,0)=GLO) or((NAME(A,0)>=LOC) and(NAME$(A,1)=SCOPE$)) or((NAME(A,0)=SHA) and((NAME$(A,1)=SCOPE$) or(SCOPE$="MAIN PROGRAM")))
- If REFER : Inc NAME(A,1) : Inc NAME(A,3) : End If
- R=A : Exit
- End If
- Else If NAME$(A,0)>NAME$
- Exit
- End If
- Inc A
- Wend
- End Proc[R]
- Procedure DLOG[A$]
- R=Dialog Box(AL$,2,A$)
- If R=2 : MN_QUIT : End If
- TITLE
- End Proc
- Procedure TITLE
- NULL=Dialog Box(AL$,0,"Variable Checker By Paul Hickman. Ctrl-C To Abort")
- End Proc