PACKET reporter routines DEFINES generate counts,
count on,
count off,
generate reports,
eliminate reports,
assert,
report on,
report off,
report:
(* Programm zur Ablaufverfolgung von ELAN Programmen. Das Programm
verfolgt Prozedur- und Refinementaufrufe ('trace') und erstellt
eine Haeufigkeitszaehlung ('frequency count') und beachtet 'assertions'.
Autor: Rainer Hahn
Letzte Aenderung: 11.01.84
Ausgabe der Gesamtaufrufe (Jan. 84)
*)
FILE VAR input file;
INT VAR zeilen nr,
type;
TEXT VAR zeile,
dummy,
dummy1,
symbol;
LET quadro fis = "####",
triple fis = "###",
double fis = "##",
tag = 1 ;
DATASPACE VAR ds := nilspace;
BOUND ROW max STRUCT (INT anzahl, BOOL proc) VAR zaehlwerk;
LET max = 2000;
(******************* gen report-Routinen ******************************)
PROC generate reports:
generate reports (last param)
END PROC generate reports;
PROC generate reports (TEXT CONST name):
disable stop;
gen trace statements (name);
IF is error AND error message = "ende"
THEN clear error
FI;
last param (name);
enable stop.
END PROC generate reports;
PROC gen trace statements (TEXT CONST name):
enable stop;
IF exists (name)
THEN input file := sequential file (modify, name)
ELSE errorstop ("input file does not exist")
FI;
input file modifizieren
END PROC gen trace statements;
(*************************** Test file modifizieren *****************)
PROC input file modifizieren:
zeilen nr := 1;
to first record (input file);
WHILE NOT eof (input file) REP
lese zeile;
IF triple fis symbol
THEN wandele in quadro fis
FI;
IF proc oder op symbol
THEN verarbeite operator oder prozedurkopf
ELIF refinement symbol
THEN verarbeite ggf refinements
FI;
down (input file)
END REP.
triple fis symbol:
pos (zeile, triple fis) > 0 AND
(pos (zeile, triple fis) <> pos (zeile, quadro fis)).
wandele in quadro fis:
change all (zeile, triple fis, quadro fis);
write record (input file, zeile).
proc oder op symbol:
pos (zeile, "PROC") > 0 OR pos (zeile, "OP") > 0.
verarbeite operator oder prozedurkopf:
IF NOT (pos (zeile, "END") > 0)
THEN scanne kopf;
insertiere trace anweisung
FI.
scanne kopf:
scan (zeile);
REP
next symbol (symbol, type);
IF ende der zeile gescannt
THEN vorwaerts;
lese zeile;
continue scan (zeile);
next symbol (symbol, type)
FI
UNTIL symbol = "PROC" OR symbol = "OP" END REP;
baue trace statement fuer kopf auf.
baue trace statement fuer kopf auf:
dummy := double fis;
dummy CAT "report(""";
dummy CAT symbol;
dummy CAT " ";
IF ende der zeile gescannt
THEN vorwaerts;
lese zeile;
continue scan (zeile)
FI;
next symbol (symbol, type);
dummy CAT symbol;
dummy CAT " ";
next symbol (symbol, type);
IF type = tag
THEN dummy CAT symbol
FI.
ende der zeile gescannt:
type >= 7.
insertiere trace anweisung:
WHILE pos (zeile, ":") = 0 REP
vorwaerts;
lese zeile
END REP;
schreibe zeile mit report statement.
refinement symbol:
INT CONST point pos := pos (zeile, ".") ;
point pos > 0 AND point pos >= length (zeile) - 1.
verarbeite ggf refinements:
ueberlies leere zeilen ;
IF ist wirklich refinement
THEN insertiere report fuer refinement
FI .
ueberlies leere zeilen :
REP
vorwaerts;
lese zeile
UNTIL pos (zeile, ""33"", ""254"", 1) > 0 PER .
ist wirklich refinement :
scan (zeile) ;
next symbol (symbol, type) ;
next symbol (symbol) ;
symbol = ":" AND type = tag .
insertiere report fuer refinement:
dummy := double fis;
dummy CAT "report(""";
dummy1 := subtext (zeile, 1, pos (zeile, ":") - 1);
dummy CAT dummy1;
schreibe zeile mit report statement
END PROC input file modifizieren;
PROC schreibe zeile mit report statement:
dummy CAT """);";
dummy CAT double fis;
IF doppelpunkt steht am ende der zeile
THEN (********** bei neuer Compiler-Version aendern:
fuelle zeile ggf auf 75 spalten auf;
zeile CAT dummy
die naechste drei zeilen dann loeschen **************)
down (input file);
insert record (input file);
write record (input file, dummy)
ELSE insert char (dummy, ":", 1);
change (zeile, ":", dummy);
write record (input file, zeile)
FI.
doppelpunkt steht am ende der zeile:
pos (zeile, ":") >= length (zeile) - 1.
(* Kommentarklammern beineuer Compiler Version hier weg:
fuelle zeile ggf auf 75 spalten auf:
IF length (zeile) < 75
THEN dummy1 := (75 - length (zeile)) * " ";
zeile CAT dummy1
FI.*)
END PROC schreibe zeile mit report statement;
PROC vorwaerts:
down (input file);
IF eof (input file)
THEN errorstop ("ende")
FI
END PROC vorwaerts;
PROC lese zeile:
read record (input file, zeile);
cout (zeilen nr);
zeilen nr INCR 1
END PROC lese zeile;
(************************ eliminate reports-Routinen ******************)
PROC eliminate reports:
eliminate reports (last param)
END PROC eliminate reports;
PROC eliminate reports (TEXT CONST name):
disable stop;
eliminate statements (name);
IF is error AND error message = "ende"
THEN clear error
FI;
last param (name);
enable stop.
END PROC eliminate reports;
PROC eliminate statements (TEXT CONST name):
enable stop;
IF exists (name)
THEN input file := sequential file (modify, name)
ELSE errorstop ("input file does not exist")
FI;
statements entfernen.
statements entfernen:
to first record (input file);
zeilen nr := 1;
WHILE NOT eof (input file) REP
lese zeile;
IF pos (zeile, double fis) > 0
THEN eliminiere zeichenketten in dieser zeile
ELSE down (input file)
FI
END REP.
eliminiere zeichenketten in dieser zeile:
INT VAR anfang := pos (zeile, double fis);
WHILE es ist noch etwas zu eliminieren REP
IF es ist ein quadro fis
THEN wandele es in ein triple fis
ELIF es ist ein triple fis
THEN lass diese sequenz stehen
ELSE entferne zeichenkette
FI
END REP;
IF zeile ist jetzt leer
THEN delete record (input file)
ELSE write record (input file, zeile);
down (input file)
FI.
es ist noch etwas zu eliminieren:
anfang > 0.
es ist ein quadro fis:
pos (zeile, quadro fis, anfang) = anfang.
wandele es in ein triple fis:
delete char (zeile, anfang);
anfang := pos (zeile, double fis, anfang + 3).
es ist ein triple fis:
pos (zeile, triple fis, anfang) = anfang.
lass diese sequenz stehen:
anfang := pos (zeile, triple fis, anfang + 1) + 3.
entferne zeichenkette:
INT VAR end := pos (zeile, double fis, anfang+2) ;
IF end > 0
THEN change (zeile, anfang, end + 1, "");
anfang := pos (zeile, double fis, anfang)
ELSE anfang := pos (zeile, double fis, anfang+2)
FI .
zeile ist jetzt leer:
pos (zeile, ""33"", ""254"", 1) = 0.
END PROC eliminate statements;
(********************** Trace-Routinen *******************************)
FILE VAR trace file;
BOOL VAR trace on, haeufigkeit on;
PROC report (TEXT CONST message):
IF NOT exists ("TRACE")
THEN trace file := sequential file (output, "TRACE");
trace on := TRUE;
haeufigkeit on := FALSE;
FI;
BOOL CONST ist prozedur ::
(pos (message, "PROC") > 0 OR pos (message, "OP") > 0);
IF trace on
THEN ablauf verfolgung
FI;
IF haeufigkeit on
THEN haeufigkeits zaehlung (ist prozedur)
FI.
ablauf verfolgung:
dummy := text (pcb (1));
dummy CAT ": ";
IF NOT ist prozedur
THEN dummy CAT " "
FI;
dummy CAT message;
putline (trace file, dummy).
END PROC report;
PROC report (TEXT CONST message, INT CONST value):
report (message, text (value))
END PROC report;
PROC report (TEXT CONST message, REAL CONST value):
report (message, text (value))
END PROC report;
PROC report (TEXT CONST message, TEXT CONST value):
dummy1 := message;
dummy1 CAT ": ";
dummy1 CAT value;
report (dummy1)
END PROC report;
PROC report (TEXT CONST message, BOOL CONST value):
dummy1 := message;
dummy1 CAT ": ";
IF value
THEN dummy1 CAT "TRUE"
ELSE dummy1 CAT "FALSE"
FI;
report (dummy1)
END PROC report;
PROC report on:
trace on := TRUE;
dummy1 := "REPORT ---> ON";
report (dummy1)
END PROC report on;
PROC report off:
dummy1 := "REPORT ---> OFF";
report (dummy1);
trace on := FALSE;
END PROC report off;
PROC assert (BOOL CONST value):
assert ("", value)
END PROC assert;
PROC assert (TEXT CONST message, BOOL CONST value):
dummy1 := "ASSERTION:";
dummy1 CAT message;
dummy1 CAT " ---> ";
IF value
THEN dummy1 CAT "TRUE"
ELSE line;
put ("ASSERTION:");
put (message);
put ("---> FALSE");
line;
IF yes ("weiter")
THEN dummy1 CAT "FALSE"
ELSE errorstop ("assertion failed")
FI
FI;
report (dummy1)
END PROC assert;
(************************** haeufigkeits-zaehlung ****************)
PROC count on:
report ("COUNT ---> ON");
haeufigkeit on := TRUE;
initialisiere haeufigkeit.
initialisiere haeufigkeit:
INT VAR i;
forget (ds);
ds := nilspace;
zaehlwerk := ds;
FOR i FROM 1 UPTO max REP
zaehlwerk [i] . anzahl := 0
END REP
END PROC count on;
PROC count off:
report ("COUNT ---> OFF");
haeufigkeit on := FALSE
END PROC count off;
PROC haeufigkeits zaehlung (BOOL CONST ist prozedur):
IF pcb (1) <= max
THEN zaehlwerk [pcb (1)]. anzahl INCR 1;
zaehlwerk [pcb (1)] . proc := ist prozedur
FI
END PROC haeufigkeits zaehlung;
PROC generate counts:
generate counts (last param)
END PROC generate counts;
PROC generate counts (TEXT CONST name):
disable stop;
insert counts (name);
last param (name);
enable stop.
END PROC generate counts;
PROC insert counts (TEXT CONST name):
enable stop;
IF exists (name)
THEN input file := sequential file (modify, name)
ELSE errorstop ("input file does not exist")
FI;
counts insertieren;
dataspace loeschen;
statistik ausgeben.
counts insertieren:
REAL VAR gesamt aufrufe :: 0.0,
proc aufrufe :: 0.0,
andere aufrufe :: 0.0;
zeilen nr := 1;
WHILE zeilennr <= lines (input file) REP
cout (zeilen nr);
IF zaehlwerk [zeilen nr] . anzahl > 0
THEN anzahl aufrufe in die eingabe zeile einfuegen;
aufrufe mitzaehlen
FI;
zeilen nr INCR 1
END REP.
anzahl aufrufe in die eingabe zeile einfuegen:
to line (input file, zeilen nr);
read record (input file, zeile);
dummy := double fis;
dummy1 := text (zaehlwerk [zeilen nr] . anzahl);
dummy CAT dummy1;
dummy CAT double fis;
change (zeile, 1, 0, dummy);
write record (input file, zeile).
aufrufe mitzaehlen:
gesamt aufrufe INCR real (zaehlwerk [zeilen nr] . anzahl);
IF zaehlwerk [zeilen nr] . proc
THEN proc aufrufe INCR real (zaehlwerk [zeilen nr] . anzahl)
ELSE andere aufrufe INCR real (zaehlwerk [zeilen nr] . anzahl)
FI.
dataspace loeschen:
forget (ds).
statistik ausgeben:
line (2);
put ("Anzahl der Gesamtaufrufe:");
put (gesamt aufrufe);
line;
put ("davon:");
line;
put (proc aufrufe); put ("Prozeduren oder Operatoren");
line;
put (andere aufrufe); put ("Refinements und andere");
line.
END PROC insert counts;
END PACKET reporter routines;