' Source for the main program precedes all source for subprograms.  The
' interpreter can handle discontinuous main programs, but the compiler
' cannot.  This program requires that the source file to be sorted be
' a text file, that is, it should not have been saved as 'Compressed'
' by the interpreter.

' Boolean constants.
true% = -1
false% = 0

' String constants.
digits$ = "0123456789"
alphabet$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

' Get the file name from the user.
print "File name: ";
input filename$

' Open a temporary file to recieve the sorted program.
open "o",#1,"temp"

' Sort the program in three passes.
'    pass 1 - write all DIM SHARED statements to the temporary file.
'    pass 2 - write the main program source lines to the temporary file.
'    pass 3 - write out all of the subprograms.

for pass% = 1 to 3

' Open the source file for each pass.
  open "i",#2,filename$
  
' Initialize position flags.
insub% = false%         ' Not in a subroutine.
inmain% = true%         ' In the main program.

  while not eof(2)

    line input #2,inline$      ' Get a line of source code.
    work$ = inline$            ' Get a working copy.
    work$ = ucase$(work$)      ' Convert to upper case.
    call bypass(work$)         ' Bypass leading spaces.
    call stripnum(work$)       ' Remove numeric label (if any).
    call bypass(work$)         ' Bypass spaces.
    call striplab(work$)       ' Remove alphanumeric label (if any).
    call bypass(work$)         ' Bypass spaces.
    call getid(work$,id1$)     ' Get the first identifier.
    call bypass(work$)         ' Bypass spaces.
    call getid(work$,id2$)     ' Get the second identifier.

' If the statement starts with the keyword 'SUB' then this line
' starts a subprogram.  Set the flags accordingly.
    if id1$ = "SUB" then insub% = true% : inmain% = false%

' If the statement is a DIM SHARED statement and this
' is pass one, then write out the line.
    if NOT((id1$="DIM") and (id2$="SHARED")) then goto noDimShared
    if (pass% = 1) then print #1, inline$ 
    goto doneDimShared

' Write out the main program source lines during pass 2 and
' the subprogram source lines during pass 3.
noDimShared:
    if insub%  and (pass% = 3) then print #1, inline$
    if inmain% and (pass% = 2) then print #1, inline$

' If the statement starts with the keyword 'END', check for an
' 'END SUB' statement.  This ends a subprogram, and the flags should
' be set accordingly.
    if (id1$="END") and (id2$="SUB") then insub% = false% : inmain% = true%

doneDimShared:

  wend

' Close the source file after each pass.
  close #2

next pass%

' Delete the original sorce file and rename the temporary.
close #1            ' Close the temporary file.
kill filename$
name "temp" as filename$

end

' Remove leading spaces and tabs from st$.
sub bypass(st$) static
while (left$(st$,1) = " ") or (left$(st$,1) = chr$(9))
  st$ = mid$(st$,2)
wend
end sub

' Remove numeric label (if any) from st$.
sub stripnum(st$) static
shared alphabet$,digits$
while (st$ <> "") and (instr(digits$,left$(st$,1)) <> 0)
  st$ = mid$(st$,2)
wend
end sub

' Remove alphanumeric label (if any) from st$.
sub striplab(st$) static
shared alphabet$,digits$
work$ = st$
if instr(alphabet$,left$(work$,1)) = 0 then exit sub
while (work$ <> "") and (instr(alphabet$ + digits$, left$(work$,1)) <> 0)
  work$ = mid$(work$,2)
wend
if left$(work$,1) = ":" then st$ = mid$(work$,2)
end sub

' Remove the first alphanumeric identifier from the front of
' st$ (if any) and return it in id$.
sub getid(st$,id$) static
shared alphabet$,digits$
id$ = ""
if instr(alphabet$,left$(st$,1)) = 0 then exit sub
while (st$ <> "") and (instr(alphabet$ + digits$, left$(st$,1)) <> 0)
id$ = id$ + left$(st$,1)
st$ = mid$(st$,2)
wend
end sub

