PACKET file DEFINES                            (* Autor: J.Liedtke *)
                                               (* Stand: 30.04.82  *)
       FILE ,
       := ,
       input ,
       output ,
       modify ,
       sequential file ,
       getline ,
       putline ,
       line ,
       reset ,
       eof ,
       put ,
       get ,
       page ,
       out ,
       eop ,
       close ,
       max line length ,
       max page length ,
       read record , 
       write record , 
       forward , 
       backward , 
       delete record , 
       insert record , 
       to first record ,
       to eof , 
       is first record , 
       headline ,
       copy attributes ,
       reorganize ,
       feldeditor ,
       feldout ,
       feldeinruecken ,
       pos ,
       change ,
       subtext ,
       sort :
 
 
 
TYPE FILE = STRUCT ( BOUND DATEI f ,
                     INT index, pointer, line counter,
                         mode, max line length, max page length,
                     BOOL edit status unchanged) ;
 
TYPE TRANSPUTDIRECTION = INT ;
 
LET closed = 1 ,
    in     = 2 ,
    outp   = 3 ,
    mod    = 4 ,
    end    = 5 ,
    escape = ""27"" ,

    nullzustand    = "    0    1    1" ,

    max length = 15 000 ;    (*  < maxint/2 because 2 * maxlength possible*)

 
TRANSPUTDIRECTION PROC input :
  TRANSPUTDIRECTION : ( in )
ENDPROC input ;
 
TRANSPUTDIRECTION PROC output :
  TRANSPUTDIRECTION : ( outp )
ENDPROC output ;
 
TRANSPUTDIRECTION PROC modify :
  TRANSPUTDIRECTION : ( mod )
ENDPROC modify ;
 
LET DATEI = ROW 4075 STRUCT (
                INT nachfolger, vorgaenger, index, fortsetzung,
                TEXT inhalt ) ;
 
LET anker = 2 ,
    freianker = 1 ;
 
TEXT VAR number word ;

FILE VAR result file ;
 
DATASPACE VAR scratch space ;
close ;
 
 
FILE PROC sequential file (TRANSPUTDIRECTION CONST mode) :
 
  IF CONCR (mode) = outp
    THEN close
  FI ;
  sequential file (mode, scratch space)
 
ENDPROC sequential file ;
 
FILE PROC sequential file (TRANSPUTDIRECTION CONST mode,
                           DATASPACE VAR ds) :
 
  IF type (ds) = 1002
    THEN result file.f := ds
  ELIF type (ds) < 0
    THEN result file.f := ds ;
         type (ds, 1002) ;
         datei initialisieren (CONCR (result file.f))
  ELSE   errorstop ("dataspace has wrong type") ;
         result file.f := scratch space
  FI ;
  result file.mode := CONCR (mode) ;
  reset (result file) ;
  result file.max line length := max line length (result file) ;
  result file.max page length := 0 ;
 
  result file .
 
ENDPROC sequential file ;
 
 
FILE PROC sequential file (TRANSPUTDIRECTION CONST mode,
                           TEXT CONST name ) :
 
  IF exists (name)
    THEN get dataspace if file
  ELIF CONCR (mode) <> in
    THEN get new file space
  ELSE errorstop ("input file not existing") ;
       result file.f := scratch space
  FI ;
  IF CONCR (mode) <> in
    THEN status (name, "") ;
         headline (result file, name)
  FI ;
  result file.mode := CONCR (mode) ;
  reset (result file) ;
  result file.max line length := max line length (result file) ;
  result file.max page length := 0 ;
 
  result file .
 
get new file space :
  result file.f := new (name) ;
  IF NOT is error
    THEN type (old (name), 1002) ;
         datei initialisieren ( CONCR (result file.f) )
  FI .
 
get dataspace if file :
  result file.f := old (name, 1002) .
 
ENDPROC sequential file ;
 
INT PROC max line length (FILE CONST file) :
 
  int (subtext (zustand, 16, 20)) .
 
zustand : 
  CONCR (file.f) (freianker).inhalt .

ENDPROC max line length ;
 
PROC max line length (FILE VAR file, INT CONST length) :
 
  replace (zustand, 16, text (length,5)) .
 
zustand : 
  CONCR (file.f) (freianker).inhalt .
 
ENDPROC max line length ;
 
PROC headline (FILE VAR file, TEXT CONST head) :
 
  CONCR (file.f)(anker).inhalt := head
 
ENDPROC headline ;
 
TEXT PROC headline (FILE VAR file) :
 
  CONCR (file.f)(anker).inhalt
 
