1	%TITLE  "FIXIT Utility for Old BASIC Programs"
	%SBTTL  "Declarations and Variable Directory"
	%IDENT  "FIXIT"

	OPTION TYPE = EXPLICIT	

        !          Author:	Tom Harris   August 1, 1983
	!			Digital Equipment Corp (ZK2-3/K06)
	!			110 Spit Brook Road
	!			Nashua, NH  USA     03062
        !	------------------------------------------------------------
        !          Input:    	an input file name, and conversion controls
	!		     	input can be BASIC-PLUS-2 V1.6 or MicroBASIC
	!		     	style programs. Keyboard input is allowed.
        !	------------------------------------------------------------
	!	    Output:  	a BASIC program, formatted for V2 BASIC
        !	------------------------------------------------------------
	!	    Support: 	Here it is, have fun, suggestions welcome,
	!		     	but no guarantees. <user-supported>
        !	------------------------------------------------------------
	!	    THIS IS A HANDOUT DEVELOPED FOR FALL US DECUS 1983
        !	------------------------------------------------------------
	DECLARE INTEGER CONSTANT					&
			 No_Tabs     = 16	! EDIT$	code		&
			,No_Blanks   = 424	! EDIT$	codes		&
			,Trim_Front  = 8	! EDIT$	code		&
			,Trim_Back   = 128	! EDIT$	code		&
			,TRUE        = -1

	DECLARE STRING CONSTANT	Break = "\"	! Backslash		&

	DECLARE STRING							&
			 DIMs.MAP(200)		! To move -> top/prog.	&
			,F.In			! Input file name	&
			,F.Out			! Output File Name	&
			,Main			! Working input buffer	&
			,Out			! Output line image	&
			,Source			! Input line image	&
			,S1 ,S2, S3		! Temp String		
	DECLARE	LONG							&
			 Bad.File		! Error on File OPEN	&
			,Comment.Column		! Comments to column x	&
			,DIMs.MAPs.Count	! Count DIM/MAPs 	&
			,TAB.Back		! Fixup indents w/this	&
			,First.Break		! THEN/ELSE/... tests	&
			,Endfile		! End-of-File flag	&
			,I			! General Use		&
			,IF.Count		! Nesting counter	&
			,Lines.In		! Counts # Lines input	&
			,Lines.Out		! Lines output		&
			,Loop.Count		! Loop nesting counter	&
			,MicroBASIC		! TRUE if a micro BASIC	&
			,MAP.DIM.Line.Number	! Line # for DIM/MAP's	&
			,Start.Time		! Seconds since 00:00	&
			,T1 ,T2, T3		! Temp working storage	&
			,TT.Output		! TRUE if F.Out="TT:"
	%PAGE


	!	The following flags are used by the uBASIC FUNCTION
	!	as a type of "OWN" storage, i.e. static storage
	!	that retains values between invocations. They are
	!	initialized to 0 as the main program starts running.

	!	The flags correspond to uBASIC statements or functions
	!	for which DEC BASIC functions or subroutines must
	!	be generated (i.e. no easy 1-1 transform exists).

	!	e.g. PRINT @128,"Hi"  becomes  PRINT AT(128);"Hi"

	!	and a BASIC function named AT has to be inserted
	!	into the front of the converted program.

	MAP (FLAGS) BYTE Action.Flag	! Caller must do something &
			,At_Flag 	! Output PRINT AT functn   &
			,MKS_Flag 	! Output MKS function      &
			,MKI_Flag 	! Output MKI function	   &
			,MKD_Flag 	! Output MKD function	   &
			,CVS_Flag 	! Output CVS function      &
			,CVI_Flag 	! Output CVI function	   &
			,CVD_Flag 	! Output CVD function	   &
			,INKEY_Flag	! Output INKEY$ function

	MAP (FLAGS) BYTE All_Flags(10)	! This makes initializing easier


	!	Below, we test the %VARIANT value (use the SET VARIANT command in the BASIC environment)
	!	to see whether we should minimize the size of this program by excluding HELP text and by
	!	skipping the call on UBASIC thus omitting that code from the executable program. Minimizing
	!	in this manner lets one run FIXIT on a PDP-11 system without having to overlay any code
	!	thus getting best possible performance.
	!
	!	The default is NOT to minimize. To request the smaller program:  SET VARIANT:1  before compiling
	!

	%LET   %Small  = 1%		! SET VARIANT = 1 when compiling, and the MicroBASIC code drops out,
	%LET   %Large  = 2%		! 	and then you don't have to overlay the translator

	%IF %VARIANT = 0%
	    %THEN
		%LET %Size = %Large
		EXTERNAL STRING FUNCTION uBASIC(STRING)	! This EXTERNAL happens only on %Large systems
	    %ELSE
		%LET %Size = %Small
	%END %IF
  %PAGE

	I = CTRLC
	ON ERROR GOTO Oops	

	GOTO Bye IF Bad.File	! Error Handler "OOPS" resumes here when unable to OPEN the *INPUT* file

	PRINT "FIXIT V1.0-AA ";TIME$(0)
	PRINT " "

  Begin_Processing:

	LINPUT "What input  file <TT:>  (? = HELP) ";F.In

	! Get an input file name, and append .BAS to it
	! as a default extension - unless the file name
	! might be a device spec, e.g. TT:  or  TTA3:

	F.In = EDIT$(F.In,No_Blanks)

	IF F.In = "?"
	THEN
	    GOSUB Help		
	    GOTO  Begin_Processing	
	END IF

	F.In = F.In + ".BAS"	IF (F.In <>"") AND 0=INSTR(1,F.In,".") AND 0=INSTR(1,F.In,":")
	F.In = "TT:"		IF LEN(F.In) = 0

	OPEN F.In FOR INPUT AS FILE #1, ACCESS READ, VARIABLE, RECORDSIZE 132

	LINPUT "What output file <TT:> ";F.Out

	! Do the same thing for the output file name

	F.Out = F.Out + ".BAS"	IF EDIT$(F.Out,No_Blanks)<>"" AND 0=INSTR(1,F.Out,".") AND 0=INSTR(1,F.Out,":")

	IF EDIT$(F.Out,No_Blanks)=""
	THEN
	    F.Out="TT:"  	
	    TT.Output = True
	END IF

	OPEN F.Out FOR OUTPUT AS FILE #2,VARIABLE, RECORDSIZE 132

	%PAGE

	MAP.DIM.Line.Number 	= 3	! Default: move MAP/DIM's to line "3"
	Comment.Column 		= 16	! Default: try to start comments in column 16
	DIMs.MAPs.Count 	= 0	! Global counter: tels how many DIM/MAP's saved up to move when program ends.

	All_Flags(I)		= 0	  FOR I = 0 to 10

	ON ERROR GOTO Hiccup

	LINPUT "Is this a Microprocessor BASIC Program <NO>";S1
	MicroBASIC = TRUE 		 IF EDIT$(Left(S1+"N",1),No_Blanks)="Y"

	LINPUT "Want to customize program conversion ? Answer Yes or No <N> ";S1

	IF EDIT$(LEFT(S1+"N",1),No_Blanks) = "Y"
	THEN
	    INPUT  "What line number should be used for moved DIM's and MAP's <3>";MAP.DIM.Line.Number
	    MAP.DIM.Line.Number = 3 IF MAP.DIM.Line.Number = 0
	
	    INPUT  "What column should be used to start comments in <16>";Comment.Column
	    Comment.Column = 16	IF Comment.Column < 2  OR  Comment.Column > 60

	    S1,S2,S3 = ""
	END IF

	Start.Time = TIME(0%)		! Start timing the conversion
	%PAGE
	%SBTTL "Main Loop"

  Main_Loop:

	WHILE TRUE

	     GOSUB DeBlock_Line  

	EXIT Main_Loop IF Endfile AND LEN(Main)=0

	     GOSUB ReBlock_Line 

	     Break.Lines:	

	        IF LEN(Out) > 132			!  This is where we break a line that is too long ...
		THEN
		    T1 = INSTR(78,Out,";")
		    T2 = INSTR(78,Out,",")		!  We'll break on a comma, semicolon, plus, AND, OR, or paren
		    T3 = INSTR(78,Out,"+")
		    T3 = INSTR(78,Out," AND ")  IF T3 = 0
		    T3 = INSTR(78,Out," OR ")   IF T3 = 0

		    T1 = T2	IF T1 = 0   OR   (T2<>0 AND T2<T1)
		    T1 = T3	IF T1 = 0   OR   (T3<>0 AND T3<T1)
		    T1 = INSTR(78,Out,")")	  IF T1 = 0

		    PRINT #2, MID(Out,1,T1)+"	&"
		    Lines.Out = Lines.Out + 1

		    Out = SPACE$(7)+EDIT$(RIGHT(Out,T1+1),Trim_Front)
		    GOTO Break.Lines
		ELSE
		    IF LEN(Out) <> 0
		    THEN
			PRINT #2, Out			!	Here, the line fits OK - no need to break it
		        Lines.Out = Lines.Out + 1	
		    END IF
		END IF

	    PRINT Lines.Out;  	IF Lines.Out = 100*INT(Lines.Out/100)  AND  NOT TT.Output ! Show progress...
	NEXT

	PRINT	IF TT.Output

	GOTO Done

	%PAGE
	%SBTTL  "HELP Text"

 Help:	PRINT " "
	%IF %Size = %Large
	%THEN
	        PRINT "	"
	        PRINT "	This program converts V1 BASIC programs to a  possibly  more"
	        PRINT "	readable  and  executable format under V2 BASIC.  It handles"
	        PRINT "	BASIC-PLUS-2 V1.x source as well as elements  of  MicroBASIC"
	        PRINT "	source code."
	        PRINT "	"
	        PRINT "	NOTE:  This is a sample  program  which  itself  illustrates"
	        PRINT "	capabilities  of  DEC BASIC.  The program has purposely been"
	        PRINT "	kept to a simple  no-brains  approach  -  it  does  not  use"
	        PRINT "	sophisticated parsing techniques and thus does not perfectly"
	        PRINT "	convert all  of  the  possible  program  formats  which  the"
	        PRINT "	BASIC's  allow.   However, it has proven useful for a number"
	        PRINT "	of different programs, and can no doubt be altered to handle"
	        PRINT "	even more."
	        PRINT "	"
	        PRINT "	The program moves MAPs and DIMs, changes REM  statements  to"
	        PRINT "	'!',  inserts  'END  IF'  statements  where  necessary,  and"
	        PRINT "	<incidentally> indents statement blocks to indicate  control"
	        PRINT "	structures while performing minor clean-ups on code."
	        PRINT "	"
	        PRINT "	You will be asked  for  input  and  output  file  names  and"
	        PRINT "	whether  you  wish  to supply customizing directions or take"
	        PRINT "	default processing parameters.  Input and Output file  names"
	        PRINT "	are  assumed  to have a .BAS extension, so you need not type"
	        PRINT "	it in (other extensions are permitted - just type 'em in!)."
	        PRINT "	"
	        PRINT "	You  will be  requested to  tell the FIXIT  program  whether"
	        PRINT "	the  input  text is in space-compressed MicroBASIC format so"
	        PRINT "	that expansions can be performed  (and  syntax  peculiar  to"
	        PRINT "	that implementation can be massaged into forms acceptable on"
	        PRINT "	this system."
	        PRINT "	"
	        PRINT "	Customizing means telling the FIXIT program whether to  move"
	        PRINT "	COMMON/DIMENSION/MAP statements and what line number to move"
	        PRINT "	them to (if you give a line  number  less  than  zero,  they"
	        PRINT "	won't  be moved - may be advisable if you have truly complex"
	        PRINT "	MAP or COMMON statements), you will be asked what column  to"
	        PRINT "	TRY  to align comments on (numbers between 8 and 70 are OK)."
	        PRINT "	"
	        PRINT "	The  program  then  runs,  reporting   each   100   <output>"
	        PRINT "	statements  processed.  Termination reporting tells how many"
	        PRINT "	input  statements  and  how  many  output  statements   were"
	        PRINT "	processed."
	        PRINT "	"
	%ELSE
		PRINT "Help Text is not available"
	%END %IF
  RETURN
	%PAGE
	%SBTTL  "Source Input Routine"

 DeBlock_Line:					! Return 1 stmt/line in *Source*

        Out,Source,S1,S2 = ""

	IF LEN(Main)=0 AND NOT Endfile 		! *Main* holds working text
	THEN
	    IF LEN(S3) = 0
	    THEN
		LINPUT  #1, Main	
		Lines.In = Lines.In + 1
		Main = EDIT$(Main,No_Blanks)

		%IF %Size = %Large
		%THEN
		    Main = uBASIC(Main)	IF MicroBASIC
		%END %IF

	    ELSE
		Main = S3
		S3 = ""
	    END IF
	END IF


   Handle.Continuation:

 	IF MID(Main,LEN(Main),1)="&"  		! Continuation lines -> *Main*
	THEN
	    T1 = INSTR(1,Main,"!")
	    Main  = EDIT$(LEFT(Main,LEN(Main)-1),Trim_Back)+" "

	    LINPUT #1, S1
	    S1    = EDIT$(S1,No_Blanks)
	    Lines.In = Lines.In + 1

	    IF T1= 0      
	    THEN
		S1    = Break+" "+S1		  IF LEFT(S1,1)="!" 
		Main  = Main + EDIT$(S1,Trim_Front)
		GOTO Handle.Continuation
	    ELSE
		S3 = S1
		S1 = ""
	    END IF
	END IF

	%PAGE

	T1    = INSTR(1,Main,Break)		! NOW, get a stmt into *Source*

	IF T1 <> 0
	THEN
	    Source = EDIT$(LEFT(Main,T1-1),Trim_Front)
	    Main   = EDIT$(RIGHT(Main,T1+1),Trim_Front) 
	    Main   = Break+Main	IF LEN(Source) <> 0
	    GOTO     DeBlock_Line  	IF LEN(Source) = 0
	ELSE
	    Source = EDIT$(Main,Trim_Front)
	    Main   = ""
	END IF
	
	T1 = INSTR(1,Source,"!")	! Break lines on THEN, ELSE and
	T2 = INSTR(1,Source,"THEN")	! work to avoid being fooled by
	T3 = INSTR(1,Source,"ELSE")	! comments containing THEN/ELSE

  RETURN  IF (T2 + T3) = 0		! <none of the above>

  RETURN  IF (T1<T2) AND (T1<T3) AND (T1<>0) ! <comment precedes the THEN or the ELSE>

	First.Break = 999		! Aha, something(s).. pick first one

	First.Break = T2 IF T2 <> 0 AND T2 < First.Break AND ( (T1 = 0) OR (T1<>0 AND T2<T1) )
	First.Break = T3 IF T3 <> 0 AND T3 < First.Break AND ( (T1 = 0) OR (T1<>0 AND T3<T1) )
	
	S1     = EDIT$(LEFT( Source,First.Break-1),Trim_Front)
	Main   = EDIT$(RIGHT(Source,First.Break  ),Trim_Front)+" "+Main
	Source = S1

	IF LEN(Source) = 0 			! Handle THEN or ELSE in Column 1
	THEN
	    S1     = LEFT(Main,4)
	    Main   = EDIT$(RIGHT(Main,5),Trim_Front)
	    Main   = "GOTO " + Main 	IF 0 <> INSTR(1,"0123456789",LEFT(Main,1)) AND LEN(Main) <> 0
	    Source = S1
	END IF

  RETURN

   	%PAGE
	%SBTTL  "Output Editing Subroutine"

  ReBlock_Line:					! Do pretty tabs & text fixups...

	    Source = EDIT$(Source,Trim_Back)
  RETURN    IF LEN(Source) = 0

	    T1 = INSTR(1,Source,"!")		! Handles RSTS CUSP convention
	    S1 = EDIT$(Left(Source,T1-1),Trim_Back+No_Tabs)
	    T3 = LEN(S1)

	    Source = S1+SPACE$(Comment.Column-T3) + RIGHT(Source,T1)  IF T1<Comment.Column AND T1>0

	    S1 	   = LEFT(Source,1)
	    T1 	   = ASCII(S1)
	    S2     = ""

	    SELECT T1					! Look for Line numbers
		CASE 48,49,50,51,52,53,54,55,56,57	! Start text in column 9

		    T2  = INSTR(1,Source," ")	! Space
		    T3  = INSTR(1,Source,"	")	! TAB

		    T2  = T3 		IF  (T2 = 0)
		    T2  = T3		IF  (T3 > 0) AND (T3 < T2)
		    T2  = LEN(Source)+1 	IF T2 = 0

		    Out = LEFT(Source,T2-1) + SPACE$(8-T2) + EDIT$(RIGHT(Source,T2),Trim_Front)

		    Out = Out + "!"		IF T2 = LEN(Source)+1

		    IF IF.Count > 0
		    THEN
			PRINT #2, SPACE$(7+4*(Loop.Count+(IF.Count-I)));"END IF" FOR I=1 TO IF.Count
			Lines.Out = Lines.Out + IF.Count 	
			IF.Count = 0
		    END IF

		CASE ELSE
		    Out = SPACE$(7)+EDIT$(Source,Trim_Front)
	    END SELECT

	    ! *WHEW* BASIC source in col-8
	    ! Now, do fixups...

	    Out = LEFT(Out,7)+"! "+EDIT$(RIGHT(Out,12),Trim_Front)  IF MID(Out,8,3)="REM"
	    Out = LEFT(Out,7)     +EDIT$(RIGHT(Out,12),Trim_Front)  IF MID(Out,8,3)="LET"

	    %PAGE
	    %SBTTL "Pretty Print Formatting"

	    Loop.Count = Loop.Count - 1 IF MID(Out,8,4)="NEXT"
	    Loop.Count = 0		IF Loop.Count < 0

	    IF.Count = IF.Count - 1  	IF 0 <> INSTR(1,Out,"END IF") AND IF.Count > 0
	    IF.Count = 0		IF IF.Count < 0

	    T1  = INSTR(1,Out,"ELSE")
	    T3  = INSTR(1,Out,"!")

	    TAB.Back = 0		! <make it appear same level as IF>
	    TAB.Back = 1		IF T1 > 0 AND ((T3=0) OR (T3<>0 AND T1<T3))

	    S2  = Out

	    Out = LEFT(Out,7) + SPACE$(4*(IF.Count-TAB.Back)) + SPACE$(4*Loop.Count) + RIGHT(Out,8)

	    T3  = INSTR(1,Out,"!")	! Try to Center comments...
	    S1  = EDIT$(Left(Out,T3-1),Trim_Back)
	    T2  = LEN(S1)

	    Out = S1+SPACE$(Comment.Column-T2)+EDIT$(RIGHT(Out,T3),Trim_Front) IF T3<Comment.Column AND T3>0

	    T1  = INSTR(1,Source,"!") 	! Key off THEN (not stmt modifier)
	    T2  = INSTR(1,Source,"THEN")

	    IF.Count = IF.Count + 1 	IF T2<>0 AND (T1=0 OR (T1<>0 AND T2<T1))

	    Loop.Count = Loop.Count + 1 IF MID(S2,8,4)="FOR "
	    Loop.Count = Loop.Count + 1 IF MID(S2,8,6)="UNLESS"
	    Loop.Count = Loop.Count + 1 IF MID(S2,8,5)="UNTIL"
	    Loop.Count = Loop.Count + 1 IF MID(S2,8,5)="WHILE"

	    %PAGE
	    %SBTTL "Handle COMMON/DIM/MAP Statements"

	    T1  = MID(S2,8,3)="DIM"	! Test for DIMension
	    T2  = MID(S2,8,3)="MAP"	! Test for MAP
	    T3  = MID(S2,8,3)="COM"	! Test for COMMON

  RETURN    IF T1+T2+T3 = 0  OR  MAP.DIM.Line.Number < 0

	    S1 = LEFT(Out,7)
	    Out= EDIT$(RIGHT(Out,8),16+128+256+8)

	    I  = INSTR(1,Out,",")

	    IF  I <> 0 AND T1=0
	    THEN
		DIMs.MAPs.Count = DIMs.MAPs.Count + 1
		DIMs.MAP(DIMs.MAPs.Count) = SPACE$(7)+LEFT(Out,I)+SPACE$(58-I)+" &"
		Out = EDIT$(RIGHT(Out,I+1),Trim_Front)

	    Find.Comma:

		I = INSTR(1,Out,",")
		IF I > 0
		THEN
		    GOSUB Add.Item
		    GOTO Find.Comma
		END IF

		DIMs.MAPs.Count = DIMs.MAPs.Count + 1
		DIMs.MAP(DIMs.MAPs.Count) = SPACE$(15)+Out
	    ELSE
		DIMs.MAPs.Count = DIMs.MAPs.Count + 1
		DIMs.MAP(DIMs.MAPs.Count) = SPACE$(7)+Out
	    END IF

	    Out = LEFT(S1,7)+SPACE$(Comment.Column-7)+"! ** MOVED COMMON, DIM, or MAP ** "

  RETURN


  Add.Item:
	    DIMs.MAPs.Count = DIMs.MAPs.Count + 1

	    DIMs.MAP(DIMs.MAPs.Count) = SPACE$(15) + 			   &
					EDIT$(LEFT(Out,I),Trim_Front)+     &
					SPACE$(50-I)+" &"

	    Out = EDIT$(RIGHT(Out,I+1),Trim_Front)

  RETURN
	
	%PAGE 
	%SBTTL  "Exception Handling and Program Termination Code"

  Hiccup:	Endfile = TRUE
	 	PRINT					IF F.Out <> "TT:"
	 	PRINT ERT$(ERR);" Error ";ERR 		IF ERR <> 11
  RESUME  9

  Oops:		PRINT "Sorry, unable to open that file, program ends"
		Bad.File = TRUE
  RESUME  1

