Programma di esempio PROTFORM.PRT |
; PROTFORM
;
; Programma per Proteus
;
; (C) 1998-2003 Simone Zanella Productions
;
; Formatta un programma Proteus, aggiungendo l'indentazione
; standard e mantenendo la lunghezza delle righe a meno di 75
; caratteri; rudimentale controllo sintattico.
;
; Questa č l'indentazione standard (!ifdef..!endif come IF..FI):
;
; IF test REPEAT SWITCH exp [func]
; method method ON exp1
; ELSE CONTINUE method
; method BREAK ONC exp2
; FI UNTIL test method
; OTHER
; method
; OFF
;
; WHILE test FUNCTION name([par1, [par2..]])
; method method
; CONTINUE RETURN value
; BREAK
; LOOP
;
; FOR id = exp1 TO exp2 [STEP exp3]
; method
; CONTINUE
; BREAK
; NEXT
;
; I blocchi tra !bdoc e !edoc, come le costanti TEXT, sono mantenute
; immodificate.
; Inizializza
FUNCTION ONSTART()
IF STREQ(ARGV(3), "..")
CONSOLELN "Sintassi: " ARGV(1) " " ARGV(2) " sorgente destinazione"
CONSOLELN ""
CONSOLELN "Scopo: indentazione standard di sorgente in destinazione"
ABORT 0
FI
_IndLev = 0
_LastLine = ""
_LineLength = 75
; Aumenta l'indentazione per i metodi seguenti
_MI = VECCREATE("FOR","REPEAT","WHILE","IF","FUNCTION",\
"SWITCH","!ifdef","!ifndef")
_RetVar = "RETURN"
; Diminuisce l'indentazione per i metodi seguenti
_MD = VECCREATE("LOOP","UNTIL",_RetVar,"OFF",\
"FI","NEXT","!endif")
; De-indenta la linea corrente, mantenendo l'indentazione per
; le linee seguenti
_MS = VECCREATE("ON","ONC","ELSE","OTHER","!else")
; Ordina i vettori per l'utilizzo di BSEARCH
SORT(_MI, 4, 1)
SORT(_MD, 4, 1)
SORT(_MS, 4, 1)
_InDoc = 0
_InText = 0
RETURN
; Stampa le costanti TEXT verbatim
IF InText
S = RTRIM(L, " \t")
IF STREQ(RIGHT(S, STRLEN(TextTerm)), TextTerm)
InText = 0
FI
PRINTLN L
IGNORE
FI
; Stampa i blocchi !bdoc/!edoc verbatim
IF InDoc
S = TOKEN(LTRIM(L, " "), 1, " ")
SWITCH S STRIEQ
ON "!BDOC"
INC(@InDoc)
ON "!EDOC"
DEC(@InDoc)
IF LT(InDoc, 0)
CONSOLELN "Troppe direttive \"!EDOC\" (linea " N " )"
ABORT 1
FI
OFF
PRINTLN L
IGNORE
FI
PL = ALLTRIM(L, " ")
; Linea divisa - unisce
IF STREQ(RIGHT(PL, 1), "\\")
IF ISNOTEMPTY(LastLine)
LastLine = LastLine " "
FI
LastLine = LastLine LEFT(PL, DEC(STRLEN(PL)))
LastLine = RTRIM(LastLine, " ")
IF EOF
CONSOLELN "Linea non terminata (" N ")"
ABORT 1
FI
IGNORE
FI
; Aggiunge l'ultimo segmento di una linea divisa
IF ISNOTEMPTY(LastLine)
LastLine = LastLine " " PL
PL = RTRIM(LastLine, " ")
LastLine = ""
FI
OldLev = IndLev
; Nome del metodo
FTok = UPPER(TOKEN(PL, 1, " "))
; Cerca il metodo nei vettori
IF ISNOTEMPTY(FTok)
X = BSEARCH(MI, 4, FTok)
IF X
; Aumenta l'indentazione
INC(@IndLev)
ELSE
X = BSEARCH(MD, 4, FTok)
IF X
; Se RETURN, decresce l'indentazione solo alla
; chiusura della funzione
IF OR(EQ(IndLev, 1), STRINEQ(FTok, RetVar))
; Decresce l'indentazione
DEC(@IndLev)
FI
ELSE
X = BSEARCH(MS, 4, FTok)
IF X
; Decresce l'indentazione solo per questa linea
OldLev = DEC(IndLev)
ELSE
; Controlla se č una linea speciale (!BDOC, TEXT..)
SWITCH Ftok STRIEQ
ON "!EDOC"
CONSOLELN "Troppe direttive \"!EDOC\" (linea " N " )"
ABORT 1
ON "!BDOC"
INC(@InDoc)
PRINTLN L
IGNORE
ON "TEXT"
InText = 1
X = POSTOKEN(L, 3, " ")
IF STREQ(SUBSTR(L, X, 1), "=")
TextTerm = RESTFROM(L, POSTOKEN(L, 4, " "))
ELSE
TextTerm = RESTFROM(L, X)
FI
IF STREQ(LEFT(TextTerm, 1), "\"")
RTRIM(@TextTerm, " ")
STRIPQUOTES(@TextTerm)
CTRAN(@TextTerm)
ELSE
; Forza l'interpretazione di TextTerm come numero
ADD(@TextTerm, 0)
FI
PRINTLN L
IGNORE
OFF
FI
FI
FI
FI
; Errore di sintassi
IF LT(IndLev, 0)
CONSOLELN "Errore di sintassi nel programma " F "!"
ABORT 1
FI
; Indentazione aumentata - stampa la linea con la vecchia indentazione
IF GT(IndLev, OldLev)
NL = REPLICATE(" ", MUL(OldLev, 2))
ELSE
; Stampa la linea con l'indentazione corrente
NL = REPLICATE(" ", MUL(IndLev, 2))
FI
Line = NL PL
; Linea troppo lunga: divide
IF GT(STRLEN(Line), LineLength)
TL = STRDUP(Line)
RL = ""
P = STRLEN(Line)
; Se commento, divide solo se spazio
IF IN(LEFT(PL, 1), ";#")
WHILE GT(P, 0)
Car = RIGHT(TL, 1)
DEC(@P)
RL = Car RL
TL = LEFT(TL, P)
; La linea puņ essere troncata solo sugli spazi
IF LE(P, LineLength)
WHILE AND(P, STRNEQ(Car, " "))
Car = RIGHT(TL, 1)
DEC(@P)
RL = Car RL
TL = LEFT(TL, P)
LOOP
; Trovato uno spazio
IF P
PRINTLN TL " \\"
TL = RL
RL = ""
P = STRLEN(TL)
IF LE(P, LineLength)
BREAK
FI
CONTINUE
FI
FI
; Una linea senza spazi? Non troncarla, tienila.
IF NOT(P)
TL = RL
FI
LOOP
ELSE
WHILE GT(P, 0)
Car = CHOP(@TL)
DEC(@P)
RL = Car RL
; Fine stringa: trova l'inizio
IF STREQ(Car, "\"")
Car = CHOP(@TL)
DEC(@P)
RL = Car RL
WHILE AND(P, \
OR(STRNEQ(Car, "\""), \
STREQ(SUBSTR(TL, P, 1), "\\") ) )
Car = CHOP(@TL)
DEC(@P)
RL = Car RL
LOOP
IF AND(NOT(P), STRNEQ(LEFT(RL, 1), "\""))
CONSOLELN "Stringa non terminata alla linea " N "."
ABORT 1
FI
FI
IF NOT(P)
TL = RL
P = 0
ELSE
IF LT(P, LineLength)
IF IN(Car, ",() ")
; La linea puņ essere troncata qui
TL = TL Car
RL = RIGHT(RL, DEC(STRLEN(RL)))
PRINTLN TL IIF(STREQ(Car, " "), "\\", " \\")
TL = RL
RL = ""
P = STRLEN(TL)
IF LE(P, LineLength)
BREAK
FI
CONTINUE
FI
FI
FI
LOOP
FI
PRINTLN TL
ELSE
PRINTLN Line
FI