Between the ================= lines is the help file. Vue this file and
unyank the help file. Then delete those lines and compile the program.

=====================================================================
                                 FULIST.BAS
                                Full Listing


                This   program  will  give  you  a  complete
           listing of BASIC files  that  use  the  ++INCLUDE
           feature within AlphaBASIC. It is very helpful for
           debugging  a  program  when  there  is  a problem
           within  a  subroutine  that  would  not  normally
           appear  in  a  listing  of  the program that only
           shows the ++INCLUDE statements.

                For more information about how  to  use  the
           INCLUDE  command,  please refer to the AlphaBASIC
           Users Manual (revision B02 or greater) Chapter 3.

                To use the program, you need only  know  the
           name  of  the  BASIC program that you wish to see
           the full listing of. The program  will  create  a
           file  with  the  same name as your BASIC program,
           with the extension .FUL. If you  had  a  previous
           program  with  the  .FUL  extension,  FULIST will
           inform you and you can choose to exit, or the old
           version of the program will be destroyed,  and  a
           new one will be created.

                AlphaBASIC  will COMPILe  programs with more
           than one  ++INCLUDE  statement  on  one line, but
           FULIST expects only  one ++INCLUDE  per line. You
           will get error  messages about not  finding files
           if you have multiple ++INCLUDE statements.

                FULIST  assumes  a default extension of .BAS
           for  your  program,  but  you  may  specify   any
           extension you desire. FULIST will only operate on
           a  source  file  within your account, but it will
           find ++INCLUDed files in your  account,  the  PPN
           matching  yours ending with 0, and on DSK0:[7,6].
           (This follows the normal searching mechanism that
           COMPIL would go through to locate  an  ++INCLUDEd
           file).

                FULIST  prints  a  dot for each line that is
           being  processed,  and  gives  you  some  summary
           information at the end of it's run that may be of
           some  use  to you during debugging.  If a file is
           not found, FULIST will show an error  message  on
           the  screen,  but complete its run. It will leave
           the ++INCLUDE line  in  the  final  program,  and
           append  a  list  of files not found at the end of
           the expanded listing.

                FULIST has no effect on your  original  file
           so  you  may use it without fear of changing your
           source programs.

                To invoke FULIST, just type RUN FULIST,  the
           program  will prompt you for the name of the file
           you wish to process.


=======================================================================
! FULIST.BAS  FULL LISTING of BASIC programs that use the ++INCLUDE
!       feature. See the instructions for further information.
!       There is also a HELP file in DSK0:[7,1]
!       Steve Elliott 9/5/81

MAP1 SOURCE'FILE,S,10       ! only works on files within the user's PPN
MAP1 DESTINATION'FILE,S,10  ! Always has the extension '.FUL'
MAP1 INCLUDED'FILE,S,24    ! will take a full filespec: DSK0:xxx.xxx[P,PN]
MAP1 ERROR'FILE,S,10,"ERRORS.FUL"  ! Temporary file for lost INCLUDEs
MAP1 FILE'NAME,S,24         ! holding bucket for files while error checking
MAP1 EXTENSION,S,10         ! the extension for the PPNS on included files

MAP1 ERROR'MESSAGES,S,80    ! Get tacked onto the end of the destination file
MAP1 TEXT'LINE,S,150        ! lots of room - you never can tell....
MAP1 TEMP'LINE,S,150        ! holds upper case TEXT'LINE for searches
MAP1 INCLUDED'TEXT'LINE,S,150
MAP1 OPEN'FILE(4),B,1       ! keeps track of open files

MAP1 CHARACTER,S,1          ! used for the HELP display
MAP1 LINE'COUNT,F           ! also for the HELP display
MAP1 PPN,F                  ! number returned by the system for PPN
MAP1 P,S,10                 ! project number
MAP1 PN,S,10                ! programer number
MAP1 WORK,F                 ! work variable for conversion to octal for PPN
MAP1 OCTAL,S,10             ! octal result for PPNs
MAP1 VALID'DIGIT,S,10,"0123456789" ! Play toy for octal conversion
MAP1 DOOMED,S,1             ! Decides whether or not to destroy existing files
MAP1 X,F                    ! used by INSTR to see if a line has an INCLUDE
MAP1 Y,F                    ! used by INSTR to find a . in a file name
MAP1 Z,F                    ! used by LOOKUP to find files
MAP1 DUMMY,S,1              ! just that - used by PAUSE & other subroutines

MAP1 INCLUDE'SEARCHES,F     ! counter for attempted searches
MAP1 SUCCESSFUL'SEARCHES,F  ! hopefully always same as INCLUDE'SEARCHES
MAP1 SOURCE'COUNT,F         ! counter for number of source file lines
MAP1 INCLUDE'COUNT,F        ! cunter for number of include file lines

CALL GET'PPN