9	!
	
  Done:	
	IF IF.Count > 0				! Put any pending END IF's
	THEN
	    PRINT #2, SPACE$(7+4*(IF.Count-I));"END IF" FOR I=1 TO IF.Count
	    Lines.Out = Lines.Out + IF.Count 	
	END IF

	IF DIMs.MAPs.Count <> 0			! Also, dump the DIM/MAP's
	THEN
	    PRINT #2, NUM1$(MAP.DIM.Line.Number);TAB(Comment.Column); "! ** COMMON, DIM, and MAP's have been moved here ** "
	    PRINT #2, DIMs.MAP(I) FOR I = 1 TO DIMs.MAPs.Count
	    Lines.Out = Lines.Out + DIMs.MAPs.Count + 1	
	END IF

	%PAGE
	%SBTTL  "Generated DEF's (for MicroBASIC Operations)"

    %IF %Size = %Large
    %THEN

	All_Flags(10) = All_Flags(10) + All_Flags(I) 	FOR I = 1 TO 9

	IF All_Flags(10) <> 0
	THEN
	    PRINT
	    PRINT #2, "4";TAB(Comment.Column);"! ** Added functions here **"
	    PRINT     "Added Line 4 (";	IF F.Out <> "TT:"

	    IF CVI_Flag   <> 0%
	    THEN
		PRINT " CVI";	IF F.Out <> "TT:"
		PRINT #2,  "	DEF WORD CVI(STRING CVI_IN)"
		PRINT #2,  "		MAP (CVIMAP) STRING CVI_STRING = 2"
		PRINT #2,  "		MAP (CVIMAP) WORD   CVI_WORD"
		PRINT #2,  ""
		PRINT #2,  "		CVI_STRING = CVI_IN"
		PRINT #2,  "		CVI        = CVI_WORD"
		PRINT #2,  "	END DEF"
		PRINT #2,  ""
	    	Lines.Out = Lines.Out + 8
	    END IF

	    IF CVS_Flag   <> 0
	    THEN
		PRINT " CVS";	IF F.Out <> "TT:"
		PRINT #2,  "	DEF SINGLE CVS(STRING CVS_IN)"
		PRINT #2,  "		MAP (CVSMAP) STRING CVS_STRING = 4"
		PRINT #2,  "		MAP (CVSMAP) SINGLE CVS_SINGLE"
		PRINT #2,  ""
		PRINT #2,  "		CVS_STRING = CVS_IN"
		PRINT #2,  "		CVS        = CVS_SINGLE"
		PRINT #2,  "	END DEF"
		PRINT #2,  ""
	    	Lines.Out = Lines.Out + 8
	    END IF

	    IF CVD_Flag   <> 0
	    THEN
		PRINT " CVD";	IF F.Out <> "TT:"
		PRINT #2,  "	DEF SINGLE CVD(STRING CVD_IN)"
		PRINT #2,  "		MAP (CVDMAP) STRING CVD_STRING = 8"
		PRINT #2,  "		MAP (CVDMAP) SINGLE CVD_DOUBLE"
		PRINT #2,  ""
		PRINT #2,  "		CVD_STRING = CVD_IN"
		PRINT #2,  "		CVD        = CVD_DOUBLE"
		PRINT #2,  "	END DEF"
		PRINT #2,  ""
	    	Lines.Out = Lines.Out + 8
	    END IF
	    %PAGE

	    IF MKI_Flag   <> 0
	    THEN
		PRINT " MKI";	IF F.Out <> "TT:"
		PRINT #2,  "	DEF STRING MKI(WORD MKI_IN)"
		PRINT #2,  "		MAP (MKIMAP) STRING MKI_STRING = 2"
		PRINT #2,  "		MAP (MKIMAP) WORD   MKI_WORD"
		PRINT #2,  ""
		PRINT #2,  "		MKI_WORD = MKI_IN"
		PRINT #2,  "		MKI        = MKI_STRING"
		PRINT #2,  "	END DEF"
		PRINT #2,  ""
	    	Lines.Out = Lines.Out + 8
	    END IF

	    IF MKS_Flag   <> 0
	    THEN
		PRINT " MKS";	IF F.Out <> "TT:"
		PRINT #2,  "	DEF STRING MKS(SINGLE MKS_IN)"
		PRINT #2,  "		MAP (MKSMAP) STRING MKS_STRING = 4"
		PRINT #2,  "		MAP (MKSMAP) SINGLE MKS_SINGLE"
		PRINT #2,  ""
		PRINT #2,  "		MKS_SINGLE = MKS_IN"
		PRINT #2,  "		MKS        = MKS_STRING"
		PRINT #2,  "	END DEF"
		PRINT #2,  ""
	    	Lines.Out = Lines.Out + 8
	    END IF

	    IF MKD_Flag   <> 0
	    THEN
		PRINT " MKD";	IF F.Out <> "TT:"
		PRINT #2,  "	DEF STRING MKD(DOUBLE MKD_IN)"
		PRINT #2,  "		MAP (MKDMAP) STRING MKD_STRING = 8"
		PRINT #2,  "		MAP (MKDMAP) SINGLE MKD_DOUBLE"
		PRINT #2,  ""
		PRINT #2,  "		MKD_DOUBLE = MKD_IN"
		PRINT #2,  "		MKD        = MKD_STRING"
		PRINT #2,  "	END DEF"
		PRINT #2,  ""
	    	Lines.Out = Lines.Out + 8
	    END IF

	    IF At_Flag <> 0 
		THEN
		PRINT     " AT";	IF F.Out <> "TT:"
	      	PRINT #2, "	 DEF STRING  At( WORD At.Line, At.Column) = ESC + '[' + NUM1$(At.Line)+';'+NUM1$(At.Column)+'f'"
	      	PRINT #2, "	 DEF STRING CLS( WORD CLS.Line, CLS.Column) = AT(CLS.Line,CLS.Column) + Clear.Below"
	      	PRINT #2, "	"
	    	Lines.Out = Lines.Out + 3
	    END IF
	    %PAGE

	    IF INKEY_Flag <> 0
	    THEN
	 	PRINT     " INKEY";	IF F.Out <> "TT:"
		PRINT #2, "	%PAGE"
		PRINT #2, "	%SBTTL  'Keyboard Input Routine (VMS Only)' "

	      	PRINT #2, "	EXTERNAL LONG CONSTANT                                          &"
	      	PRINT #2, "	                 IO$_READVBLK                          		&"
	      	PRINT #2, "	                ,IO$M_NOECHO					&"
		PRINT #2, "                     ,SS$_NORMAL"
	      	PRINT #2, ""

	      	PRINT #2, "	EXTERNAL LONG FUNCTION SYS$ASSIGN ( 				&"
		PRINT #2, "                      STRING BY DESC              		 	&"
	      	PRINT #2, "	                ,WORD   BY REF                         		&"
	      	PRINT #2, "	                ,LONG   BY VALUE                       		&"
	      	PRINT #2, "	                ,LONG   BY VALUE  )"
	      	PRINT #2, ""

	      	PRINT #2, "	EXTERNAL LONG FUNCTION SYS$QIOW (   				&"
		PRINT #2, "			 LONG   BY VALUE                       		&"
	      	PRINT #2, "	                ,WORD   BY VALUE                       		&"
	      	PRINT #2, "	                ,LONG   BY VALUE                       		&"
	      	PRINT #2, "	                ,LONG   BY REF                         		&"
	      	PRINT #2, "	                ,LONG   BY REF                         		&"
	      	PRINT #2, "	                ,LONG   BY VALUE                       		&"
	      	PRINT #2, "	                ,WORD   BY REF                         		&"
	      	PRINT #2, "	                ,LONG   BY VALUE                       		&"
	      	PRINT #2, "	                ,LONG   BY VALUE                       		&"
	      	PRINT #2, "	                ,LONG   BY REF                         		&"
	      	PRINT #2, "	                ,LONG   BY REF                         		&"
	      	PRINT #2, "	                ,LONG   BY VALUE  )"
	      	PRINT #2, ""

	      	PRINT #2, "	DECLARE STRING CONSTANT                                         &"
	      	PRINT #2, "	                 Clear.Screen   = ESC + '[2J'                   &"
	      	PRINT #2, "	                ,Clear.Below    = ESC + '[0J'                   &"
	      	PRINT #2, "	                ,Clear.Right    = ESC + '[K'                    &"
	      	PRINT #2, "	                ,Clear.Line     = ESC + '[2K'                   &"
	      	PRINT #2, "	                ,Col.132        = ESC + '[?3h'                  &"
	      	PRINT #2, "	                ,Black.Screen   = ESC + '[?5l'                  &"
	      	PRINT #2, "	                ,Normal.Chars   = ESC + '[0m'                   &"
	      	PRINT #2, "	                ,Bold.Chars     = ESC + '[1m'                   &"
	      	PRINT #2, "	                ,Reverse.Chars  = ESC + '[7m'                   &"
	      	PRINT #2, "	                ,Underscore.On  = ESC + '[4m'                   &"
	      	PRINT #2, "	                ,Blink          = ESC + '[5m'                   &"
	      	PRINT #2, "	                ,Scroll.Down    = ESC + 'M'"
	      	PRINT #2, ""
		%PAGE
	      	PRINT #2, "	DECLARE  INTEGER CONSTANT                                       &"
	      	PRINT #2, "	                  True          =  -1                           &"
	      	PRINT #2, "	                 ,False         =   0                           &"
	      	PRINT #2, "	                 ,Up            =   1                           &"
	      	PRINT #2, "	                 ,Down          =   0                           &"
	      	PRINT #2, ""

	      	PRINT #2, "	DECLARE STRING                                                  &"
	      	PRINT #2, "	                  Hold.Value                                    &"
	      	PRINT #2, "	                 ,Key.Value                                     &"
	      	PRINT #2, "	                 ,Key.Pad                                       &"
	      	PRINT #2, "	                 ,Text"
	      	PRINT #2, ""

	      	PRINT #2, "	DECLARE WORD                                                    &"
	      	PRINT #2, "	                  Chan                                          &"
	      	PRINT #2, "	                 ,QIO.Char                                      &"
	      	PRINT #2, "	                 ,Direction                                     &"
		PRINT #2, ""

	      	PRINT #2, "	DECLARE LONG                                                    &"
	      	PRINT #2, "	                  S.Status                                      &"
	      	PRINT #2, ""

	      	PRINT #2, "	%PAGE"
	      	PRINT #2, "	%SBTTL  'Keypad (One Character) Input Function'"
	      	PRINT #2, "	DEF STRING InKey"
	      	PRINT #2, "	    DECLARE BYTE  Arrow.Key"
	      	PRINT #2, "	    S.Status = SYS$ASSIGN('TT',Chan,,)        ! <ready for QIOs>"
	      	PRINT #2, "	    PRINT 'ERROR ON SYS$ASSIGN '  IF S.Status <> SS$_NORMAL"
	      	PRINT #2, "	    Arrow.Key = False"
	      	PRINT #2, "	    Key.Pad   = CHR$(0)"
	      	PRINT #2, ""
	      	PRINT #2, "	 C1: WHILE TRUE"
	      	PRINT #2, "	        S.Status = SYS$QIOW(                                       &"
	      	PRINT #2, "	                  ,Chan                                            &"
	      	PRINT #2, "	                  ,(IO$_READVBLK OR IO$M_NOECHO)                   &"
	      	PRINT #2, "	                  ,                                                &"
	      	PRINT #2, "	                  ,                                                &"
	      	PRINT #2, "	                  ,                                                &"
	      	PRINT #2, "	                  ,QIO.Char                                        &"
	      	PRINT #2, "	                  ,1%                                              &"
	      	PRINT #2, "	                  ,                                                &"
	      	PRINT #2, "	                  ,                                                &"
	      	PRINT #2, "	                  ,                                                &"
	      	PRINT #2, "	                  ,                                                &"
	      	PRINT #2, "	                          )"
	      	PRINT #2, "	    	PRINT 'ERROR ON SYS$QIOW' IF S.Status <> SS$_NORMAL"
	      	PRINT #2, "	        Arrow.Key = True       	  IF QIO.Char = 27 AND Arrow.Key = False"
	      	PRINT #2, "	        EXIT C1                   IF NOT Arrow.Key"
	      	PRINT #2, "	        ITERATE C1                IF QIO.Char = ASCII('[') OR QIO.Char = ASCII('O')"
	      	PRINT #2, ""
	      	PRINT #2, "	        IF QIO.Char <> ASCII('[') AND QIO.Char <> 27"
	      	PRINT #2, "	        THEN"
	      	PRINT #2, "	                SELECT QIO.Char"
	      	PRINT #2, "	                    CASE 65"
	      	PRINT #2, "	                        QIO.Char = ASCII('{')   !  ESC [ A  is up-arrow"
	      	PRINT #2, "	                    CASE 66"
	      	PRINT #2, "	                        QIO.Char = ASCII('v')   !  ESC [ B  is down-arrow"
	      	PRINT #2, "	                    CASE 67"
	      	PRINT #2, "	                        QIO.Char = ASCII('>')   !  ESC [ C  is right-arrow"
	      	PRINT #2, "	                    CASE 68"
	      	PRINT #2, "	                        QIO.Char = ASCII('<')   !  ESC [ D  is left-arrow"
	      	PRINT #2, "	                    CASE ELSE"
	      	PRINT #2, "	                        Key.Pad  = CHR$(QIO.Char)"
	      	PRINT #2, "	                        QIO.Char = ASCII('?')   !  ESC [ other  is probably a keypad key"
	      	PRINT #2, "	                END SELECT"
	      	PRINT #2, "	        EXIT C1"
	      	PRINT #2, "	        END IF"
	      	PRINT #2, "	    NEXT"
	      	PRINT #2, "	    InKey = CHR$(QIO.Char)"
	      	PRINT #2, "	    CALL SYS$DASSGN (Chan BY VALUE)"
	      	PRINT #2, "	 END DEF"
	      	PRINT #2, "	 %PAGE"
	      	PRINT #2, "	 %SBTTL  'Program Text...'"
	    	Lines.Out = Lines.Out + 113
		END IF
	    PRINT " )"	IF F.Out <> "TT:"
	END IF
    %END %IF
    %PAGE
    %SBTTL "Program Termination and Statistics"

	CLOSE #2
	CLOSE #1
	
	I = TIME(0%)				!  Compute elapsed <wall> time

	IF Start.Time < I
	THEN
	    I = I - Start.Time		 	!  Daytime run
	ELSE				
    	    I = I + (24*60*60 - Start.Time)	!  Midnight run
	END IF

	PRINT
	PRINT   "("; NUM1$(Lines.In); ") Input Lines from " ; F.In ; ", ("; &
			NUM1$(Lines.Out) ; ") lines written to " ; F.Out

	PRINT   "("; NUM1$(DIMs.MAPs.Count);") lines of DIM and MAP statements moved."

	PRINT   "("+NUM1$(I)+")Seconds elapsed time ... ("+NUM1$(Lines.In/(I/60))+") lines/minute"

 Bye:	
	END

