888 lines
38 KiB
Plaintext
Executable File
888 lines
38 KiB
Plaintext
Executable File
*******************************************************************************
|
|
*
|
|
* uniVerse basic FORMAT.BASIC subroutine (PIopen)
|
|
*
|
|
* Module %M% Version %I% Date %H%
|
|
*
|
|
* (c) Copyright 1998 Ardent Software Inc. - All Rights Reserved
|
|
* This is unpublished proprietary source code of Ardent Software Inc.
|
|
* The copyright notice above does not evidence any actual or intended
|
|
* publication of such source code.
|
|
*
|
|
*******************************************************************************
|
|
*
|
|
* Maintenance log - insert most recent change descriptions at top
|
|
*
|
|
* Date.... GTAR# WHO Description.........................................
|
|
* 10/14/98 23801 SAP Change copyrights.
|
|
* 06/09/94 13973 RM Add handling of ISOLATION to BEGIN TRANSACTIONS
|
|
* 03/11/93 11188 PVW Fixed handling of BEGIN/END TRANSACTIONS
|
|
* 03/11/93 11136 PVW Changed assigning of INDEX.CHARS so that it works
|
|
* correctly. we do not support '' to escape '.
|
|
* 02/01/93 10966 PVW Allow SQL NULL as element in multivalued data.
|
|
* 11/12/92 10214 PVW Port PIopen editor to uniVerse.
|
|
*
|
|
*******************************************************************************
|
|
$OPTIONS INFORMATION
|
|
|
|
SUBROUTINE FORMAT.BASIC(PROGRAM,NO.OF.LINES,MAT FORMAT.OPTIONS)
|
|
|
|
$INCLUDE UNIVERSE.INCLUDE FORMAT.OPTS.H
|
|
$INCLUDE UNIVERSE.INCLUDE VERBINSERT.H
|
|
|
|
X = 0 ;* Display length returned from DISLEN
|
|
|
|
***************************************************************************
|
|
** Initialize the formatter. **
|
|
***************************************************************************
|
|
EQUATE TAB TO CHAR(9) ;* Tab character (treated as space)
|
|
DYN.REF = TRUE ;* Assume < is a dynamic array reference
|
|
END.OF.PROGRAM = FALSE ;* End of source program reached
|
|
INDENT.LEVEL = 0 ;* Level indentation for current line.
|
|
LINE.NO = 0 ;* Line number in original source
|
|
LIST.CONTINUED = FALSE ;* Comma separated list continues
|
|
NEXT.INDENT.LEVEL = 0 ;* Level of indentation for next line.
|
|
NO.OF.LINES = 0 ;* Number of lines in formatted program.
|
|
LAST.LINE = '' ;* The previous line output
|
|
UNFORMATTED.PROGRAM = PROGRAM ;* The original program
|
|
PROGRAM = '' ;* The formatted program
|
|
IDENTIFIER.CHARACTERS = '' ;* Valid identifier characters
|
|
IDENTIFIER.CHARACTERS := 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
|
IDENTIFIER.CHARACTERS := 'abcdefghijklmnopqrstuvwxyz'
|
|
IDENTIFIER.CHARACTERS := '0123456789'
|
|
IDENTIFIER.CHARACTERS := '.$%'
|
|
NUMERIC.LABEL.CHARACTERS = '0123456789.' ;* Valid numeric label characters
|
|
STRING.DELIMITERS = '''"\' ;* Recognised string delimiters
|
|
VAR.IND = '=+-:(<[' ;* Check of FOR and LOOP as variables
|
|
|
|
***************************************************************************
|
|
** Format the program. **
|
|
***************************************************************************
|
|
|
|
***************************************************************************
|
|
** Leave the first line unchanged if it is a comment. **
|
|
***************************************************************************
|
|
GOSUB GET.LINE:
|
|
IF LINE[1,1] = '*' THEN
|
|
FORMATTED.LINE = LINE
|
|
GOSUB ADD.FORMATTED.LINE:
|
|
GOSUB GET.LINE:
|
|
END
|
|
|
|
LOOP
|
|
UNTIL(END.OF.PROGRAM) DO
|
|
*************************************************************************
|
|
** Display an asterisk every 10 lines processed. **
|
|
*************************************************************************
|
|
IF NOT(FORMAT.BRIEF) AND (MOD(LINE.NO,10) = 0) THEN
|
|
CRT '*':
|
|
END
|
|
|
|
*************************************************************************
|
|
** Process the line. **
|
|
*************************************************************************
|
|
GOSUB PROCESS.LINE:
|
|
|
|
*************************************************************************
|
|
** Format the line. **
|
|
*************************************************************************
|
|
FORMAT.THE.LINE:
|
|
|
|
IDENTATION = FORMAT.MARGIN + (FORMAT.INDENT * INDENT.LEVEL)
|
|
IF (LABEL = '') THEN
|
|
FORMATTED.LINE = STR(' ',IDENTATION):LINE
|
|
END ELSE
|
|
FORMATTED.LINE = LABEL:STR(' ',IDENTATION - LEN(LABEL)):LINE
|
|
END
|
|
IF COMMENT THEN
|
|
X = LEN(FORMATTED.LINE)
|
|
IF X < 40
|
|
THEN FORMATTED.LINE := SPACE(40-X): COMMENT
|
|
ELSE FORMATTED.LINE := SPACE(INT((X+10)/10)*10-X): COMMENT
|
|
END
|
|
INDENT.LEVEL = NEXT.INDENT.LEVEL
|
|
|
|
*************************************************************************
|
|
** Add the formatted line to the formatted program. **
|
|
*************************************************************************
|
|
GOSUB ADD.FORMATTED.LINE:
|
|
|
|
NEXT.LINE:
|
|
GOSUB GET.LINE:
|
|
REPEAT
|
|
|
|
***************************************************************************
|
|
** Move the cursor to the beginning of the next line. **
|
|
***************************************************************************
|
|
IF NOT(FORMAT.BRIEF) THEN CRT
|
|
|
|
GO EXIT.FORMAT.BASIC:
|
|
|
|
*******************************************************************************
|
|
** Get a line of the program. **
|
|
*******************************************************************************
|
|
GET.LINE:
|
|
|
|
LINE = ''
|
|
LOOP
|
|
REMOVE LINE.SEGMENT FROM UNFORMATTED.PROGRAM SETTING LINE.SEGMENT.MARK
|
|
UNTIL(LINE.SEGMENT.MARK = 2 OR LINE.SEGMENT.MARK = 0) DO
|
|
IF ISNULL(LINE.SEGMENT) THEN LINE.SEGMENT = @NULL.STR
|
|
LINE := LINE.SEGMENT:CHAR(256 - LINE.SEGMENT.MARK)
|
|
REPEAT
|
|
IF ISNULL(LINE.SEGMENT) THEN LINE.SEGMENT = @NULL.STR
|
|
LINE := LINE.SEGMENT
|
|
IF (LINE.SEGMENT.MARK = 0 AND LINE = '') THEN
|
|
END.OF.PROGRAM = TRUE
|
|
END ELSE
|
|
LINE.NO += 1
|
|
END
|
|
|
|
RETURN
|
|
|
|
*******************************************************************************
|
|
** Process a source line checking whitespace, labels, and control keywords. **
|
|
*******************************************************************************
|
|
PROCESS.LINE:
|
|
|
|
***************************************************************************
|
|
** Initialize the line trim routine. **
|
|
***************************************************************************
|
|
CHARACTER.POS = 1 ;* Character position being processed in line.
|
|
LABEL = '' ;* Statement label.
|
|
COMMENT = '' ;* Trailing comment.
|
|
LEADING.SPACES = FALSE ;* Were there leading spaces in this line.
|
|
***************************************************************************
|
|
** Remove trailing spaces **
|
|
***************************************************************************
|
|
POS = LEN(LINE)
|
|
LOOP
|
|
UNTIL POS <= 0 OR LINE[POS,1] # ' ' DO
|
|
POS -= 1
|
|
REPEAT
|
|
LINE = LINE[1,POS]
|
|
LINE.LENGTH = LEN(LINE) ;* Length of original line.
|
|
***************************************************************************
|
|
** Remove leading spaces **
|
|
***************************************************************************
|
|
POS = 1
|
|
LOOP
|
|
UNTIL LINE[POS,1] # ' '
|
|
POS += 1
|
|
REPEAT
|
|
ORIGINAL.LINE = LINE[POS,99999]
|
|
LINE = '' ;* Null the original, we'll build it as we go.
|
|
IF NOT(LIST.CONTINUED) THEN
|
|
INSIDE.EXPR = FALSE ;* Is the character inside a nested expression.
|
|
|
|
*************************************************************************
|
|
** Remove statement label if one is present. **
|
|
*************************************************************************
|
|
LABEL.POS = 1
|
|
BEGIN CASE
|
|
***********************************************************************
|
|
** Line begins with a numeric label. **
|
|
***********************************************************************
|
|
CASE (ORIGINAL.LINE MATCHES '1N0X')
|
|
LABEL.POS = 1
|
|
LOOP
|
|
CHARACTER = ORIGINAL.LINE[LABEL.POS,1]
|
|
WHILE(CHARACTER # '' AND INDEX(NUMERIC.LABEL.CHARACTERS,CHARACTER,1)) DO
|
|
LABEL.POS += 1
|
|
LABEL := CHARACTER
|
|
REPEAT
|
|
LOOP
|
|
CHARACTER = ORIGINAL.LINE[LABEL.POS,1]
|
|
WHILE (CHARACTER = ' ' OR CHARACTER = TAB) DO
|
|
LABEL.POS += 1
|
|
REPEAT
|
|
IF CHARACTER = ':' THEN
|
|
LABEL.POS += 1
|
|
END
|
|
LABEL := ':'
|
|
ORIGINAL.LINE = ORIGINAL.LINE[LABEL.POS,999999]
|
|
*********************************************************************
|
|
** Remove leading spaces **
|
|
*********************************************************************
|
|
POS = 1
|
|
LOOP
|
|
UNTIL ORIGINAL.LINE[POS,1] # ' '
|
|
POS += 1
|
|
REPEAT
|
|
ORIGINAL.LINE = ORIGINAL.LINE[POS,99999]
|
|
|
|
***********************************************************************
|
|
** Line may begin with an Alphanumeric label. **
|
|
***********************************************************************
|
|
CASE (ORIGINAL.LINE MATCHES '1A0X')
|
|
LABEL.POS = 1
|
|
LOOP
|
|
CHARACTER = ORIGINAL.LINE[LABEL.POS,1]
|
|
WHILE(CHARACTER # '' AND INDEX(IDENTIFIER.CHARACTERS,CHARACTER,1)) DO
|
|
LABEL.POS += 1
|
|
LABEL := CHARACTER
|
|
REPEAT
|
|
LOOP
|
|
CHARACTER = ORIGINAL.LINE[LABEL.POS,1]
|
|
WHILE (CHARACTER = ' ' OR CHARACTER = TAB) DO
|
|
LABEL.POS += 1
|
|
REPEAT
|
|
IF (CHARACTER = ':' AND ORIGINAL.LINE[LABEL.POS + 1,1] # '=') THEN
|
|
LABEL.POS += 1
|
|
LABEL := ':'
|
|
END ELSE
|
|
LABEL.POS = 1
|
|
LABEL = ''
|
|
END
|
|
ORIGINAL.LINE = ORIGINAL.LINE[LABEL.POS,999999]
|
|
*********************************************************************
|
|
** Remove leading spaces **
|
|
*********************************************************************
|
|
POS = 1
|
|
LOOP
|
|
UNTIL ORIGINAL.LINE[POS,1] # ' '
|
|
POS += 1
|
|
REPEAT
|
|
ORIGINAL.LINE = ORIGINAL.LINE[POS,99999]
|
|
|
|
END CASE
|
|
|
|
*************************************************************************
|
|
** If the labels option is set, put label on line by itself. **
|
|
*************************************************************************
|
|
IF (LABEL # '' AND FORMAT.LABELS) THEN
|
|
IF (LAST.LINE[1,1] # '*' AND LAST.LINE # '') THEN
|
|
FORMATTED.LINE = '' ;* Insert null line before label
|
|
GOSUB ADD.FORMATTED.LINE:
|
|
END
|
|
FORMATTED.LINE = LABEL
|
|
GOSUB ADD.FORMATTED.LINE:
|
|
LABEL = ''
|
|
IF ORIGINAL.LINE = '' THEN
|
|
RETURN TO NEXT.LINE:
|
|
END
|
|
END
|
|
END
|
|
|
|
***************************************************************************
|
|
** Were there leading spaces? **
|
|
***************************************************************************
|
|
IF (LINE.LENGTH # LEN(ORIGINAL.LINE) + LABEL.POS - 1) THEN
|
|
LEADING.SPACES = TRUE
|
|
END
|
|
|
|
***************************************************************************
|
|
** Check for special cases. **
|
|
***************************************************************************
|
|
BEGIN CASE
|
|
*************************************************************************
|
|
** Blank lines in the program. **
|
|
*************************************************************************
|
|
CASE ORIGINAL.LINE = ''
|
|
FORMATTED.LINE = LABEL
|
|
GOSUB ADD.FORMATTED.LINE:
|
|
RETURN TO NEXT.LINE:
|
|
|
|
*************************************************************************
|
|
** Line is a comment beginning with '*' **
|
|
** These comments are treated specially when FORMAT.COMMENT is TRUE **
|
|
*************************************************************************
|
|
CASE ORIGINAL.LINE[1,1] = '*'
|
|
IF FORMAT.COMMENT THEN
|
|
IF (LEADING.SPACES) THEN
|
|
FORMATTED.LINE = LABEL:ORIGINAL.LINE
|
|
GOSUB ADD.FORMATTED.LINE
|
|
RETURN TO NEXT.LINE:
|
|
END
|
|
IF ORIGINAL.LINE = '*' THEN
|
|
FORMATTED.LINE = LABEL
|
|
GOSUB ADD.FORMATTED.LINE:
|
|
RETURN TO NEXT.LINE:
|
|
END
|
|
L = 2
|
|
LOOP WHILE ORIGINAL.LINE[L,1] # '' AND INDEX('*- ',ORIGINAL.LINE[L,1],1) DO L+= 1 REPEAT
|
|
IF LAST.LINE[1,1] = '*' THEN
|
|
FORMATTED.LINE = LABEL:'* ':ORIGINAL.LINE[L,9999]
|
|
GOSUB ADD.FORMATTED.LINE:
|
|
RETURN TO NEXT.LINE:
|
|
END
|
|
IF LAST.LINE[1,1] = ' ' THEN
|
|
FORMATTED.LINE = ''
|
|
GOSUB ADD.FORMATTED.LINE:
|
|
END
|
|
IF L = LEN(ORIGINAL.LINE) THEN
|
|
FORMATTED.LINE = LABEL:'!'
|
|
GOSUB ADD.FORMATTED.LINE:
|
|
RETURN TO NEXT.LINE
|
|
END
|
|
FORMATTED.LINE = LABEL:'*---- ':ORIGINAL.LINE[L,9999]
|
|
GOSUB ADD.FORMATTED.LINE:
|
|
RETURN TO NEXT.LINE:
|
|
END ELSE
|
|
IF (LEADING.SPACES) THEN
|
|
LINE = ORIGINAL.LINE
|
|
RETURN TO FORMAT.THE.LINE:
|
|
END ELSE
|
|
FORMATTED.LINE = LABEL:ORIGINAL.LINE
|
|
GOSUB ADD.FORMATTED.LINE:
|
|
RETURN TO NEXT.LINE:
|
|
END
|
|
END
|
|
|
|
*************************************************************************
|
|
** Line is a comment beginning with ! **
|
|
*************************************************************************
|
|
CASE ORIGINAL.LINE[1,1] = '!'
|
|
IF (LEADING.SPACES) THEN
|
|
LINE = ORIGINAL.LINE
|
|
RETURN TO FORMAT.THE.LINE:
|
|
END ELSE
|
|
FORMATTED.LINE = LABEL:ORIGINAL.LINE
|
|
GOSUB ADD.FORMATTED.LINE:
|
|
RETURN TO NEXT.LINE:
|
|
END
|
|
|
|
*************************************************************************
|
|
** Line is a comment of the form REM comment text... **
|
|
** There should be a check here for the use of REM as a variable **
|
|
*************************************************************************
|
|
CASE (OCONV(ORIGINAL.LINE[1,4],FORMAT.CASE) = 'REM ' OR OCONV(ORIGINAL.LINE,FORMAT.CASE) = 'REM')
|
|
IF (LEADING.SPACES) THEN
|
|
LINE = ORIGINAL.LINE
|
|
RETURN TO FORMAT.THE.LINE:
|
|
END ELSE
|
|
FORMATTED.LINE = LABEL:ORIGINAL.LINE
|
|
GOSUB ADD.FORMATTED.LINE:
|
|
RETURN TO NEXT.LINE:
|
|
END
|
|
|
|
*************************************************************************
|
|
** Line is a $ directive (don't trim embedded or trailing blanks) **
|
|
*************************************************************************
|
|
CASE ORIGINAL.LINE[1,1] = '$'
|
|
FORMATTED.LINE = LABEL:ORIGINAL.LINE
|
|
GOSUB ADD.FORMATTED.LINE:
|
|
RETURN TO NEXT.LINE:
|
|
|
|
END CASE
|
|
|
|
***************************************************************************
|
|
** Trim the embedded spaces. **
|
|
***************************************************************************
|
|
WHITESPACE.FLAG = FALSE
|
|
STATEMENT = ''
|
|
CHARACTER = ''
|
|
PREVIOUS.CHARACTER = ''
|
|
CHARACTER.POS = 0
|
|
FIRST.STATEMENT.ON.LINE = TRUE
|
|
***************************************************************************
|
|
** Check if special characters are to be surrounded with spaces. **
|
|
***************************************************************************
|
|
IF FORMAT.SURROUND THEN
|
|
INDEX.CHARS = TAB:" ;()[]'":'"\=:+-#><'
|
|
END ELSE
|
|
INDEX.CHARS = TAB:" ;()[]'":'"\'
|
|
END
|
|
NEXT.CHARACTER:
|
|
CHARACTER.POS += 1
|
|
CHARACTER = ORIGINAL.LINE[CHARACTER.POS,1]
|
|
IF CHARACTER = '' THEN
|
|
GOTO END.OF.LINE:
|
|
END
|
|
***************************************************************************
|
|
** Check for special cases. **
|
|
***************************************************************************
|
|
ON INDEX(INDEX.CHARS,CHARACTER,1) + 1 GOTO OTHER.LABEL:,
|
|
WHITESPACE.LABEL:,
|
|
WHITESPACE.LABEL:,
|
|
SEMI.LABEL:,
|
|
OPEN.LABEL:,
|
|
CLOSE.LABEL:,
|
|
OPEN.LABEL:,
|
|
CLOSE.LABEL:,
|
|
QUOTE.LABEL:,
|
|
QUOTE.LABEL:,
|
|
QUOTE.LABEL:,
|
|
EQ.LABEL:,
|
|
COLON.LABEL:,
|
|
PLUS.LABEL:,
|
|
MINUS.LABEL:,
|
|
NE.LABEL:,
|
|
GT.LABEL:,
|
|
LT.LABEL:
|
|
|
|
***************************************************************************
|
|
** Add CHARACTER to the current statement. **
|
|
***************************************************************************
|
|
OTHER.LABEL:
|
|
ADD.CHARACTER:
|
|
IF WHITESPACE.FLAG THEN
|
|
STATEMENT := ' '
|
|
WHITESPACE.FLAG = FALSE
|
|
END
|
|
STATEMENT := CHARACTER
|
|
PREVIOUS.CHARACTER = CHARACTER
|
|
GOTO NEXT.CHARACTER:
|
|
|
|
***************************************************************************
|
|
** Compress all contiguous blanks to a single blank. **
|
|
***************************************************************************
|
|
WHITESPACE.LABEL:
|
|
IF PREVIOUS.CHARACTER # '' THEN
|
|
WHITESPACE.FLAG = TRUE
|
|
END
|
|
GOTO NEXT.CHARACTER
|
|
|
|
***************************************************************************
|
|
** Handle the nesting of expressions. **
|
|
***************************************************************************
|
|
OPEN.LABEL:
|
|
INSIDE.EXPR += 1
|
|
GOTO ADD.CHARACTER:
|
|
CLOSE.LABEL:
|
|
INSIDE.EXPR -= 1
|
|
GOTO ADD.CHARACTER:
|
|
|
|
***************************************************************************
|
|
** Handle end of statement. **
|
|
***************************************************************************
|
|
SEMI.LABEL:
|
|
IF NOT(INSIDE.EXPR) OR PREVIOUS.CHARACTER = ',' THEN
|
|
COMMENT = ORIGINAL.LINE[CHARACTER.POS+1,999999]
|
|
*********************************************************************
|
|
** Remove leading spaces **
|
|
*********************************************************************
|
|
POS = 1
|
|
LOOP
|
|
UNTIL COMMENT[POS,1] # ' '
|
|
POS += 1
|
|
REPEAT
|
|
COMMENT = COMMENT[POS,99999]
|
|
*****************************************************************
|
|
** Don't worry about check if the statement is a comment. **
|
|
*****************************************************************
|
|
IF COMMENT[1,1] = '*' THEN
|
|
IF FORMAT.COMMENT THEN
|
|
COMMENT = COMMENT[2,999999]
|
|
*********************************************************************
|
|
** Remove leading spaces **
|
|
*********************************************************************
|
|
POS = 1
|
|
LOOP
|
|
UNTIL COMMENT[POS,1] # ' '
|
|
POS += 1
|
|
REPEAT
|
|
COMMENT = ' ;* ':COMMENT[POS,99999]
|
|
END ELSE
|
|
COMMENT = ' ; ':COMMENT
|
|
END
|
|
GOTO END.OF.LINE:
|
|
END
|
|
IF COMMENT[1,1] = '!' OR OCONV(COMMENT,FORMAT.CASE) = 'REM' OR OCONV(COMMENT[1,4],FORMAT.CASE) = 'REM ' THEN
|
|
COMMENT = ' ; ':COMMENT
|
|
GOTO END.OF.LINE:
|
|
END ELSE
|
|
***********************************************************************
|
|
** End of statement. Check control keywords, add to line. **
|
|
***********************************************************************
|
|
COMMENT = ''
|
|
GOSUB CHECK.CONTROL.KEYWORDS:
|
|
LINE := STATEMENT:' ; '
|
|
STATEMENT = ''
|
|
CHARACTER = ''
|
|
PREVIOUS.CHARACTER = ''
|
|
WHITESPACE.FLAG = FALSE
|
|
FIRST.STATEMENT.ON.LINE = FALSE
|
|
GOTO NEXT.CHARACTER:
|
|
END
|
|
END ELSE
|
|
GOTO ADD.CHARACTER:
|
|
END
|
|
|
|
**************************************************************************
|
|
** Handle quoted strings. **
|
|
**************************************************************************
|
|
QUOTE.LABEL:
|
|
STRING = ORIGINAL.LINE[CHARACTER.POS,9999]
|
|
STR.LEN = INDEX(STRING[2,9999],CHARACTER,1) + 1
|
|
STRING = STRING[1,STR.LEN]
|
|
IF WHITESPACE.FLAG THEN
|
|
STATEMENT := ' '
|
|
WHITESPACE.FLAG = FALSE
|
|
END
|
|
STATEMENT := STRING
|
|
PREVIOUS.CHARACTER = CHARACTER
|
|
CHARACTER.POS += STR.LEN - 1
|
|
GOTO NEXT.CHARACTER:
|
|
|
|
***************************************************************************
|
|
** Handle '+=','-=',':='. **
|
|
***************************************************************************
|
|
COLON.LABEL:
|
|
PLUS.LABEL:
|
|
MINUS.LABEL:
|
|
CHAR.NEXT = ORIGINAL.LINE[CHARACTER.POS+1,1]
|
|
IF CHAR.NEXT = '=' THEN
|
|
GOTO SURROUND.2
|
|
END ELSE
|
|
GOTO ADD.CHARACTER:
|
|
END
|
|
|
|
***************************************************************************
|
|
** Handle '=','=>','=<','#','#>','#<'. **
|
|
***************************************************************************
|
|
EQ.LABEL:
|
|
CHAR.NEXT = ORIGINAL.LINE[CHARACTER.POS+1,1]
|
|
IF CHAR.NEXT = '<' OR CHAR.NEXT = '>' THEN
|
|
GOTO SURROUND.2
|
|
END ELSE
|
|
GOTO SURROUND.1
|
|
END
|
|
|
|
NE.LABEL:
|
|
IF ORIGINAL.LINE[CHARACTER.POS,5] = '####(' THEN
|
|
IF WHITESPACE.FLAG THEN
|
|
STATEMENT := ' '
|
|
WHITESPACE.FLAG = FALSE
|
|
END
|
|
STATEMENT := '####('
|
|
PREVIOUS.CHARACTER = '('
|
|
CHARACTER.POS += 4
|
|
GOTO NEXT.CHARACTER:
|
|
END ELSE
|
|
CHAR.NEXT = ORIGINAL.LINE[CHARACTER.POS+1,1]
|
|
IF CHAR.NEXT = '<' OR CHAR.NEXT = '>' THEN
|
|
GOTO SURROUND.2
|
|
END ELSE
|
|
GOTO SURROUND.1
|
|
END
|
|
END
|
|
|
|
***************************************************************************
|
|
** Handle '<','<=','<>','>','>=','><'. **
|
|
***************************************************************************
|
|
GT.LABEL:
|
|
CHAR.NEXT = ORIGINAL.LINE[CHARACTER.POS+1,1]
|
|
IF CHAR.NEXT = '<' OR CHAR.NEXT = '=' THEN
|
|
GOTO SURROUND.2
|
|
END ELSE
|
|
*************************************************************************
|
|
** Possible check for dynamic array reference or GT **
|
|
** Always assumes dynamic array reference at present **
|
|
*************************************************************************
|
|
IF DYN.REF THEN
|
|
GOTO ADD.CHARACTER:
|
|
END ELSE
|
|
GOTO SURROUND.1
|
|
END
|
|
END
|
|
LT.LABEL:
|
|
CHAR.NEXT = ORIGINAL.LINE[CHARACTER.POS+1,1]
|
|
IF CHAR.NEXT = '=' OR CHAR.NEXT = '>' THEN
|
|
GOTO SURROUND.2
|
|
END ELSE
|
|
*************************************************************************
|
|
** Possible check for dynamic array reference or LT **
|
|
** Always assumes dynamic array reference at present **
|
|
*************************************************************************
|
|
IF DYN.REF THEN
|
|
GOTO ADD.CHARACTER:
|
|
END ELSE
|
|
GOTO SURROUND.1
|
|
END
|
|
END
|
|
|
|
***************************************************************************
|
|
** Surround single character with spaces. **
|
|
***************************************************************************
|
|
SURROUND.1:
|
|
STATEMENT := ' ':CHARACTER
|
|
WHITESPACE.FLAG = TRUE
|
|
PREVIOUS.CHARACTER = CHARACTER
|
|
GOTO NEXT.CHARACTER:
|
|
|
|
***************************************************************************
|
|
** Surround double characters with spaces. **
|
|
***************************************************************************
|
|
SURROUND.2:
|
|
STATEMENT := ' ':CHARACTER:CHAR.NEXT
|
|
WHITESPACE.FLAG = TRUE
|
|
PREVIOUS.CHARACTER = CHAR.NEXT
|
|
CHARACTER.POS += 1
|
|
GOTO NEXT.CHARACTER:
|
|
|
|
END.OF.LINE:
|
|
***************************************************************************
|
|
** Add the last statement to the line. **
|
|
***************************************************************************
|
|
GOSUB CHECK.CONTROL.KEYWORDS:
|
|
LINE := STATEMENT
|
|
|
|
***************************************************************************
|
|
** Check if this line is continued. **
|
|
***************************************************************************
|
|
IF LINE[1] = ',' THEN
|
|
IF NOT(LIST.CONTINUED) THEN
|
|
LIST.CONTINUED = TRUE
|
|
NEXT.INDENT.LEVEL += 1
|
|
END
|
|
END ELSE
|
|
IF LIST.CONTINUED THEN
|
|
LIST.CONTINUED = FALSE
|
|
NEXT.INDENT.LEVEL -= 1
|
|
END
|
|
END
|
|
|
|
EXIT.PROCESS.LINE:
|
|
RETURN
|
|
|
|
*******************************************************************************
|
|
** Add a line to the formatted program. **
|
|
*******************************************************************************
|
|
ADD.FORMATTED.LINE:
|
|
NO.OF.LINES += 1
|
|
* PROGRAM<-1> = FORMATTED.LINE
|
|
IF PROGRAM THEN
|
|
PROGRAM := @FM : FORMATTED.LINE
|
|
END ELSE
|
|
PROGRAM = FORMATTED.LINE
|
|
END
|
|
LAST.LINE = FORMATTED.LINE
|
|
RETURN
|
|
|
|
*******************************************************************************
|
|
** Check for the beginning and/or end of a control block. **
|
|
*******************************************************************************
|
|
CHECK.CONTROL.KEYWORDS:
|
|
|
|
***************************************************************************
|
|
** Check for leading keywords. **
|
|
***************************************************************************
|
|
STATEMENT.CASE = OCONV(STATEMENT,FORMAT.CASE)
|
|
ON INDEX('BCEFLNORTUW',STATEMENT.CASE[1,1],1) + 1 GOTO CLAUSE.LABEL, ;* clauses
|
|
B.LABEL, ;* BEGIN CASE keyword
|
|
C.LABEL, ;* CASE keyword
|
|
E.LABEL, ;* END and ELSE keywords
|
|
F.LABEL, ;* FOR keyword
|
|
L.LABEL, ;* LOOP and LOCKED keywords
|
|
N.LABEL, ;* NEXT keyword
|
|
O.LABEL, ;* ON ERROR keyword
|
|
R.LABEL, ;* REPEAT keyword
|
|
T.LABEL, ;* THEN keyword
|
|
U.LABEL, ;* UNTIL keyword
|
|
W.LABEL ;* WHILE keyword
|
|
|
|
CLAUSE.LABEL:
|
|
***************************************************************************
|
|
** Indent the next line if this line ends in a clause. **
|
|
***************************************************************************
|
|
IF STATEMENT.CASE[9] = ' ON ERROR' OR STATEMENT.CASE[7] = ' LOCKED' OR STATEMENT.CASE[5] = ' THEN' OR STATEMENT.CASE[5] = ' ELSE' THEN
|
|
NEXT.INDENT.LEVEL += 1
|
|
END
|
|
RETURN
|
|
|
|
REPEAT.LABEL:
|
|
****************************************************************************
|
|
** Stop indenting for LOOP on the next line if this line ends in a repeat.**
|
|
****************************************************************************
|
|
IF STATEMENT.CASE[7] = ' REPEAT' THEN
|
|
NEXT.INDENT.LEVEL -= 1
|
|
END
|
|
RETURN
|
|
|
|
B.LABEL:
|
|
***************************************************************************
|
|
** Indent the next line by 2 if this line starts a CASE statement. **
|
|
** This is so CASE clauses can be indented form the BEGIN CASE. **
|
|
***************************************************************************
|
|
IF STATEMENT.CASE = 'BEGIN CASE' THEN
|
|
NEXT.INDENT.LEVEL += 2
|
|
RETURN
|
|
END
|
|
IF STATEMENT.CASE = 'BEGIN TRANSACTION' OR FIELD(STATEMENT.CASE," ",3) = 'ISOLATION' THEN
|
|
NEXT.INDENT.LEVEL += 1
|
|
RETURN
|
|
END
|
|
GOTO CLAUSE.LABEL:
|
|
|
|
C.LABEL:
|
|
***************************************************************************
|
|
** Outdent this line if it is a CASE clause. **
|
|
***************************************************************************
|
|
IF STATEMENT.CASE[1,5] = 'CASE ' THEN
|
|
INDENT.LEVEL -= 1
|
|
RETURN
|
|
END
|
|
GOTO CLAUSE.LABEL:
|
|
|
|
E.LABEL:
|
|
***************************************************************************
|
|
** Stop the indenting for the clause if this is an END **
|
|
***************************************************************************
|
|
IF STATEMENT.CASE = 'END' THEN
|
|
IF FIRST.STATEMENT.ON.LINE THEN
|
|
INDENT.LEVEL -= 1
|
|
END
|
|
NEXT.INDENT.LEVEL -= 1
|
|
RETURN
|
|
END
|
|
***************************************************************************
|
|
** Stop the indenting for the CASE statement if this is an END CASE **
|
|
***************************************************************************
|
|
IF STATEMENT.CASE = 'END CASE' THEN
|
|
NEXT.INDENT.LEVEL -= 2
|
|
INDENT.LEVEL -= 2
|
|
RETURN
|
|
END
|
|
IF STATEMENT.CASE = 'END TRANSACTION' THEN
|
|
NEXT.INDENT.LEVEL -= 1
|
|
INDENT.LEVEL -= 1
|
|
RETURN
|
|
END
|
|
***************************************************************************
|
|
** Stop the indenting for the clause and check for the start of more **
|
|
** clauses **
|
|
***************************************************************************
|
|
IF STATEMENT.CASE[1,4] = 'END ' THEN
|
|
NEXT.INDENT.LEVEL -= 1
|
|
INDENT.LEVEL -= 1
|
|
GOTO CLAUSE.LABEL:
|
|
END
|
|
***************************************************************************
|
|
** Handle ELSE clauses **
|
|
***************************************************************************
|
|
IF STATEMENT.CASE = 'ELSE' THEN
|
|
NEXT.INDENT.LEVEL += 1
|
|
RETURN
|
|
END
|
|
IF STATEMENT.CASE[1,5] = 'ELSE ' THEN
|
|
INDENT.LEVEL += 1
|
|
GOTO CLAUSE.LABEL:
|
|
END
|
|
GOTO CLAUSE.LABEL:
|
|
|
|
F.LABEL:
|
|
***************************************************************************
|
|
** Handle FOR statements. **
|
|
***************************************************************************
|
|
IF STATEMENT.CASE[1,4] = 'FOR ' THEN
|
|
*************************************************************************
|
|
** Check for FOR = type of constructs **
|
|
*************************************************************************
|
|
IF NOT(INDEX(VAR.IND,STATEMENT.CASE[5,1],1)) THEN
|
|
NEXT.INDENT.LEVEL += 1
|
|
RETURN
|
|
END
|
|
END
|
|
GOTO CLAUSE.LABEL:
|
|
|
|
L.LABEL:
|
|
***************************************************************************
|
|
** Handle LOOP statements. **
|
|
***************************************************************************
|
|
IF STATEMENT.CASE = 'LOOP' THEN
|
|
NEXT.INDENT.LEVEL += 1
|
|
RETURN
|
|
END
|
|
IF STATEMENT.CASE[1,5] = 'LOOP ' THEN
|
|
*************************************************************************
|
|
** Check for LOOP = type of constructs **
|
|
*************************************************************************
|
|
IF NOT(INDEX(VAR.IND,STATEMENT.CASE[6,1],1)) THEN
|
|
NEXT.INDENT.LEVEL += 1
|
|
GOTO REPEAT.LABEL:
|
|
END
|
|
END
|
|
***************************************************************************
|
|
** Handle LOCKED clauses **
|
|
***************************************************************************
|
|
IF STATEMENT.CASE = 'LOCKED' THEN
|
|
NEXT.INDENT.LEVEL += 1
|
|
RETURN
|
|
END
|
|
IF STATEMENT.CASE[1,7] = 'LOCKED ' THEN
|
|
INDENT.LEVEL += 1
|
|
GOTO CLAUSE.LABEL:
|
|
END
|
|
GOTO CLAUSE.LABEL:
|
|
|
|
N.LABEL:
|
|
***************************************************************************
|
|
** Handle NEXT statements. **
|
|
***************************************************************************
|
|
IF STATEMENT.CASE = 'NEXT' OR STATEMENT.CASE[1,5] = 'NEXT ' THEN
|
|
NEXT.INDENT.LEVEL -= 1
|
|
IF FIRST.STATEMENT.ON.LINE THEN
|
|
INDENT.LEVEL -= 1
|
|
END
|
|
RETURN
|
|
END
|
|
GOTO CLAUSE.LABEL:
|
|
|
|
O.LABEL:
|
|
***************************************************************************
|
|
** Handle ON ERROR clauses **
|
|
***************************************************************************
|
|
IF STATEMENT.CASE = 'ON ERROR' THEN
|
|
NEXT.INDENT.LEVEL += 1
|
|
RETURN
|
|
END
|
|
IF STATEMENT.CASE[1,9] = 'ON ERROR ' THEN
|
|
INDENT.LEVEL += 1
|
|
GOTO CLAUSE.LABEL:
|
|
END
|
|
GOTO CLAUSE.LABEL:
|
|
|
|
R.LABEL:
|
|
***************************************************************************
|
|
** Handle REPEAT statements. **
|
|
***************************************************************************
|
|
IF STATEMENT.CASE = 'REPEAT' THEN
|
|
NEXT.INDENT.LEVEL -= 1
|
|
INDENT.LEVEL -= 1
|
|
RETURN
|
|
END
|
|
GOTO CLAUSE.LABEL:
|
|
|
|
T.LABEL:
|
|
***************************************************************************
|
|
** Handle THEN clauses **
|
|
***************************************************************************
|
|
IF STATEMENT.CASE = 'THEN' THEN
|
|
NEXT.INDENT.LEVEL += 1
|
|
RETURN
|
|
END
|
|
IF STATEMENT.CASE[1,5] = 'THEN ' THEN
|
|
INDENT.LEVEL += 1
|
|
GOTO CLAUSE.LABEL:
|
|
END
|
|
GOTO CLAUSE.LABEL:
|
|
|
|
U.LABEL:
|
|
***************************************************************************
|
|
** Handle an UNTIL clause. **
|
|
***************************************************************************
|
|
IF STATEMENT.CASE[1,6] = 'UNTIL ' THEN
|
|
INDENT.LEVEL -= 1
|
|
GOTO REPEAT.LABEL:
|
|
END
|
|
GOTO CLAUSE.LABEL:
|
|
|
|
W.LABEL:
|
|
***************************************************************************
|
|
** Handle a WHILE clause. **
|
|
***************************************************************************
|
|
IF STATEMENT.CASE[1,6] = 'WHILE ' THEN
|
|
INDENT.LEVEL -= 1
|
|
GOTO REPEAT.LABEL:
|
|
END
|
|
GOTO CLAUSE.LABEL:
|
|
|
|
*******************************************************************************
|
|
** Exit the INFO/BASIC source formatting routine. **
|
|
*******************************************************************************
|
|
EXIT.FORMAT.BASIC:
|
|
RETURN
|
|
END
|
|
* END-CODE
|