MENU:
       ! There's a wierdness here! - if the user chooses to do the full
       ! list thing, it automatically drops straight through to QUIT.
       ! This program should END before being run again so that
       ! variables get cleaned up & reset to nulls or zero.
       ? TAB(-1,0)
       ? TAB(2,30); "FULIST.BAS"
       ? TAB(4,10); "Full Listing for BASIC programs using the INCLUDE statement"
       ? TAB(10,10); "Would you like:"
       ? TAB(12,15); "1. Instructions"
       ? TAB(13,15); "2. A full listing of a BASIC program sent to a file"
       ? TAB(14,15); "3. To quit."
       ? TAB(16,15);
       INPUT "Enter your choice --> ", CHOICE
       ON CHOICE CALL INSTRUCTIONS, PROCESS, QUIT
       GOTO MENU

INSTRUCTIONS:
       ? TAB(-1,0)
       CHARACTER = ""
       OPEN #99, "DSK0:FULIST.HLP[7,1]", INPUT
       LINE'COUNT = 1
       CALL DISPLAY'LOOP
       TEXT'LINE = ""
       RETURN

PROCESS:
       ? TAB(-1,0); TAB(2,20);
       ? "FULIST.BAS - Full Listing of Source files"
       INCLUDE'SEARCHES = 0  :  SUCCESSFUL'SEARCHES = 0
       SOURCE'COUNT = 0      :  INCLUDE'COUNT = 0
       CALL DETERMINE'SOURCE'FILE'NAME
       CALL LOOKUP'DESTINATION'FILE
       ? TAB(10,1); "Processing source file"
       OPEN #1, SOURCE'FILE, INPUT        : OPEN'FILE(1) = 1
       OPEN #2, DESTINATION'FILE, OUTPUT  : OPEN'FILE(2) = 1
       OPEN #3, ERROR'FILE, OUTPUT        : OPEN'FILE(3) = 1
       CALL READ'THROUGH'THE'SOURCE'FILE