ENDPROC headline ;
 
PROC copy attributes (FILE CONST source, FILE VAR dest) :

  dest attributes := source attributes ;
  reset edit status (dest) ;
  dest headline   := source headline .

dest attributes :   CONCR (dest.f) (freianker).inhalt .
source attributes : CONCR (source.f) (freianker).inhalt .

dest headline :     CONCR (dest.f) (anker).inhalt .
source headline :   CONCR (source.f) (anker).inhalt .

ENDPROC copy attributes ;


PROC input (FILE VAR file) :
 
  file.mode := in ;
  reset (file)
 
ENDPROC input ;
 
PROC output (FILE VAR file) :
 
  file.mode := outp ;
  reset (file)
 
ENDPROC output ;
 
PROC modify (FILE VAR file) :
 
  file.mode := mod ;
  reset (file)
 
ENDPROC modify ;
 
 
PROC putline (FILE VAR file, TEXT CONST record) :
 
  check mode (file, outp) ;
  line (file) ;
  CONCR (file.f)(file.index).inhalt := record ;
  file.pointer := max length
 
ENDPROC putline ;
 
 
PROC getline (FILE VAR file, TEXT VAR record) :
 
  check mode (file, in) ;
  line (file) ;
  record := CONCR (file.f)(file.index).inhalt ;
  file.pointer := max length
 
ENDPROC getline ;
 
 
PROC line (FILE VAR file) :
 
  file.index := CONCR (file.f) (file.index).nachfolger ;
  file.pointer  := 0 ;
  IF file.mode = in
    THEN check eof
  ELIF file.mode = outp
    THEN satz erzeugen (CONCR (file.f), file.index) ;
         CONCR (file.f)(file.index).inhalt := "" ;
         perhaps implicit page feed
  FI .
 
check eof :
  IF eof
    THEN file.mode := end
  FI .
 
eof : CONCR (file.f)(file.index).nachfolger = anker .
 
perhaps implicit page feed :
  file.line counter INCR 1 ;
  IF file.line counter = file.max page length
    THEN page (file)
  FI .
 
ENDPROC line ;
 
PROC check mode (FILE CONST file, INT CONST mode) :
 
  IF file.mode = mode
      THEN LEAVE check mode
  ELIF file.mode = closed
      THEN errorstop ("file not open")
  ELIF file.mode = mod
      THEN errorstop ("operation not in transputdirection 'modify'")
  ELIF mode = mod
      THEN errorstop ("operation only in transputdirection 'modify'")
  ELIF file.mode = end
      THEN IF eof (file) THEN errorstop ("input after end of file") FI
  ELIF mode = in
      THEN errorstop ("input access to output file")
  ELIF mode = outp
      THEN errorstop ("output access to input file")
  FI
 
ENDPROC check mode ;
 
PROC reset (FILE VAR file) :
 
  file.pointer := max length ;
  file.line counter := 0 ;
  file.edit status unchanged := TRUE ;
  initialize file index ;
  set correct file mode .
 
initialize file index :
  IF file.mode = outp
    THEN file.index := last record
    ELSE file.index := anker
  FI .
 
set correct file mode :
  IF file.mode = end
    THEN file.mode := in
  FI ;
  IF file.mode = in AND empty file
    THEN file.mode := end
  FI .
 
last record : CONCR (file.f) (anker).vorgaenger .
 
empty file  : CONCR (file.f) (anker).nachfolger = anker .
 
ENDPROC reset ;
 
BOOL PROC eof (FILE CONST file) :
 
  IF file.mode = end
    THEN end of record
  ELIF file.mode = mod
    THEN file.index = anker
    ELSE FALSE
  FI .
 
end of record :
  file.pointer >= length (CONCR (file.f)(file.index).inhalt) .
 
ENDPROC eof ;
 
PROC line (FILE VAR file, INT CONST lines) :
 
  check mode (file, outp) ;
  INT VAR i ;
  FOR i FROM 1 UPTO lines REP
    line (file)
  PER
 
ENDPROC line ;
 
PROC page (FILE VAR file) :
 
  file.line counter := 0 ;
  putline (file, "#page")
 
ENDPROC page ;
 
BOOL PROC eop (FILE CONST file) :
 
  CONCR (file.f)(file.index).inhalt = "#page"
 
ENDPROC eop ;
 
PROC put (FILE VAR file, TEXT CONST word) :
 
  check mode (file, outp) ;
  IF file.pointer + LENGTH word >= file.max line length
    THEN line (file)
  FI ;
  put word (CONCR (file.f)(file.index).inhalt, word, file.pointer)
 