400 %SBTTL "Fixup MicroBASIC Funnies"
	
    FUNCTION STRING uBASIC(STRING Source)

	OPTION TYPE = EXPLICIT

	DECLARE LONG CONSTANT	TRUE = -1
	DECLARE LONG 		I, J, K, T1, T2, T3, T4, T5, Action_Code, X
	DECLARE STRING  	Keyword, New.word, S1, S2

	!	The following flags are used by the uBASIC FUNCTION
	!	as a type of "OWN" storage, i.e. static storage
	!	that retains values between invocations. They are
	!	initialized to 0 as the main program starts running.

	!	The flags correspond to uBASIC statements or functions
	!	for which DEC BASIC functions or subroutines must
	!	be generated (i.e. no easy 1-1 transform exists).

	!	e.g. PRINT @128,"Hi"  becomes  PRINT AT(128);"Hi"

	!	and a BASIC function named AT has to be inserted
	!	into the front of the converted program.

	MAP (FLAGS)   	BYTE  	 Action.Flag	! Caller must do something &
				,At_Flag 	! Output PRINT AT functn   &
				,MKS_Flag 	! Output MKS function      &
				,MKI_Flag 	! Output MKI function	   &
				,MKD_Flag 	! Output MKD function	   &
				,CVS_Flag 	! Output CVS function      &
				,CVI_Flag 	! Output CVI function	   &
				,CVD_Flag 	! Output CVD function	   &
				,INKEY_Flag	! Output INKEY$ function

	MAP (FLAGS)	BYTE	All_Flags(10)	! This makes initializing easier

	GOTO Colon         	IF LEN(Source) = 0     ! White Space

	GOSUB Lin.Num		IF 0 <> INSTR(1,"0123456789",LEFT(Source,1))

	GOTO Set  		IF "REM" = LEFT(EDIT$(RIGHT(Source,J),-1),3)
	RESTORE

	%PAGE
	!	Here, we read from a table of DATA statements, looking for transforms
	!	to perform on the line of text sent into this FUNCTION. The table consists
	!	of:  thing-to-find, thing-to-change-to, and a special-action-code. The
	!	BASIC function INSTR does the lookup. The action code simply tells us
	!	to set one of the flags checked by the calling main program as it
	!	determines whether to emit DEF's at the end of the program being translated.

  Look: WHILE TRUE
            READ Keyword, New.Word, Action_Code
	EXIT Look       IF Keyword = "..."
	    I = 1
          Again:  
	    WHILE TRUE
		I =  INSTR(I,Source,Keyword)		!	The lookup

	ITERATE Look    	IF I = 0		!	<unsuccessful>
		J = INSTR(1,Source,'"')			!	<success - possibly..>	
		K = INSTR(J+1,Source,'"')		!	     its no success if the find is inside a literal
	    EXIT Again		IF J<I AND K>I		!	     in that case, ignore the find. EXIT off end-of-line

		SELECT Action_Code			!	<find>
		  CASE 0				! 		No Special Action Needed
		  CASE 1,2,3,4,5,6,7,8		  	!		Need action: set a flag 
			All_Flags(Action_Code)  = 1
			Action.Flag		= 1	!		and the flag that says "some flags are set"
		  CASE ELSE				! 
		END SELECT

                Source = LEFT(Source,I-1) + New.Word+ RIGHT(Source,I+Len(Keyword))	! <insert the change-to text>
		I      = I + LEN(New.Word)						! ... and scan for next word 
		NEXT
            NEXT
  Colon: 					!  Lets turn colon-within-literal into a dash
	    I = INSTR(1,Source,':"')		!       <inelegant trick>
	    Source = MID(Source,1,I-1)+"-"+MID(Source,I+1,LEN(Source)-I) IF I <> 0
            GOTO Colon                      	IF I <> 0

	    I = INSTR(1,Source,': "')		!  ditto, for colon-space  into a dash
	    Source = MID(Source,1,I-1)+"-"+MID(Source,I+1,LEN(Source)-I) IF I <> 0
            GOTO Colon                      	IF I <> 0

	    I = INSTR(1,Source,":")		!  If we see just a colon, that turns into a backslash

	    Source = LEFT(Source,I-1)+"\"+RIGHT(Source,I+1) IF I <> 0
            GOTO Colon                      		    IF I <> 0

	    T1 = INSTR(1,Source," IF ")
	    T2 = INSTR(1,Source," THEN ")	IF T1 <> 0

	    GOSUB Fix.IF			IF (T1 <> 0) AND (T2 = 0)	! special handling for IF and OPEN
	    GOSUB Fix.OPEN			IF 0  <> INSTR(1,Source,"OPEN")
	    GOSUB Print.At			IF 0  <> INSTR(1,Source,"@")	! and for PRINT @ to PRINT AT
	Set:
	    Source = EDIT$(Source,8+16+32+128+256)				! discard any junk characters
	    uBASIC = Source							! and exit: this line is done.
  EXIT FUNCTION
  %PAGE
	%SBTTL "Fixup MicroBASIC Syntax for DEC Systems"
	Lin.Num: J = 0				! inserts white space to the right of BASIC line numbers
	L.Scan:	
	    FOR I=2 TO LEN(Source)
	    	IF 0=INSTR(1,"0123456789",MID(Source,I,1))
	    	THEN
		    J = I
		    EXIT L.Scan
		END IF
	    NEXT I
	Source = Left(Source,J-1)+" "+RIGHT(Source,J)	IF J <> 0
  RETURN

  Fix.IF:
	J  = T1				!  some variants of IF omit the keyword "THEN"
	T1 = INSTR(J,Source,"GO")
	T2 = INSTR(J,Source,"PRINT")
	T3 = INSTR(J,Source,"INPUT")
	T4 = INSTR(J,Source,"LET")

	T5 = 999

	T5 = T1 			IF T1 < T5 AND T1 <> 0
	T5 = T2				IF T2 < T5 AND T2 <> 0
	T5 = T3				IF T3 < T5 AND T3 <> 0
	T5 = T4				IF T4 < T5 AND T4 <> 0

	Source = LEFT(Source,T5-1)+" THEN "+RIGHT(Source,T5) IF T5 <> 999	! insert a THEN if its needed
  RETURN

  Fix.OPEN:				! the MicroBASIC OPEN has the right kind of components,
	T1 = INSTR(1,Source,'"O"')	!  OPEN FOR OUTPUT   and
	T2 = INSTR(1,Source,'"I"')	!  OPEN FOR INPUT    ... its just the spelling and the ordering...
  RETURN     IF T1+T2 = 0

	S2 = "FOR INPUT"
	S2 = "FOR OUTPUT"		IF T1 <> 0
	T1 = T2				IF T2 <> 0 AND T1 = 0

	T3 = INSTR(T1,Source,",")	!  pickup the channel number
	S1 = " AS FILE #" + MID(Source,T3+1,1)

	T3 = INSTR(T3+1,Source,",")

	T2 = INSTR(T3,Source,"\")	! and the file name
	T4 = INSTR(T3,Source,"ELSE")
	T2 = T4				IF T4<T2 AND T4<>0
	T2 = LEN(Source)+1		IF T2 =  0

	S1 = MID(Source, T3+1, T2-T3-1) + " " + S2 + S1

	Source = LEFT(Source,T1-1)+S1+RIGHT(Source,T2) ! and output a DEC-style OPEN statement
  GOTO  FIX.OPEN
  %PAGE

  Print.At:		! careful here, there are several variations of PRINT-at

	I = INSTR(1,Source,"@")				!  Typical use ...
	J = INSTR(I,Source,",")				!  PRINT @255+13,"Hello"
	J = INSTR(I,Source,";")		IF J = 0	!  PRINT @255+13;"Hello" 
							!        I      J
  RETURN 				IF J=0

	Source = LEFT(Source,I-1) + "AT(" + MID(Source,I+1,J-I-1) + ");"+RIGHT(Source,J+1)

	At_Flag 	=  TRUE
	Action.Flag 	=  TRUE
  RETURN

  %PAGE
	%SBTTL  "Conversion DATA Tables"

	!	GENERAL TABLE FORMAT IS SIMPLY...
	!
	!       <find this>	, <change to this>				, Additional Action Code
	!
	!
1000    DATA    "AND"      	,  " AND "					, 0
1050    DATA    "OR"       	,  " OR "					, 0
1100	DATA	"'"	   	,  " ! "					, 0
1150	DATA	"&"	   	,  " PRINT"					, 0
1160    !
1200	DATA	"/BAS"     	,  ".BAS"					, 0
1250	DATA	"/DAT"     	,  ".DAT"					, 0
1300	!
2000	!
2200    DATA    "CLEAR"    	,  " ! *CLEAR* "				, 0
2250    DATA    "CLOSE"    	,  " CLOSE "					, 0
2295	DATA	"CLR$"	   	,  "C.LR$"					, 0
2300    DATA    "CLR"      	,  " PRINT FOR CLR. = 1 TO 24 ! *CLR* "		, 0
2350    DATA    "CLS"      	,  " PRINT FOR CLS. = 1 TO 24 ! *CLS* "		, 0
2360    DATA    "CMD"      	,  " PRINT '*CMD*' ! "				, 0
2370	DATA	"CVI"	   	,  "CVI"					, 6
2380	DATA	"CVS"	   	,  "CVS"					, 5
2390	DATA	"CVD"	   	,  "CVD"					, 7
2440	!
2450    DATA    "DATA"     	,  " DATA "					, 0
2500    DATA    "DEFDBL"   	,  " ! DECLARE DOUBLE ( *DEFDBL* ) "		, 0
2550    DATA    "DEFN"    	,  " ! (*DEFFN*)  "				, 0
2600    DATA    "DEFINT"   	,  " ! DECLARE WORD   ( *DEFINT* ) "		, 0
2650    DATA    "DEFSNG"   	,  " ! DECLARE SINGLE ( *DEFSNG* ) "		, 0
2700    DATA    "DEFUSR"   	,  " ! (*DEFUSR*) "				, 0
2750    DATA    "DEFSTR"   	,  " ! DECLARE STRING ( *DEFSTR* ) "		, 0
2800    DATA    "DELETE"   	,  " DELETE "					, 0
2850    DATA    "DIM"      	,  " DIM "					, 0
2855	!				
2900    DATA    "ELSE"     	,  " ELSE "					, 0
2925	DATA	"WEND"     	,  " NEXT "					, 0
2950    DATA    "END"      	,  " END "					, 0
3000    DATA    "ERROR"    	,  " ERROR "					, 0
3005	!
3050    DATA    "FIELD"    	,  " FIELD ! *FIELD* ! "			, 0
3100    DATA    "FOR"      	,  " FOR "					, 0
3105	!
3110	DATA	" F OR "   	,  " FOR "					, 0
3150    DATA    "GET"      	,  " GET "					, 0
3200    DATA    "GOSUB"    	,  " GOSUB "					, 0
3250    DATA    "GOTO"     	,  " GOTO "					, 0
3255	!
3300    DATA    "IF"       	,  " IF "					, 0
3350    DATA    "INKEY$"   	,  " INKEY"					, 8
3360    DATA    "INPUT"    	,  " INPUT "					, 0
3375	!
3400    DATA    "KILL"     	,  " KILL "					, 0
3405	!
3425    DATA    "LET"      	,  " LET "					, 0
3450    DATA    "LSET"     	,  " LSET "					, 0
3500    DATA    "RSET"     	,  " RSET "					, 0
3550    DATA   "LINE INPUT"	,  " LINPUT "					, 0
3555	!
3600	DATA    "MAX"      	,  "MAXI"					, 0
3605	DATA	"MKI$"     	,  "MKI"					, 3
3610	DATA	"MKS$"     	,  "MKS"					, 2
3615	DATA	"MKD$"     	,  "MKD"					, 4
3645	!
3650    DATA    "NAME"     	,  " NAME "					, 0
3700    DATA    "NEXT"     	,  " NEXT "					, 0
3705	!
3800	DATA    "F OR"    	,  " FOR"					, 0
3850    DATA    "OPEN"     	,  " OPEN "					, 0
3860	DATA	"OPTION"   	,  " ! OPTION "					, 0
3900    DATA    "OUT"      	,  " ! *OUT* "					, 0
3905	!
3950	DATA    "PEEK"     	,  "  ! *PEEK* ! '?' * "			, 0
4000    DATA    "POKE"     	,  "? ! *POKE* "				, 0
4050    DATA    "PRINT"    	,  "PRINT "					, 0
4060	DATA	"WIDTH LPRINT"	, "MARGIN #9, "					, 0
4100	DATA    "LPRINT"   	,  " PRINT #9,"					, 0
4150	DATA	"PUT"	   	,  "PUT "					, 0
4155	!
4200    DATA    "RANDOM"   	,  " RANDOM "					, 0
4250	DATA	"RANDOM IZE"	, " RANDOMIZE "					, 0
4300    DATA    "READ"     	,  " READ "					, 0
4350    DATA    "REM"      	,  "\ REM "					, 0
4400    DATA    "RESET"    	,  " RESET "					, 0
4450    DATA    "RESTORE"  	,  " RESTORE "					, 0
4500    DATA    "RESUME"   	,  " RESUME "					, 0
4550    DATA    "RETURN"   	,  " RETURN "					, 0
4600	DATA	"RND("	   	,  "RND*("					, 0
4605	!
4650    DATA    "SET"      	,  " SET "					, 0
4660	DATA	"SP"	   	,  "SP."					, 0
4700    DATA    "STEP"     	,  " STEP "					, 0
4750    DATA    "STOP"     	,  " STOP "					, 0
4755	!
4800    DATA    "THEN"     	,  " THEN "					, 0
4850    DATA    "TO"       	,  " TO "					, 0
4900	DATA    "GO TO"    	,  "GOTO"					, 0
4905	!
4910	DATA	" S TO P " 	,  " STOP "					, 0
4950    DATA    "USING"    	,  " USING "					, 0
5000	DATA	"#9, USING"	,  "#9 USING"					, 0
5001	DATA	"#9,  USING"	,  "#9 USING"					, 0
5002	DATA	"#9,   USING"	,  "#9 USING"					, 0
5005	!
5050	DATA	"WHILE"    	,  " WHILE "					, 0
5850	!
5900    DATA    "..."      	,  " ..."					, 0
9000	!
9999    END FUNCTION