QUIT:
       ? TAB(10,1); TAB(-1,10)
       IF LEN(DESTINATION'FILE) = 0 &
           THEN &
               ? TAB(23,1); "THE END" :&
               END
       ? "Closing files and tidying up - one moment please"
       IF OPEN'FILE(1) = 1 &
           THEN &
               CLOSE #1 : OPEN'FILE(1) = 0
       IF OPEN'FILE(3) = 1 &
           THEN &
               CLOSE #3 : OPEN'FILE(3) = 0 :&
               CALL WRITE'ERROR'MESSAGES'TO'DESTINATION'FILE
       IF OPEN'FILE(2) = 1 &
           THEN &
               CLOSE #2 : OPEN'FILE(2) = 0
       IF OPEN'FILE(3) = 1 &
           THEN &
               CLOSE #3 : OPEN'FILE(3) = 0
       LOOKUP "ERRORS.FUL", Z
       IF Z > 0 &
           THEN &
               KILL "ERRORS.FUL"
       CALL DISPLAY'STATISTICS
       ? TAB(23,1); "THE END"
       END

! ************************* LEVEL 1 *****************************

DISPLAY'LOOP:
       INPUT LINE #99, TEXT'LINE
       IF EOF(99) # 1 AND UCS(CHARACTER) # "Q" &
           THEN &
               CALL LINE'DISPLAY :&
               GOTO DISPLAY'LOOP &
           ELSE &
               IF UCS(CHARACTER) # "Q" &
                   THEN &
                       CALL PAUSE
       CLOSE #99
       RETURN

DETERMINE'SOURCE'FILE'NAME:
       CALL ENTER'SOURCE'FILE'NAME
       IF FILE'CHECK # "OK" &
           THEN &
               CALL BOGUS'FILE'NAME :&
               GOTO DETERMINE'SOURCE'FILE'NAME
       CALL LOOKUP'SOURCE'FILE
       RETURN

LOOKUP'DESTINATION'FILE:
       Y = 0
       Y = INSTR(1,SOURCE'FILE,".")
       DESTINATION'FILE = SOURCE'FILE[1,(Y-1)] + ".FUL"
       LOOKUP DESTINATION'FILE, Z
       IF Z > 0 &
           THEN &
               CALL DESTINATION'ALREADY'EXISTS
       RETURN

READ'THROUGH'THE'SOURCE'FILE:
       ? TAB(11,1);
       SOURCE'READ'LOOP:
           ? ".";
           SOURCE'COUNT = SOURCE'COUNT + 1
           X = 0
           INPUT LINE #1, TEXT'LINE
           TEMP'LINE = UCS(TEXT'LINE)
           IF EOF(1) # 1 &
               THEN &
                   X = INSTR(1,TEMP'LINE,"++INCLUDE") :&
                   IF X > 0 &
                       THEN &
                           CALL PROCESS'INCLUDE'LINE :&
                           GOTO SOURCE'READ'LOOP &
                       ELSE &
                           CALL PROCESS'NORMAL'LINE :&
                           GOTO SOURCE'READ'LOOP
       RETURN

DESTINATION'ALREADY'EXISTS:
       ? TAB(10,1); TAB(-1,10);
       ? DESTINATION'FILE; " already exists, do you wish to destroy it"
       INPUT LINE "and create a new one in it's place? --> ", DOOMED
       IF UCS(DOOMED) # "Y" &
           THEN &
               CALL MESSAGE'OF'DOOM
       ? TAB(10,1); TAB(-1,10);
       RETURN

WRITE'ERROR'MESSAGES'TO'DESTINATION'FILE:
       IF OPEN'FILE(3) = 0 &
           THEN &
               OPEN #3, "ERRORS.FUL", INPUT : OPEN'FILE(3) = 1
       INPUT LINE #3, TEXT'LINE
       IF EOF(3) # 1 &
           THEN &
               CALL PRINT'ERROR'FILE'HEADING :&
               CALL READ'SOME'MORE'ERRORS
       RETURN

! ************************* LEVEL 2 *****************************

LINE'DISPLAY:
       LINE'COUNT = LINE'COUNT + 1
       IF LINE'COUNT < 22 &
           THEN &
               ? TEXT'LINE &
           ELSE &
               ? TEXT'LINE :&
               LINE'COUNT = 0 :&
               CALL BAIL'OUT :&
               ? TAB(-1,0)
       RETURN

BAIL'OUT:
       ? TAB(23,1); TAB(-1,10);
       INPUT LINE "Enter 'Q' to QUIT, RETURN to continue --> ", CHARACTER
       RETURN

ENTER'SOURCE'FILE'NAME:
       ? TAB(10,1); TAB(-1,10);
       ? "Please enter the name of the file to be listed."
       INPUT LINE "(.BAS is assumed as an extension --> ", FILE'NAME
       ? TAB(10,1); TAB(-1,10)
       FILE'NAME = UCS(FILE'NAME)
       CALL CHECK'FILE'NAME
       RETURN

LOOKUP'SOURCE'FILE:
       LOOKUP SOURCE'FILE, Z
       IF Z <= 0 &
           THEN &
               CALL BOGUS'FILE'NAME
       RETURN

PROCESS'INCLUDE'LINE:
       INCLUDE'SEARCHES = INCLUDE'SEARCHES + 1
       Z = 0  : X = 0
       X = INSTR(1,TEXT'LINE," ")
       INCLUDED'FILE = TEXT'LINE[ X+1, LEN(TEXT'LINE)]
       CALL CHECK'INCLUDED'FILE'NAME
       ! This is a three step search:
       !    1. in the local PPN
       !    2. In the project, Programmer number 0
       !    3. In DSK0:[7,6]
       CALL ON'TO'18

       LOOKUP INCLUDED'FILE, Z
       IF Z = 0 &
           THEN &
               CALL ADD'PPN :&
               LOOKUP INCLUDED'FILE, Z :&
               IF Z = 0 &
                   THEN &
                       CALL ADD'DSK0 :&
                       LOOKUP INCLUDED'FILE, Z :&
                       IF Z = 0 &
                           THEN &
                               CALL NO'INCLUDE'FILE'FOUND :&
                               CALL PROCESS'NORMAL'LINE
       IF Z > 0 &
           THEN &
               SUCCESSFUL'SEARCHES = SUCCESSFUL'SEARCHES + 1 :&
               OPEN #4, INCLUDED'FILE, INPUT :&
               CALL READ'IN'INCLUDE'FILE'LINES :&
               CLOSE #4
       RETURN

PROCESS'NORMAL'LINE:
       ? #2, TEXT'LINE
       ? ".";
       RETURN

PRINT'ERROR'FILE'HEADING:
       ? "Listing lost INCLUDED files at the end of "DESTINATION'FILE
       ? #2 : ? #2, "! INCLUDED files not found:"
       ? #2
       ? #2, "! "; TEXT'LINE
       RETURN

READ'SOME'MORE'ERRORS:
       INPUT LINE #3, TEXT'LINE
       IF EOF(3) # 1 &
           THEN &
               ? #2, "! "; TEXT'LINE :&
               GOTO READ'SOME'MORE'ERRORS
       RETURN

MESSAGE'OF'DOOM:
       ? : ? "This program can't continue until you rename that"
       ? "file or whatever. Please take whatever steps you think"
       ? "are necessary, and then come back and try this again."
       ? TAB(23,1); TAB(-1,10); "End of FULIST"
       END
       ! This subroutine dies here - no RETURN

! ************************* LEVEL 3 *****************************

CHECK'FILE'NAME:
       Z = 0  :  FILE'CHECK = ""
       Z = INSTR(1,FILE'NAME,".")
       ! If there's no extension, add .BAS as the default
       IF Z = 0 &
           THEN &
               IF LEN(FILE'NAME) > 0 AND LEN(FILE'NAME) <= 6 &
                   THEN &
                       FILE'NAME = FILE'NAME + ".BAS" :&
                       FILE'CHECK = "OK"
       IF Z > 0 &
           THEN &
               IF LEN(FILE'NAME) > 0 AND LEN(FILE'NAME) <= 10 &
                   THEN &
                       FILE'CHECK = "OK"
       IF FILE'CHECK = "OK" &
           THEN &
               SOURCE'FILE = FILE'NAME
       FILE'NAME = ""
       RETURN

CHECK'INCLUDED'FILE'NAME:
       Z = 0
       Z = INSTR(1,INCLUDED'FILE,".")
       ! if there's no extension, add .BSI as the default
       IF Z = 0 &
           THEN &
               IF LEN(INCLUDED'FILE) >0 AND LEN(INCLUDED'FILE) <= 6 &
                   THEN &
                       INCLUDED'FILE = INCLUDED'FILE + ".BSI"
       RETURN

NO'INCLUDE'FILE'FOUND:
       ! first strip off the DSK0: and the PPN from the name
       Y = INSTR(1,INCLUDED'FILE,"[")
       INCLUDED'FILE = INCLUDED'FILE[6,(Y-1)]
       ! Tell the user about it on the screen
       CALL ON'TO'18
       ? TAB(20,1); TAB(-1,9);
       ? "%Cannot find included file: ";INCLUDED'FILE
       ! Send the name to the error file
       ? #3, INCLUDED'FILE
       RETURN

BOGUS'FILE'NAME:
       ? "I'm having a problem with the file you asked for. Perhaps"
       ? "you've misspelled the name, since I can't find it. Let's"
       ? "try it again."
       CALL PAUSE
       RETURN

ADD'PPN:
       EXTENSION = "[" + P + ",0]"
       INCLUDED'FILE = INCLUDED'FILE + EXTENSION
       CALL ON'TO'18
       RETURN

ADD'DSK0:
       Y = 0
       Y = INSTR(1,INCLUDED'FILE,"[")
       INCLUDED'FILE = INCLUDED'FILE[1,(Y-1)]
       INCLUDED'FILE = "DSK0:" + INCLUDED'FILE + "[7,6]"
       CALL ON'TO'18
       RETURN

READ'IN'INCLUDE'FILE'LINES:
       INCLUDE'COUNT = INCLUDE'COUNT + 1
       INPUT LINE #4, INCLUDED'TEXT'LINE
       IF EOF(4) # 1 &
           THEN &
               ? #2, INCLUDED'TEXT'LINE :&
               ? "."; :&
               GOTO READ'IN'INCLUDE'FILE'LINES
       RETURN

! ************************* LEVEL 4 *****************************

PAUSE:
       ? TAB(23,1);
       INPUT LINE " press RETURN to continue --> ", DUMMY
       RETURN

GET'PPN:
! getppn.bas returns to you the PPN number that you're logged in under.
!       This is a four stage process:
!         1. use the word(word) thing to get a decimal number that
!            represents your ppn.
!         2. divide by 256 to get P; AND with 255 to get the PN (both decimal)
!         3. Convert P to octal
!         4. convert PN to octal
!       If you plan to reproduce this, pay special attention to MAPping,
!       Most work variables used in the octal conversion are strings !

       PPN = word(word(78) + 16)
       P = INT(PPN/256)
       PN = PPN AND 255

       OCTAL = ""  : WORK = 0
       CONTINUE'CALC1:
           WORK = INT(P/8)
           OCTAL = VALID'DIGIT[1 + P - WORK * 8 ; 1] + OCTAL
           P = WORK
           IF P # 0 GOTO CONTINUE'CALC1
       P = OCTAL

       OCTAL = ""  : WORK = 0
       CONTINUE'CALC:
           WORK = INT(PN/8)
           OCTAL = VALID'DIGIT[1 + PN - WORK * 8 ; 1] + OCTAL
           PN = WORK
           IF PN # 0 GOTO CONTINUE'CALC
       PN = OCTAL
       RETURN

ON'TO'18:
       ? TAB(18,1); TAB(-1,9);
       ? "Searching for: "; INCLUDED'FILE
       RETURN

DISPLAY'STATISTICS:
       ? TAB(18,1); TAB(-1,10);
       ? INCLUDE'SEARCHES; "++INCLUDE statements were found in ";SOURCE'FILE;"."
       ? SUCCESSFUL'SEARCHES; "of those files were successfully found."
       ? SOURCE'COUNT; "lines were in the source program."
       ? INCLUDE'COUNT; "lines were in the INCLUDEd files."
       RETURN

! End of listing for FULIST.BAS