ENDPROC put ;
 
PROC put word (TEXT VAR record, TEXT CONST word, INT VAR pointer) :
 
  IF pointer > 0
    THEN record CAT " " ;
  FI ;
  record CAT word ;
  pointer := LENGTH record
 
ENDPROC put word ;
 
PROC put (FILE VAR f, INT CONST value) :
 
  put (f, text (value) )
 
ENDPROC put ;
 
PROC put (FILE VAR f, REAL CONST real) :
 
  put (f, text (real) )
 
ENDPROC put ;
 
PROC out (FILE VAR file, TEXT CONST word) :
 
  check mode (file, outp) ;
  IF file.pointer + LENGTH word >= file.max line length
    THEN line (file)
  FI ;
  record CAT word ;
  file.pointer INCR LENGTH word .
 
record : CONCR (file.f)(file.index).inhalt .
 
ENDPROC out ;
 
PROC get (FILE VAR file, TEXT VAR word, TEXT CONST separator) :
 
  check mode (file, in) ;
  get word (CONCR (file.f)(file.index).inhalt, word,
            file.pointer, max length, separator)
 
ENDPROC get ;
 
PROC get (FILE VAR file, TEXT VAR word, INT CONST max length) :
 
  check mode (file, in) ;
  get word (CONCR (file.f)(file.index).inhalt, word,
            file.pointer, max length, "")
 
ENDPROC get ;
 
PROC get (FILE VAR file, TEXT VAR word) :
 
  check mode (file, in) ;
  next word (file, CONCR (file.f)(file.index).inhalt, word)
 
ENDPROC get ;
 
PROC next word (FILE VAR file, TEXT CONST record, TEXT VAR word) :
 
  get next non blank char ;
  IF char found
    THEN get word (record, word, file.pointer, max length, " ")
  ELIF last line of file
    THEN word := "" ;
         file.pointer := max length
    ELSE line (file) ;
         get (file, word)
  FI .
 
get next non blank char :
  TEXT VAR char ;
  REP
    file.pointer INCR 1 ;
    char := record SUB file.pointer
  UNTIL char <> " " PER ;
  file.pointer DECR 1 .
 
char found :  char <> "" .
 
last line of file :
  CONCR (file.f) (anker).nachfolger = anker .
 
ENDPROC next word ;
 
PROC get (FILE VAR f, INT VAR number) :
 
  get (f, number word) ;
  number := int (number word)
 
ENDPROC get ;
 
PROC get (FILE VAR f, REAL VAR number) :
 
  get (f, number word) ;
  number := real (number word)
 
ENDPROC get ;
 
PROC get word (TEXT CONST record, TEXT VAR word, INT VAR pointer,
               INT CONST max length, TEXT CONST separator) :
 
  INT VAR end of word := pos (record, separator, pointer+1) - 1 ;
  IF end of word < 0
    THEN end of word := pointer + max length
  FI ;
  word := subtext (record, pointer+1, end of word) ;
  pointer := end of word + 1
 
ENDPROC get word ;
 
PROC close (FILE VAR file) :
 
  file.mode := closed
 
ENDPROC close ;
 
PROC close :
 
  disable stop ;
  forget (scratch space) ;
  scratch space := nilspace
 
ENDPROC close ;
 
INT PROC max page length (FILE CONST file) :
  file.max page length
ENDPROC max page length ;
 
PROC max page length (FILE VAR file, INT CONST length) :
  file.max page length := length
ENDPROC max page length
 
 
PROC read record (FILE CONST file, TEXT VAR record) : 
 
  check mode (file, mod) ;
  record := CONCR (file.f) (file.index).inhalt 
 
ENDPROC read record ; 
 
PROC write record (FILE VAR file, TEXT CONST record) : 
 
  check mode (file, mod) ;
  CONCR (file.f) (file.index).inhalt := record 
 
ENDPROC write record ; 
 
PROC forward (FILE VAR file) : 
 
  check mode (file, mod) ;
  IF file.index <> anker 
    THEN file.index := CONCR (file.f) (file.index).nachfolger 
    ELSE errorstop ("forward at eof") 
  FI 
 
ENDPROC forward ; 
 
PROC backward (FILE VAR file) : 
 
  check mode (file, mod) ;
  file.index := CONCR (file.f) (file.index).vorgaenger ; 
  IF file.index = anker 
    THEN to first record (file) ; 
         errorstop ("backward at first record") 
  FI 
 
