Action Source Code Formatter#
; ; FORMAT.ACT - Formats Action! sources ; with indented DO-OD, IF-FI pairs. ; ; by Harold Long ; ; Source should be in simple form, i.e., ; one keyword per line, no "DO mumble OD" ; constructions, etc. ; CHAR ARRAY SOURCE(255), ;Temporary DEST(255), ;String arrays KEYWORD ;Test word pointer CARD ARRAY POS(6),NEG(6),RES(6),TEMP(6), LEAD(6) ;Keyword arrays BYTE I,J,K ;Counters BYTE CurPos=~[0], ;Current character pointer LastPos=~[0], ;Last Character position Spaces=~[0], ;Current indent value NextSpace=~[0], ;Next line indent value Indent=~[2] ;Number of spaces per indent INT TempSpace=~[0] ;Back up this line only ; ; Setup keyword arrays with desired values ; To include additional words, add to list ; and modify Foo(0) to reflect total number ; of words in list. ; PROC Setup() POS(0)=2 ;Number of words in list POS(1)="IF" ;Roughly sorted by frequency POS(2)="DO" NEG(0)=3 NEG(1)="FI" NEG(2)="OD" NEG(3)="RETURN" RES(0)=3 RES(1)="MODULE" RES(2)="PROC" RES(3)="FUNC" TEMP(0)=2 TEMP(1)="ELSE" TEMP(2)="ELSEIF" TEMP(3)="RETURN" LEAD(0)=4 LEAD(1)="BYTE" LEAD(2)="CARD" LEAD(3)="INT" LEAD(4)="CHAR" TempSpace=-Indent Spaces=Indent RETURN ; ; Strip out all leading spaces. ; Returns with stripped data in ; SOURCE ; PROC Strip() FOR I=1 to SOURCE(0) ;Count spaces DO IF SOURCE(I)#32 THEN ;Exit on first non-space char EXIT FI OD IF SOURCE(I)=155 THEN SOURCE(0)=0 SOURCE(1)=155 FI IF SOURCE(0)#0 THEN ScopyS(DEST,SOURCE,I,SOURCE(0)) ;Move to delete spaces ScopyS(SOURCE,DEST,1,DEST(0)) ;Put back in source record FI RETURN ; ; Extract substring: returns with ; start:(end-1) inclusive string in ; DEST ; PROC SubStr(BYTE Start, BYTE End) IF End>Start THEN DEST(0)=(End-Start) FOR I=1 to DEST(0) DO DEST(I)=SOURCE(Start+I-1) OD ELSE DEST(0)=0 DEST(1)=155 FI RETURN ; ; Find delimiter: returns next occurrence ; of space char in SOURCE ; BYTE FUNC FindLim(BYTE Start, BYTE End) IF End>Start THEN FOR I=Start TO End DO IF SOURCE(I)=32 THEN EXIT FI OD ELSE I=0 FI RETURN(I) ; ; Test for lower case character ; BYTE FUNC IsLower(BYTE c) IF (c>='a) AND (c<='z) THEN RETURN(1) FI RETURN(0) ; ; Shift to upper case if lower ; BYTE FUNC ToUpper(BYTE c) IF IsLower(c) THEN c==-$20 FI RETURN(c) ; ; Force substring to upper case just ; in case you forgot... ; PROC SubUp() BYTE c FOR I=1 to DEST(0) DO c=DEST(I) DEST(I)=ToUpper(c) OD RETURN ; Test Positive indent; examine DEST ; for match with positive keyword ; BYTE FUNC TestPos() BYTE Match Match=0 FOR I=1 TO POS(0) DO KEYWORD=POS(I) IF SCompare(DEST,KEYWORD)=0 THEN Match=Indent FI OD RETURN(Match) ; ; Test Negative indent; examine DEST ; for match with negative keyword ; BYTE FUNC TestNeg() BYTE Match Match=0 FOR I=1 to NEG(0) DO KEYWORD=NEG(I) IF Scompare(DEST,KEYWORD)=0 THEN Match=Indent FI OD RETURN(Match) ; ; Test for Reset; cancel any ; outstanding pos/neg indents ; BYTE FUNC TestRes() BYTE Match Match=0 FOR I=1 to RES(0) DO KEYWORD=RES(I) IF Scompare(DEST,KEYWORD)=0 THEN Match=Indent FI OD RETURN(Match) ; ; Test for Temporary reset; back up ; line one space to emphasize word. ; BYTE FUNC TestTemp() BYTE Match Match=0 FOR I=1 to TEMP(0) DO KEYWORD=TEMP(I) IF Scompare(DEST,KEYWORD)=0 THEN Match=Indent FI OD RETURN(Match) ; ; Test for 'leader' word, e.g., complex ; expression such that keyword may follow ; BYTE FUNC TestLead() BYTE Match Match=0 FOR I=1 to LEAD(0) DO KEYWORD=LEAD(I) IF SCompare(DEST,KEYWORD)=0 THEN Match=1 FI OD RETURN(Match) ; ; File handler; ; ; Opens Foo.ACT as input and ; Foo.FCT as output. Default ; filename is "TEST". ; PROC FOpen(BYTE ARRAY FName) BYTE ARRAY INAME(16) ;Input file name BYTE ARRAY ONAME(16) ;Output file BYTE ARRAY IEXT=".ACT" BYTE ARRAY OEXT=".FCT" IF FName(0)=0 THEN Scopy(Fname,"D:TEST") FI FOR I=1 TO FName(0) DO INAME(I)=FName(I) ONAME(I)=FName(I) OD FOR I=FName(0)+1 TO FName(0)+4 DO INAME(I)=IEXT(I-FName(0)) ONAME(I)=OEXT(I-FName(0)) OD INAME(0)=FNAME(0)+4 ONAME(0)=FNAME(0)+4 OPEN(2,INAME,4,0) ;Input is read only OPEN(3,ONAME,8,0) ;Output is write only RETURN ; ; Process Record; inputs a line from ; Foo.ACT, strips it, tests for leading ; keywords, adjusts indentation, and ; outputs to Foo.FCT. PROC ProcRec() InputSD(2,SOURCE) ;Get record Strip() ;Delete leading spaces IF SOURCE(0)>0 THEN ;Skip blank lines CurPos=FindLim(1,SOURCE(0)) ;Find delimiter SubStr(1,CurPos) ;extract substring SubUp() ;Upper case IF TestLead() THEN ;Complex expression? LastPos=Curpos+1 CurPos=FindLim(LastPos,Source(0)) ;Get next word SubStr(LastPos,Curpos) ;Extract SubUp() ;Upper case FI IF TestRes()#0 OR SOURCE(1)='; THEN Spaces=Indent TempSpace=-Indent FI Spaces==-TestNeg() NextSpace=TestPos() TempSpace==-TestTemp() CurPos=Spaces+TempSpace+1 FOR I=1 TO 254 ;Blank target line DO DEST(I)=32 OD DEST(0)=254 DEST(255)=155 SAssign(DEST,SOURCE,Curpos,SOURCE(0)+CurPos) ScopyS(SOURCE,DEST,1,SOURCE(0)+Curpos) TempSpace=0 FI PrintDE(3,SOURCE) ;Write record Spaces==+NextSpace RETURN PROC Main() BYTE ARRAY File(20) CLOSE(2) CLOSE(3) GRAPHICS(0) ;CLEAR SCREEN POSITION(10,2) PRINTE("Action! Formatter") POSITION(2,4) PRINTE("Formats Action! source files with") POSITION(2,5) PRINTE("indented DO-OD, IF-FI, etc. pairs.") POSITION(2,7) PRINTE("Specify input file as Dn:mumble") POSITION(2,8) PRINTE("Input extension of .ACT is assumed.") POSITION(2,9) PRINTE("Output file will be Dn:mumble.FCT") Position(2,11) PRINT("Input: ") INPUTS(File) FOpen(File) Setup() WHILE EOF(2)=0 DO ProcRec() OD CLOSE(2) CLOSE(3) POSITION(2,13) PRINTE("DONE!") RETURN