; STATC
;
; Program for Proteus
;
; (C) 1998-2004 Simone Zanella Productions
;
; Statistics on a C program.
;
; Report:
; - total number of lines;
; - total number and percentage of non-blank lines;
; - total number and percentage of lines including directives.
;
; Note: tokens "/*" and "*/" cannot appear inside strings.
; Implicit parameters: output to console
;!proteus -o
; Start up
FUNCTION ONSTART()
IF STREQ(ARGV(3), "..")
CONSOLELN "Syntax: " ARGV(1) " " ARGV(2) " filename.c"
CONSOLELN ""
CONSOLELN "Purpose: report statistics on the specified C program file"
ABORT 0
FI
; Flag: line is inside a remark?
_InRem = 0
; Total number of lines
_TNL = 0
; Number of directives
_TPPD = 0
; Number of non-blank lines (not counting directives)
_TML = 0
RETURN
; Increase line counter
INC(@TNL)
IF EQ(InRem, 0)
; Line begins out of remark
; Find start of remark
Pos = STRSTR(L, "/*")
; Duplicate line
PL = STRDUP(L)
; Is there a remark?
IF NEQ(Pos, 0)
PL3 = ""
REPEAT
; Pos is where the part out of remark ends
DEC(@Pos)
; PL2 is the part out of remark
PL2 = LEFT(PL, Pos)
; Append PL2 to PL3
IF ISNOTEMPTY(PL2)
PL3 = PL3 PL2
FI
; Pos2 is where remark ends (if on the same line)
Pos2 = STRSTR(PL, "*/")
; We are inside a remark; set flag
InRem = 1
; Remark ends in line?
IF NEQ(Pos2, 0)
; Reset flag
InRem = 0
; Pos2 is the start of the part out of remark
ADD(@Pos2, 2)
; Is there something to append?
IF NEQ(Pos2, 0)
PL = SUBSTR(PL, Pos2, STRLEN(PL))
ELSE
BREAK
FI
ELSE
BREAK
FI
Pos = STRSTR(PL, "/*")
UNTIL EQ(Pos, 0)
ELSE
PL3 = STRDUP(L)
FI
ELSE
; We are inside a remark
; Find the end of the remark
Pos = STRSTR(L, "*/")
; Create a copy of the line
PL = STRDUP(L)
; End of remark found
IF NEQ(Pos, 0)
PL3 = ""
REPEAT
; Pos is the start of the part out of remark
ADD(@Pos, 2)
; PL is the part outside of remark
PL = SUBSTR(PL, Pos, STRLEN(PL))
; Find in PL the start of the next remark
Pos2 = STRSTR(PL, "/*")
; Out of remark
InRem = 0
; Is there a new remark in the rest of the line?
IF NEQ(Pos2, 0)
; Pos2 is where the part out of remark ends
DEC(@Pos2)
; PL2 is the part out of remark
PL2 = LEFT(PL, Pos2)
; Append PL2 to PL3
IF ISNOTEMPTY(PL2)
PL3 = PL3 PL2
FI
; Find the next end of remark
Pos = STRSTR(PL, "*/")
; Found: update PL
IF NEQ(Pos, 0)
DEC(@Pos)
PL = SUBSTR(PL, Pos, STRLEN(PL))
ELSE
; We are inside a remark again
InRem = 1
FI
ELSE
; The rest of the line is out of remark
IF ISNOTEMPTY(PL)
PL3 = PL3 PL
FI
FI
Pos = STRSTR(PL, "*/")
UNTIL EQ(Pos, 0)
ELSE
; The line is inside a remark - ignore it (the rest of the
; program is skipped)
IF EOF
CONSOLELN "Unterminated remark, line " N
ABORT 1
ELSE
IGNORE
FI
FI
FI
; Remove blanks
PL3 = ALLTRIM(PL3, " ")
IF ISNOTEMPTY(PL3)
; Check if line is a directive
IF STREQ(LEFT(PL3, 1), "#")
INC(@TPPD)
ELSE
; Skip remarks in C++ style
IF NOT(STREQ(LEFT(PL3, 2), "//"))
INC(@TML)
FI
FI
FI
FUNCTION ONEND()
PRINTLN "File: " _F
PRINTLN "Total number of lines: " _TNL
T = ADD(_TML, _TPPD)
PN = MUL(FDIV(T, _TNL), 100)
PRINTLN "Total number of non-blank lines: " T \
" (" PFORMAT("02.02f", PN) "%)"
PN = MUL(FDIV(_TPPD, _TNL), 100)
PRINTLN "Number of directives: " _TPPD \
" (" PFORMAT("02.02f", PN) "%)"
RETURN