ENDPROC backward ; 
 
PROC delete record (FILE VAR file) : 
 
  check mode (file, mod) ;
  IF file.edit status unchanged
    THEN reset edit status (file)
  FI ;
  satz loeschen (CONCR (file.f), file.index) 
 
ENDPROC delete record ; 
 
PROC insert record (FILE VAR file) : 
 
  check mode (file, mod) ;
  IF file.edit status unchanged
    THEN reset edit status (file)
  FI ;
  satz erzeugen (CONCR (file.f), file.index) 
 
ENDPROC insert record ; 
 
PROC to first record (FILE VAR file) : 
 
  check mode (file, mod) ;
  file.index := CONCR (file.f) (anker).nachfolger 
 
ENDPROC to first record ; 
 
PROC to eof (FILE VAR file) : 
 
  check mode (file, mod) ;
  file.index := anker 
 
ENDPROC to eof ; 
 
BOOL PROC is first record (FILE CONST file) : 
 
  file.index = CONCR (file.f) (anker).nachfolger 
 
ENDPROC is first record ; 
 
PROC reset edit status (FILE VAR file) :
 
  replace (zustand, 1, nullzustand) ;
  file.edit status unchanged := FALSE .
 
zustand :  CONCR (file.f)(freianker).inhalt .
 
ENDPROC reset edit status ;
 
 
FILE VAR scratch , file ;
TEXT VAR record ;
 
LET esc = ""27"" ;
 
PROC reorganize (TEXT CONST file name) :
 
  IF exists (file name)
    THEN last param (file name) ;
         reorganize file
    ELSE errorstop ("file does not exist")
  FI .
 
reorganize file :
  scratch := sequential file (output) ;
  headline (scratch, file name) ;
  IF format 15
    THEN set to 16 file type ; 
         file := sequential file (input, file name)
    ELSE file := sequential file (input, file name) ;
         copy attributes (file, scratch) 
  FI ;
 
  disable stop ;

  INT VAR counter := 0 ;
  WHILE NOT eof (file) REP
    getline (file, record) ;
    putline (scratch, record) ;
    counter INCR 1 ;
    cout (counter) ;
    IF is incharety (escape) OR is error
      THEN close ;
           LEAVE reorganize
    FI
  PER ;
  forget file ;
  copy (scratch space, file name) ;
  close .
 
forget file :
  BOOL CONST old status := command dialogue ;
  command dialogue (FALSE) ;
  forget (file name) ;
  command dialogue (old status) .
 
format 15 :  type (old (file name)) = 1001 .

set to 16 file type :
  type (old (file name), 1002) .

ENDPROC reorganize ;
 
PROC reorganize :
 
  reorganize (last param)
 
ENDPROC reorganize ;
 
PROC feldout (FILE CONST file, TEXT CONST satz) :
 
  feldout ( CONCR (file.f) (file.index).inhalt )
 
ENDPROC feldout ;
 
PROC feldeinruecken (FILE CONST file, TEXT CONST satz) :
 
  feldeinruecken ( CONCR (file.f) (file.index).inhalt )
 
ENDPROC feldeinruecken ;
 
PROC feldeditor (FILE VAR file, TEXT CONST satz) :
 
  feldeditor ( CONCR (file.f) (file.index).inhalt )
 
ENDPROC feldeditor ;
 
INT PROC pos (FILE CONST file, TEXT CONST pattern, INT CONST from) :
 
  pos ( CONCR (file.f) (file.index).inhalt, pattern, from )
 
ENDPROC pos ;
 
PROC change (FILE VAR file, INT CONST from, to, TEXT CONST new) :
 
  change ( CONCR (file.f) (file.index).inhalt, from, to, new )
 
ENDPROC change ;
 
TEXT PROC subtext (FILE CONST file, INT CONST from) :
 
  record := subtext ( CONCR (file.f) (file.index).inhalt, from ) ;
  record
 
ENDPROC subtext ;
 
TEXT PROC subtext (FILE CONST file, INT CONST from, to) :
 
  record := subtext ( CONCR (file.f) (file.index).inhalt, from, to ) ;
  record
 
ENDPROC subtext ;
 
(*  sortieren sequentieller Dateien                  Autor: P.Heyderhoff *) 
                                                  (* Stand: 14.11.80     *) 
 
BOUND DATEI VAR datei; 
INT  VAR sortierstelle, sortanker, byte;
TEXT VAR median, tausch ;
 
PROC sort (TEXT CONST dateiname) : 
     sortierstelle := feldanfang; sort (dateiname, "")
 END PROC sort; 
 
