BFormat: Difference between revisions

From Pickwiki
Jump to navigationJump to search
m link fix
 
IanMcGowan (talk | contribs)
mNo edit summary
Line 3: Line 3:
This utility will format a basic program to your taste.
This utility will format a basic program to your taste.


NB: It treats a RETURN in a subroutine as the end of the routine, only if there's a blank line after it, so use some whitespace between routines, people!
* Will convert blank lines to a single comment marker - if you need to move code between systems, the ability to just paste into ED is really handy
* It treats a RETURN in a subroutine as the end of the routine, only if there's a comment after it, so use some whitespace between routines, people!
 
[https://github.com/ianmcgowan/SCI.BP/blob/master/BFORMAT https://github.com/ianmcgowan/SCI.BP/blob/master/BFORMAT] for the latest version


<PRE>
<PRE>
***************************************************************************
***************************************************************************
* Program: BASIC FORMAT PROGRAM
* Program: BASIC FORMAT PROGRAM
* Author : Ian [[McGowan]]
* Author : Ian McGowan
* Date  : 08/30/1989
* Date  : 08/30/1989
* Edited : $Id: BFORMAT,v 1.2 2003/05/15 18:54:51 dsiroot Exp $
* Edited : $Id: BFORMAT 11766 2006-05-05 23:22:04Z mcgowan $
* Comment: Program to indent BASIC programs according to user defined options
* Comment: Program to indent BASIC programs according to user defined options
***************************************************************************
***************************************************************************
* 11/16/1997 Ian  Modified to sort subroutines alphabetically
* 11/16/1997 Ian  Modified to sort subroutines alphabetically
* 07/23/2002 Ian  Deal with tabs
* 07/23/2002 Ian  Deal with tabs
* $Log: BFORMAT,v $
* Revision 1.2  2003/05/15 18:54:51  dsiroot
* mcgowan:Remove code for sorting subroutines
*
*
PROMPT ":"
PROMPT ":"
SPACE = ' ' ; STAR  = '*' ; COLON = ':' ; TAB=CHAR(9)
SPACE = ' ' ; STAR  = '*' ; COLON = ':' ; TAB=CHAR(9)
Line 29: Line 27:
OPEN 'VOC' TO VOC ELSE STOP 201,'VOC'
OPEN 'VOC' TO VOC ELSE STOP 201,'VOC'
OPEN HOME.FILE TO HOME.F ELSE
OPEN HOME.FILE TO HOME.F ELSE
    R='DIR' ; R<2>=HOME.DIR ; R<3>='[[D_VOC]]'
  R='DIR' ; R<2>=HOME.DIR ; R<3>='D_VOC'
    WRITE R ON VOC, HOME.FILE
  WRITE R ON VOC, HOME.FILE
    OPEN HOME.FILE TO HOME.F ELSE STOP 201, HOME.FILE
  OPEN HOME.FILE TO HOME.F ELSE STOP 201, HOME.FILE
END
END
 
*
* These are all commands that may have ELSE or THEN statements
* These are all commands that may have ELSE or THEN statements
* (or blocks) following them
* (or blocks) following them
Line 41: Line 39:
SPECIAL.CASES:= "READVU":@AM:"REWIND":@AM:"SEEK":@AM:"WEOF":@AM:"WRITESEQ":@AM
SPECIAL.CASES:= "READVU":@AM:"REWIND":@AM:"SEEK":@AM:"WEOF":@AM:"WRITESEQ":@AM
SPECIAL.CASES:= "WRITET"
SPECIAL.CASES:= "WRITET"
 
*
DEF.INDENT=4
DEF.INDENT=2
READ FORMATS FROM HOME.F,'.STACK.FORMAT_':ID ELSE
READ FORMATS FROM HOME.F,'.STACK.FORMAT_':ID ELSE
    FORMATS=":":@VM:"BEGIN":@VM:"CASE":@VM:"ELSE":@VM:"END":@VM:"FOR":@VM
  FORMATS=":":@VM:"BEGIN":@VM:"CASE":@VM:"ELSE":@VM:"END":@VM:"FOR":@VM
    FORMATS:="IF":@VM:"LOOP":@VM:"NEXT":@VM:"REPEAT":@VM:"RETURN":@VM
  FORMATS:="IF":@VM:"LOOP":@VM:"NEXT":@VM:"REPEAT":@VM:"RETURN":@VM
    FORMATS:="THEN":@VM:"UNTIL":@VM:"WHILE"
  FORMATS:="THEN":@VM:"UNTIL":@VM:"WHILE"
    * THIS.IND is the amount this line will be in or outdented
  * THIS.IND is the amount this line will be in or outdented
    FORMATS<2>=0:@VM:0:@VM:-1:@VM:0:@VM:-1:@VM:0:@VM:0:@VM
  FORMATS<2>=0:@VM:0:@VM:-1:@VM:0:@VM:-1:@VM:0:@VM:0:@VM
    FORMATS<2>:=0:@VM:-1:@VM:-1:@VM:-1:@VM:0:@VM:-1:@VM:-1
  FORMATS<2>:=0:@VM:-1:@VM:-1:@VM:-1:@VM:0:@VM:-1:@VM:-1
    * NEXT.IND is the amount that all following lines will be indented
  * NEXT.IND is the amount that all following lines will be indented
    FORMATS<3>=1:@VM:2:@VM:0:@VM:1:@VM:-1:@VM:1:@VM:1:@VM
  FORMATS<3>=1:@VM:2:@VM:0:@VM:1:@VM:-1:@VM:1:@VM:1:@VM
    FORMATS<3>:=1:@VM:-1:@VM:-1:@VM:-1:@VM:1:@VM:0:@VM:0
  FORMATS<3>:=1:@VM:-1:@VM:-1:@VM:-1:@VM:1:@VM:0:@VM:0
    FORMATS<4>=DEF.INDENT
  FORMATS<4>=DEF.INDENT
END
END
DEF.INDENT=FORMATS<4>
DEF.INDENT=FORMATS<4>
 
*
ERR = "Usage - BFORMAT file-name item-name"
ERR = "Usage - BFORMAT file-name item-name"
F.NAME = FIELD(TRIM(@SENTENCE),' ',2)
F.NAME = FIELD(TRIM(@SENTENCE),' ',2)
IF F.NAME = '' THEN
IF F.NAME = '' THEN
    PRINT "File :": ; INPUT F.NAME
  PRINT "File :": ; INPUT F.NAME
END
END
IF F.NAME = "" OR F.NAME = "/" THEN STOP
IF F.NAME = "" OR F.NAME = "/" THEN STOP
OPEN F.NAME TO FI ELSE PRINT ERR ; STOP
OPEN F.NAME TO FI ELSE PRINT ERR ; STOP
 
*
B.NAME = FIELD(TRIM(@SENTENCE),' ',3)
B.NAME = FIELD(TRIM(@SENTENCE),' ',3)
IF B.NAME = '' THEN
IF B.NAME = '' THEN
    PRINT "Item :": ; INPUT B.NAME
  PRINT "Item :": ; INPUT B.NAME
END
END
IF B.NAME = "" OR B.NAME = "/" THEN STOP
IF B.NAME = "" OR B.NAME = "/" THEN STOP
 
*
READ REC FROM FI,B.NAME ELSE PRINT "CANNOT READ ":F.NAME:",":B.NAME ; STOP
READ REC FROM FI,B.NAME ELSE PRINT "CANNOT READ ":F.NAME:",":B.NAME ; STOP
WRITE REC ON FI,B.NAME:".BAK"
WRITE REC ON FI,B.NAME:".BAK"
 
SWAP CHAR(9) WITH SPACE(DEF.INDENT) IN REC
*
I = DCOUNT(REC,@AM)
I = DCOUNT(REC,@AM)
IF I < 2 THEN STOP
IF I < 2 THEN STOP
FOR F = 1 TO I
FOR F = 1 TO I
    PRINT STAR:
  PRINT STAR:
    L = REC<F> ; NEXT.LINE=REC<F+1>
  L = REC<F> ; NEXT.LINE=REC<F+1>
    GOSUB FORMAT.LINE
  GOSUB FORMAT.LINE
    REC<F> = L
  REC<F> = L
NEXT F
NEXT F
WRITE REC ON FI,B.NAME
WRITE REC ON FI,B.NAME
PRINT STAR ; PRINT I:" lines of ":B.NAME:" formatted"
PRINT STAR ; PRINT I:" lines of ":B.NAME:" formatted"
STOP
STOP
 
*
FORMAT.LINE:
FORMAT.LINE:
    GOSUB TRIM.LINE
  GOSUB TRIM.LINE
    CONVERT TAB TO "" IN L
  CONVERT TAB TO "" IN L
    FIRST.WORD = FIELD(L,SPACE,1)
  FIRST.WORD = FIELD(L,SPACE,1)
    LEN.FIRST.WORD = LEN(FIRST.WORD)
  LEN.FIRST.WORD = LEN(FIRST.WORD)
    LOCATE FIRST.WORD IN SPECIAL.CASES BY 'AL' SETTING SPECIAL ELSE SPECIAL = 0
  LOCATE FIRST.WORD IN SPECIAL.CASES BY 'AL' SETTING SPECIAL ELSE SPECIAL = 0
    NUM.SPACES = COUNT(L,SPACE) + 1
  NUM.SPACES = COUNT(L,SPACE) + 1
    LAST.WORD = FIELD(L,SPACE,NUM.SPACES)
  LAST.WORD = FIELD(L,SPACE,NUM.SPACES)
    NEXT.TO.LAST.WORD = FIELD(L,SPACE,NUM.SPACES-1)
  NEXT.TO.LAST.WORD = FIELD(L,SPACE,NUM.SPACES-1)
    THIS.IND = 0
  THIS.IND = 0
    NEXT.IND = 0
  NEXT.IND = 0
     IF L # "" THEN
  BEGIN CASE
        BEGIN CASE
     CASE L=""
            CASE FIRST.WORD[LEN.FIRST.WORD,1] = COLON OR NUM(FIRST.WORD)
      L="*" ;* Makes pasting code around easier with no blank lines
                * A label
    CASE FIRST.WORD[LEN.FIRST.WORD,1] = COLON OR NUM(FIRST.WORD)
                IND = 0
      * A label
                LOCATE COLON IN FORMATS<1> SETTING POS ELSE POS = 0
      IND = 0
                THIS.IND = FORMATS<2,POS>
      LOCATE COLON IN FORMATS<1> SETTING POS ELSE POS = 0
                NEXT.IND = FORMATS<3,POS>
      THIS.IND = FORMATS<2,POS>
            CASE FIRST.WORD = "IF"
      NEXT.IND = FORMATS<3,POS>
                LOCATE FIRST.WORD IN FORMATS<1> SETTING POS ELSE POS = 0
    CASE FIRST.WORD = "IF"
                IF LAST.WORD = "THEN" THEN
      LOCATE FIRST.WORD IN FORMATS<1> SETTING POS ELSE POS = 0
                    THIS.IND = FORMATS<2,POS>
      IF LAST.WORD = "THEN" THEN
                    NEXT.IND = FORMATS<3,POS>
        THIS.IND = FORMATS<2,POS>
                END
        NEXT.IND = FORMATS<3,POS>
            CASE FIRST.WORD = "END"
      END
                SECOND.WORD = FIELD(L,SPACE,2)
    CASE FIRST.WORD = "END"
                IF SECOND.WORD = "ELSE" THEN
      SECOND.WORD = FIELD(L,SPACE,2)
                    LOCATE "ELSE" IN FORMATS<1> SETTING POS ELSE POS = 0
      IF SECOND.WORD = "ELSE" THEN
                    THIS.IND = -FORMATS<3,POS>
        LOCATE "ELSE" IN FORMATS<1> SETTING POS ELSE POS = 0
                    NEXT.IND = FORMATS<2,POS>
        THIS.IND = -FORMATS<3,POS>
                END ELSE
        NEXT.IND = FORMATS<2,POS>
                    IF SECOND.WORD = "CASE" THEN
      END ELSE
                        LOCATE "BEGIN" IN FORMATS<1> SETTING POS ELSE POS = 0
        IF SECOND.WORD = "CASE" THEN
                        THIS.IND = -FORMATS<3,POS>
          LOCATE "BEGIN" IN FORMATS<1> SETTING POS ELSE POS = 0
                        NEXT.IND = -FORMATS<3,POS>
          THIS.IND = -FORMATS<3,POS>
                    END ELSE
          NEXT.IND = -FORMATS<3,POS>
                        LOCATE FIRST.WORD IN FORMATS<1> SETTING POS ELSE POS = 0
        END ELSE
                        THIS.IND = FORMATS<2,POS>
          LOCATE FIRST.WORD IN FORMATS<1> SETTING POS ELSE POS = 0
                        NEXT.IND = FORMATS<3,POS>
          THIS.IND = FORMATS<2,POS>
                    END
          NEXT.IND = FORMATS<3,POS>
                END
        END
            CASE SPECIAL
      END
                * Find last word - skip until a space
    CASE SPECIAL
                IF LAST.WORD = "ELSE" OR LAST.WORD = "THEN" THEN
      * Find last word - skip until a space
                    LOCATE LAST.WORD IN FORMATS<1> SETTING POS ELSE POS = 0
      IF LAST.WORD = "ELSE" OR LAST.WORD = "THEN" THEN
                    THIS.IND = FORMATS<2,POS>
        LOCATE LAST.WORD IN FORMATS<1> SETTING POS ELSE POS = 0
                    NEXT.IND = FORMATS<3,POS>
        THIS.IND = FORMATS<2,POS>
                END
        NEXT.IND = FORMATS<3,POS>
            CASE FIRST.WORD = "FOR" AND NEXT.TO.LAST.WORD = "NEXT"
      END
                * FOR loop on one line means do nothing
    CASE FIRST.WORD = "FOR" AND NEXT.TO.LAST.WORD = "NEXT"
            CASE FIRST.WORD = "RETURN" AND NEXT.LINE # ""
      * FOR loop on one line means do nothing
                * RETURN without a blank line means do nothing
    CASE FIRST.WORD = "RETURN" AND TRIM(NEXT.LINE) # "*"
            CASE 1
      * RETURN without a blank line means do nothing
                LOCATE FIRST.WORD IN FORMATS<1> SETTING POS ELSE POS = 0
    CASE 1
                IF POS # 0 THEN
      LOCATE FIRST.WORD IN FORMATS<1> SETTING POS ELSE POS = 0
                    THIS.IND = FORMATS<2,POS>
      IF POS # 0 THEN
                    NEXT.IND = FORMATS<3,POS>
        THIS.IND = FORMATS<2,POS>
                END
        NEXT.IND = FORMATS<3,POS>
        END CASE
      END
    END
  END CASE
    L = SPACE((IND+THIS.IND)*DEF.INDENT):L
  L = SPACE((IND+THIS.IND)*DEF.INDENT):L
    *L = STR(TAB,IND+THIS.IND):L
  *L = STR(TAB,IND+THIS.IND):L
    IND = IND + NEXT.IND
  IND = IND + NEXT.IND
RETURN
RETURN
 
*
TRIM.LINE:
TRIM.LINE:
    * Trim leading and trailing spaces, but not included
  * Trim leading and trailing spaces, but not included
    XXLENGTH = LEN(L)
  XXLENGTH = LEN(L)
    FOR J = 1 TO XXLENGTH UNTIL L[J,1] # SPACE ; NEXT J
  FOR J = 1 TO XXLENGTH UNTIL L[J,1] # SPACE ; NEXT J
    IF J = XXLENGTH THEN L = "" ELSE L = L[J,XXLENGTH]
  IF J = XXLENGTH THEN L = "" ELSE L = L[J,XXLENGTH]
    XXLENGTH = LEN(L)
  XXLENGTH = LEN(L)
    FOR J = XXLENGTH TO 1 STEP -1 UNTIL L[J,1] # SPACE ; NEXT J
  FOR J = XXLENGTH TO 1 STEP -1 UNTIL L[J,1] # SPACE ; NEXT J
    L = L[1,J]
  L = L[1,J]
RETURN
RETURN
*
</PRE>
</PRE>

Revision as of 00:02, 15 February 2019

Back to BasicSource

This utility will format a basic program to your taste.

  • Will convert blank lines to a single comment marker - if you need to move code between systems, the ability to just paste into ED is really handy
  • It treats a RETURN in a subroutine as the end of the routine, only if there's a comment after it, so use some whitespace between routines, people!

https://github.com/ianmcgowan/SCI.BP/blob/master/BFORMAT for the latest version

***************************************************************************
* Program: BASIC FORMAT PROGRAM
* Author : Ian McGowan
* Date   : 08/30/1989
* Edited : $Id: BFORMAT 11766 2006-05-05 23:22:04Z mcgowan $
* Comment: Program to indent BASIC programs according to user defined options
***************************************************************************
* 11/16/1997 Ian  Modified to sort subroutines alphabetically
* 07/23/2002 Ian  Deal with tabs
*
PROMPT ":"
SPACE = ' ' ; STAR  = '*' ; COLON = ':' ; TAB=CHAR(9)
IND = 0
ID=UPCASE(@LOGNAME)
HOME.DIR=GETENV("HOME")
HOME.FILE='HOME.':UPCASE(ID)
OPEN 'VOC' TO VOC ELSE STOP 201,'VOC'
OPEN HOME.FILE TO HOME.F ELSE
  R='DIR' ; R<2>=HOME.DIR ; R<3>='D_VOC'
  WRITE R ON VOC, HOME.FILE
  OPEN HOME.FILE TO HOME.F ELSE STOP 201, HOME.FILE
END
*
* These are all commands that may have ELSE or THEN statements
* (or blocks) following them
SPECIAL.CASES = "GET":@AM:"INPUT":@AM:"LOCATE":@AM:"LOCK":@AM:"MATREAD":@AM:"MATREADU":@AM
SPECIAL.CASES:= "MATWRITE":@AM:"MATWRITEU":@AM:"OPEN":@AM:"PROCREAD":@AM
SPECIAL.CASES:= "PROCWRITE":@AM:"READ":@AM:"READNEXT":@AM:"READSEQ":@AM:"READT":@AM:"READU":@AM:"READV":@AM
SPECIAL.CASES:= "READVU":@AM:"REWIND":@AM:"SEEK":@AM:"WEOF":@AM:"WRITESEQ":@AM
SPECIAL.CASES:= "WRITET"
*
DEF.INDENT=2
READ FORMATS FROM HOME.F,'.STACK.FORMAT_':ID ELSE
  FORMATS=":":@VM:"BEGIN":@VM:"CASE":@VM:"ELSE":@VM:"END":@VM:"FOR":@VM
  FORMATS:="IF":@VM:"LOOP":@VM:"NEXT":@VM:"REPEAT":@VM:"RETURN":@VM
  FORMATS:="THEN":@VM:"UNTIL":@VM:"WHILE"
  * THIS.IND is the amount this line will be in or outdented
  FORMATS<2>=0:@VM:0:@VM:-1:@VM:0:@VM:-1:@VM:0:@VM:0:@VM
  FORMATS<2>:=0:@VM:-1:@VM:-1:@VM:-1:@VM:0:@VM:-1:@VM:-1
  * NEXT.IND is the amount that all following lines will be indented
  FORMATS<3>=1:@VM:2:@VM:0:@VM:1:@VM:-1:@VM:1:@VM:1:@VM
  FORMATS<3>:=1:@VM:-1:@VM:-1:@VM:-1:@VM:1:@VM:0:@VM:0
  FORMATS<4>=DEF.INDENT
END
DEF.INDENT=FORMATS<4>
*
ERR = "Usage - BFORMAT file-name item-name"
F.NAME = FIELD(TRIM(@SENTENCE),' ',2)
IF F.NAME = '' THEN
  PRINT "File :": ; INPUT F.NAME
END
IF F.NAME = "" OR F.NAME = "/" THEN STOP
OPEN F.NAME TO FI ELSE PRINT ERR ; STOP
*
B.NAME = FIELD(TRIM(@SENTENCE),' ',3)
IF B.NAME = '' THEN
  PRINT "Item :": ; INPUT B.NAME
END
IF B.NAME = "" OR B.NAME = "/" THEN STOP
*
READ REC FROM FI,B.NAME ELSE PRINT "CANNOT READ ":F.NAME:",":B.NAME ; STOP
WRITE REC ON FI,B.NAME:".BAK"
SWAP CHAR(9) WITH SPACE(DEF.INDENT) IN REC
*
I = DCOUNT(REC,@AM)
IF I < 2 THEN STOP
FOR F = 1 TO I
  PRINT STAR:
  L = REC<F> ; NEXT.LINE=REC<F+1>
  GOSUB FORMAT.LINE
  REC<F> = L
NEXT F
WRITE REC ON FI,B.NAME
PRINT STAR ; PRINT I:" lines of ":B.NAME:" formatted"
STOP
*
FORMAT.LINE:
  GOSUB TRIM.LINE
  CONVERT TAB TO "" IN L
  FIRST.WORD = FIELD(L,SPACE,1)
  LEN.FIRST.WORD = LEN(FIRST.WORD)
  LOCATE FIRST.WORD IN SPECIAL.CASES BY 'AL' SETTING SPECIAL ELSE SPECIAL = 0
  NUM.SPACES = COUNT(L,SPACE) + 1
  LAST.WORD = FIELD(L,SPACE,NUM.SPACES)
  NEXT.TO.LAST.WORD = FIELD(L,SPACE,NUM.SPACES-1)
  THIS.IND = 0
  NEXT.IND = 0
  BEGIN CASE
    CASE L=""
      L="*" ;* Makes pasting code around easier with no blank lines
    CASE FIRST.WORD[LEN.FIRST.WORD,1] = COLON OR NUM(FIRST.WORD)
      * A label
      IND = 0
      LOCATE COLON IN FORMATS<1> SETTING POS ELSE POS = 0
      THIS.IND = FORMATS<2,POS>
      NEXT.IND = FORMATS<3,POS>
    CASE FIRST.WORD = "IF"
      LOCATE FIRST.WORD IN FORMATS<1> SETTING POS ELSE POS = 0
      IF LAST.WORD = "THEN" THEN
        THIS.IND = FORMATS<2,POS>
        NEXT.IND = FORMATS<3,POS>
      END
    CASE FIRST.WORD = "END"
      SECOND.WORD = FIELD(L,SPACE,2)
      IF SECOND.WORD = "ELSE" THEN
        LOCATE "ELSE" IN FORMATS<1> SETTING POS ELSE POS = 0
        THIS.IND = -FORMATS<3,POS>
        NEXT.IND = FORMATS<2,POS>
      END ELSE
        IF SECOND.WORD = "CASE" THEN
          LOCATE "BEGIN" IN FORMATS<1> SETTING POS ELSE POS = 0
          THIS.IND = -FORMATS<3,POS>
          NEXT.IND = -FORMATS<3,POS>
        END ELSE
          LOCATE FIRST.WORD IN FORMATS<1> SETTING POS ELSE POS = 0
          THIS.IND = FORMATS<2,POS>
          NEXT.IND = FORMATS<3,POS>
        END
      END
    CASE SPECIAL
      * Find last word - skip until a space
      IF LAST.WORD = "ELSE" OR LAST.WORD = "THEN" THEN
        LOCATE LAST.WORD IN FORMATS<1> SETTING POS ELSE POS = 0
        THIS.IND = FORMATS<2,POS>
        NEXT.IND = FORMATS<3,POS>
      END
    CASE FIRST.WORD = "FOR" AND NEXT.TO.LAST.WORD = "NEXT"
      * FOR loop on one line means do nothing
    CASE FIRST.WORD = "RETURN" AND TRIM(NEXT.LINE) # "*"
      * RETURN without a blank line means do nothing
    CASE 1
      LOCATE FIRST.WORD IN FORMATS<1> SETTING POS ELSE POS = 0
      IF POS # 0 THEN
        THIS.IND = FORMATS<2,POS>
        NEXT.IND = FORMATS<3,POS>
      END
  END CASE
  L = SPACE((IND+THIS.IND)*DEF.INDENT):L
  *L = STR(TAB,IND+THIS.IND):L
  IND = IND + NEXT.IND
RETURN
*
TRIM.LINE:
  * Trim leading and trailing spaces, but not included
  XXLENGTH = LEN(L)
  FOR J = 1 TO XXLENGTH UNTIL L[J,1] # SPACE ; NEXT J
  IF J = XXLENGTH THEN L = "" ELSE L = L[J,XXLENGTH]
  XXLENGTH = LEN(L)
  FOR J = XXLENGTH TO 1 STEP -1 UNTIL L[J,1] # SPACE ; NEXT J
  L = L[1,J]
RETURN
*