PROC sort (TEXT CONST dateiname, INT CONST sortieranfang) : 
     sortierstelle := sortieranfang; sort (dateiname, "")
 END PROC sort; 
 
PROC sort (TEXT CONST dateiname, feldname) :
     IF   exists (dateiname)
     THEN datei := old (dateiname); 
          IF   CONCR(datei) (freianker).nachfolger <> freianker 
          THEN reorganize (dateiname) 
          FI ; 
          sortanker := 3;
          IF   feldname = ""
          THEN byte := 0
          ELSE feldname in feldnummer uebersetzen
          FI;
          quicksort(sortanker, CONCR(datei)(freianker).fortsetzung-1) 
     FI .
feldname in feldnummer uebersetzen :
    byte := pos (CONCR(datei) (sortanker).inhalt, feldname);
    IF   byte > 0
    THEN byte := pos (CONCR(datei) (sortanker).inhalt, code(255-byte))
    FI;
    IF   byte = 0 
    THEN errorstop ("sort: feldname"); LEAVE sort
    FI ; sortanker INCR 1 .
 END PROC sort; 
 
PROC quicksort ( INT CONST anfang, ende ) : 
     IF   anfang < ende 
     THEN INT VAR p,q; 
          spalte    (anfang, ende, p, q); 
          quicksort (anfang, q); 
          quicksort (p, ende)    FI 
 END PROC quicksort; 
 
PROC spalte (INT CONST anfang, ende, INT VAR p, q): 
     fange an der seite an und waehle den median; 
     ruecke p und q so dicht wie moeglich zusammen; 
     hole ggf median in die mitte . 
 
   fange an der seite an und waehle den median : 
     p := anfang; q := ende ; 
     INT CONST m :: (p + q) DIV 2 ; 
     median := subtext(datei m, merkmal m) . 
 
   ruecke p und q so dicht wie moeglich zusammen : 
     REP schiebe p und q so weit wie moeglich auf bzw ab; 
         IF p < q THEN vertausche die beiden FI 
     UNTIL p > q END REP . 
 
   vertausche die beiden : 
     tausch := datei p; datei p := datei q; datei q := tausch; 
     p INCR 1; q DECR 1 . 
 
   schiebe p und q so weit wie moeglich auf bzw ab : 
     WHILE p kann groesser werden REP p INCR 1 END REP; 
     WHILE q kann kleiner  werden REP q DECR 1 END REP . 
 
   p kann groesser werden : 
     IF p <= ende THEN subtext (datei p, merkmal p) <= median ELSE FALSE FI . 
 
   q kann kleiner werden : 
     IF q >= anfang THEN subtext(datei q,merkmal q) >= median ELSE FALSE FI . 
 
   hole ggf median in die mitte : 
     IF   m < q THEN vertausche m und q 
     ELIF m > p THEN vertausche m und p FI . 
 
   vertausche m und q : 
     tausch := datei m; datei m := datei q; datei q := tausch; q DECR 1 . 
 
   vertausche m und p : 
     tausch := datei m; datei m := datei p; datei p := tausch; p INCR 1 . 
 
   merkmal m :
     IF byte = 0 THEN sortierstelle  ELSE 255 - code (datei m SUB byte) FI .
 
   merkmal p :
     IF byte = 0 THEN sortierstelle  ELSE 255 - code (datei p SUB byte) FI .
 
   merkmal q :
     IF byte = 0 THEN sortierstelle  ELSE 255 - code (datei q SUB byte) FI .
 
   datei m :  CONCR(datei)(m).inhalt . 
   datei p :  CONCR(datei)(p).inhalt . 
   datei q :  CONCR(datei)(q).inhalt . 
 
END PROC spalte; 
 
 
(*********** schrott ************)
 
OP := (FILE VAR a, FILE CONST b) :
  EXTERNAL 294
ENDOP := ;
 
PROC becomes (ROW 8 INT VAR a, b) :
  INTERNAL 294 ;
  a := b
ENDPROC becomes ;
 
PROC datei initialisieren (DATEI VAR datei) : 
  EXTERNAL 290 ;
END  PROC datei initialisieren; 
 
PROC satz erzeugen (DATEI VAR datei, INT VAR satz): 
  EXTERNAL 291;
END  PROC satz erzeugen; 
 
PROC satz loeschen (DATEI VAR datei, INT VAR satz): 
  EXTERNAL 292 ;
END  PROC satz loeschen; 
 
ENDPACKET file ;