diff options
| author | Lars-Dominik Braun <lars@6xq.net> | 2019-02-04 13:09:03 +0100 | 
|---|---|---|
| committer | Lars-Dominik Braun <lars@6xq.net> | 2019-02-04 13:09:03 +0100 | 
| commit | 04e68443040c7abad84d66477e98f93bed701760 (patch) | |
| tree | 2b6202afae659e773bf6916157d23e83edfa44e3 /system/base/1.7.5/src/file | |
| download | eumel-src-04e68443040c7abad84d66477e98f93bed701760.tar.gz eumel-src-04e68443040c7abad84d66477e98f93bed701760.tar.bz2 eumel-src-04e68443040c7abad84d66477e98f93bed701760.zip  | |
Initial import
Diffstat (limited to 'system/base/1.7.5/src/file')
| -rw-r--r-- | system/base/1.7.5/src/file | 2122 | 
1 files changed, 2122 insertions, 0 deletions
diff --git a/system/base/1.7.5/src/file b/system/base/1.7.5/src/file new file mode 100644 index 0000000..530dcb3 --- /dev/null +++ b/system/base/1.7.5/src/file @@ -0,0 +1,2122 @@ +(* ------------------- VERSION 35     02.06.86 ------------------- *) +PACKET file handling DEFINES     (* Autoren: J.Liedtke, D.Martinek *) +       (***********)  +  +       FILE, +       :=, +       sequential file, +       reorganize, +       input, +       output, +       modify, +       close, +       putline, +       getline, +       put, +       get, +       write , +       line, +       reset, +       down, +       up, +       downety, +       uppety, +       pattern found, +       to first record, +       to line, +       to eof, +       insert record, +       delete record, +       read record, +       write record, +       is first record, +       eof, +       line no, +       FRANGE, +       set range, +       reset range , +       remove, +       clear removed, +       reinsert, +       max line length, +       edit info, +       line type , +       copy attributes , +       headline, +       put tabs, +       get tabs, +       col, +       word, +       at, +       removed lines, +       exec, +       pos , +       len , +       subtext , +       change , +       lines , +       segments , +       mark , +       mark line no , +       mark col , +       set marked range , +       split line , +       concatenate line , +       prefix , +       sort , +       lexsort : + + +(**********************************************************************) +(*                                                                    *) +(*  Terminologie:                                                     *) +(*                                                                    *) +(*                                                                    *) +(*     ATOMROW       Menge aller Atome eines FILEs.                   *) +(*                   Die einzelnen Atome haben zwar eine Position     *) +(*                   im Row, aber in dieser Betrachtung keine         *) +(*                   logische Reihenfolge.                            *) +(*                                                                    *) +(*     ATOM          Basiselement, kann eine Zeile der Datei und die  *) +(*                   zugehoerige Verwaltungsinformation aufnehmen     *) +(*                                                                    *) +(*     CHAIN         Zyklisch geschlossene Kette von Segmenten.       *) +(*                                                                    *) +(*     SEGMENT       Teilbereich des Atomrows, enthaelt 1 oder mehr   *) +(*                   zusammenhaengende Atoms.                         *) +(*                   Jedes Segment hat ein Vorgaenger- und ein        *) +(*                   Nachfolgersegment.                               *) +(*                   Jedes Segment enthaelt einen logisch zumsammen-  *) +(*                   haengenden Teile einer Sequence.                 *) +(*                                                                    *) +(*     SEQUENCE      Logische Folge von Lines.                        *) +(*                   Jede Sequence ist Teil einer Chain oder besteht  *) +(*                   vollstaendig daraus:                             *) +(*                                                                    *) +(*                        SEG1--SEG2--SEG3--SEG4--SEG5                *) +(*                          :----sequence----:                        *) +(*                                                                    *) +(*                   Die 'Reihenfolge' ebenso wie die 'Anzahl' der    *) +(*                   Lines ist eine wesentliche Eigenschaft einer     *) +(*                   Sequence.                                        *) +(*                                                                    *) +(*     LINE          Ein Atom als Element ein Sequence betrachtet.    *) +(*                                                                    *) +(*                                                                    *) +(**********************************************************************) +(*                                                                    *) +(* Eigenschaften:                                                     *) +(*                                                                    *) +(*     Folgende Mengen bilden eine Zerlegung (im math. Sinn) einer    *) +(*     gesamten Datei:                                                *) +(*                        used segment chain                          *) +(*                        scratch segment chain                       *) +(*                        free segment chain                          *) +(*                        unused tail                                 *) +(*                                                                    *) +(*     Fuer jedes X aus (used, scratch, free) gelten:                 *) +(*                                                                    *) +(*     'X sequence' ist echte Teilmenge von 'X segment chain'.        *) +(*                                                                    *) +(*                       (Daraus folgt, es gibt keine leere 'chain'.) *) +(*                                                                    *) +(*     'X segment chain' ist zyklisch gekettet.                       *) +(*                                                                    *) +(*     Alle Atome von 'X segment chain' haben definierten Inhalt.     *) +(*                                                                    *) +(**********************************************************************) +  +  +LET file size    = 4075 , +    nil          = 0 , +  +    free root    = 1 , +    scratch root = 2 , +    used root    = 3 , +    first unused = 4 ; +  +  +LET SEQUENCE = STRUCT (INT index, segment begin, segment end, +                       INT line no, lines), +    SEGMENT  = STRUCT (INT succ, pred, end), +    ATOM     = STRUCT (SEGMENT seg, INT type, TEXT line), +    ATOMROW  = ROW filesize ATOM, +  +    LIST     = STRUCT (SEQUENCE used, INT prefix lines, postfix lines, +                       SEQUENCE scratch, free, INT unused tail, +                       INT mode, col, limit, edit info, mark line, mark col, +                       ATOMROW atoms); +  +TYPE FILE = BOUND LIST ; +  +TYPE FRANGE = STRUCT (INT pre, post, BOOL pre was split, post was split); + + +OP := (FRANGE VAR left, FRANGE CONST right): +  CONCR (left) := CONCR (right) +ENDOP := ; + + +OP := (FILE VAR left, FILE CONST right): +  EXTERNAL 260 +END OP :=; + + +PROC becomes (INT VAR a, b) : +  INTERNAL 260  ; +  a := b +END PROC becomes; +  +  +PROC initialize (FILE VAR f) : +  +   f.used     := SEQUENCE : (used root, used root, used root, 1, 0); +   f.prefix lines  := 0; +   f.postfix lines := 0; +   f.free     := SEQUENCE : (free root, free root, free root, 1, 0); +   f.scratch  := SEQUENCE : (scratch root, scratch root, scratch root, 1, 0); +   f.unused tail := first unused; + +   f.limit := 77; +   f.edit info := 0; +   f.col := 1 ; +   f.mark line := 0 ; +   f.mark col := 0 ; + +   INT VAR i; +   FOR i FROM 1 UPTO 3 REP +     root (i).seg  := SEGMENT : (i, i, i); +     root (i).line := "" +   PER; +   put tabs (f, "") . +  +root : f.atoms . +  +END PROC initialize; +  +  +(**********************************************************************) +(*                                                                    *) +(*        Segment Handler         (SEGMENTs & CHAINs)                 *) +(*                                                                    *) +(**********************************************************************) + +INT PROC segs (SEQUENCE CONST s, ATOMROW CONST atom) : + +  INT VAR number of segments := 0 , +  actual segment := s.segment begin ; +  REP +    number of segments INCR 1 ; +    actual segment := atom (actual segment).seg.succ +  UNTIL actual segment = s.segment begin PER ; +  number of segments . + +ENDPROC segs ; + +  +PROC next segment (SEQUENCE VAR s, ATOMROW CONST atom) : +  +  disable stop; +  s.line no INCR (s.segment end - s.index + 1); +  INT CONST new segment index := actual segment.succ; +  s.segment begin := new segment index; +  s.segment end   := new segment.end; +  s.index         := new segment index . + +actual segment :  atom (s.segment begin).seg . +new segment :     atom (new segment index).seg . +  +END PROC next segment; +  +  +PROC previous segment (SEQUENCE VAR s, ATOMROW CONST atom) : + +  disable stop; +  s.line no DECR (s.index - s.segment begin + 1); +  INT CONST new segment index := actual segment.pred; +  s.segment begin := new segment index; +  s.segment end   := new segment.end; +  s.index         := s.segment end . +  +actual segment :  atom (s.segment begin).seg . +new segment :     atom (new segment index).seg . +  +END PROC previous segment; +  +  +PROC split segment (SEQUENCE VAR s, ATOMROW VAR atom) : + +  disable stop; +  IF not at segment top +    THEN split segment at actual position +  FI . + +split segment at actual position : +  INT CONST pred index   := s.segment begin, +            actual index := s.index, +            succ index   := pred.succ; + +  actual.pred  := pred index; +  actual.succ  := succ index; +  actual.end   := s.segment end; +  +  pred.succ    := actual index; +  pred.end     := actual index - 1; +  +  succ.pred    := actual index; +  +  s.segment begin := actual index . +  +not at segment top : s.index > s.segment begin . + +pred   : atom (pred index).seg . +  +actual : atom (actual index).seg . +  +succ   : atom (succ index).seg . +  +END PROC split segment; +  + +PROC join segments (ATOMROW VAR atom, +                    INT CONST first index, INT VAR second index) : +  +  disable stop; +  IF first seg.end + 1 = second index +    THEN attach second to first segment +    ELSE link first to second segment +  FI . +  +attach second to first segment : +  first seg.end  := second seg.end; +  INT VAR successor of second := second seg.succ; +  IF successor of second = second index +    THEN first seg.succ := first index +    ELSE join segments (atom, first index, successor of second) +  FI; +  second index := first index . +  +link first to second segment : +  first seg.succ  := second index; +  second seg.pred := first index . +  +first seg :  atom (first index).seg . +second seg : atom (second index).seg . +  +END PROC join segments; +  +  +PROC delete segments (SEQUENCE VAR from, ATOMROW VAR atom, +                      INT CONST first index, last index, lines) : +  +  determine surrounding segments and new atom index; +  join surrounding segments; +  update sequence descriptor . +  +determine surrounding segments and new atom index : +  INT VAR pred index   := first seg.pred, +          actual index := last seg.succ; +  from.index := actual index . +  +join surrounding segments : +  join segments (atom, pred index, actual index) . +  +update sequence descriptor : +  from.segment begin := actual index; +  from.segment end := actual seg.end; +  from.lines DECR lines . +  +actual seg :  atom (actual index).seg . +first seg :   atom (first index).seg . +last seg :    atom (last index).seg . +  +END PROC delete segments; +  +  +PROC insert segments (SEQUENCE VAR into, ATOMROW VAR atom, +                      INT CONST first index, last index, lines) : +  +  join into sequence and new segments; +  update sequence descriptor . +  +join into sequence and new segments : +  INT VAR actual index := into.index, +          pred index   := actual seg.pred; +  join segments (atom, last index, actual index); +  actual index := first index; +  join segments (atom, pred index, actual index) . +  +update sequence descriptor : +  into.index := first index; +  into.segment begin := actual index; +  into.segment end := actual seg.end; +  into.lines INCR lines . +  +actual seg :  atom (actual index).seg . +  +END PROC insert segments; +  +  +PROC next atom (SEQUENCE VAR s, ATOMROW CONST atom) : +  +  IF s.line no <= s.lines +    THEN to next atom +    ELSE errorstop ("'down' nach Dateiende") +  FI . +  +to next atom : +  disable stop; +  IF s.index = s.segment end +    THEN next segment (s, atom) +    ELSE s.index INCR 1; +         s.line no INCR 1 +  FI +  +END PROC next atom; +  +  +PROC next atoms (SEQUENCE VAR s, ATOMROW CONST atom, INT CONST times) : +  +  INT CONST destination line := min (s.line no + times, s.lines + 1); +  jump upto destination segment; +  position within destination segment . +  +jump upto destination segment : +  WHILE s.line no + length of actual segments tail < destination line REP +    next segment (s, atom); +  PER . +  +position within destination segment : +  disable stop; +  s.index INCR (destination line - s.line no); +  s.line no := destination line . +  +length of actual segments tail :   s.segment end - s.index . +  +END PROC next atoms; +  +  +PROC previous atom (SEQUENCE VAR s, ATOMROW CONST atom) : +  +  IF s.line no > 1 +    THEN to previous atom +    ELSE errorstop ("'up' am Dateianfang") +  FI . +  +to previous atom : +  disable stop; +  IF s.index = s.segment begin +    THEN previous segment (s, atom) +    ELSE s.index DECR 1; +         s.line no DECR 1 +  FI +  +END PROC previous atom; +  +  +PROC previous atoms (SEQUENCE VAR s, ATOMROW CONST atom, INT CONST times) : +  +  INT CONST destination line := max (1, s.line no - times); +  jump back to destination segment; +  position within destination segment . +  +jump back to destination segment : +  WHILE s.line no - length of actual segments head > destination line REP +    previous segment (s, atom); +  PER . +  +position within destination segment : +  disable stop; +  s.index DECR (s.line no - destination line); +  s.line no := destination line . +  +length of actual segments head :   s.index - s.segment begin . +  +END PROC previous atoms; + + +TEXT VAR pre, pat, pattern0; +INT VAR last search line ; + +PROC search down (SEQUENCE VAR s, ATOMROW CONST atom, TEXT CONST pattern, +                  INT CONST max lines, INT VAR column) : + +  INT CONST start col := column , +            start line := s.lineno ; +  last search line := min (s.lines, s.lineno + max lines) ; +  pre:= somefix (pattern) ; +  pattern0 := pattern ** 0 ; +  down in atoms (s, atom, pre, column);  +  IF NOT (last search succeeded CAND like pattern) +    THEN try again +  FI;  +  last search succeeded := TRUE ; +  column := matchpos (0) .  +  +try again:  +  WHILE s.line no < last search line +    REP next atom (s, atom) ; +        column := 1 ;  +        down in atoms (s, atom, pre, column);  +        IF last search succeeded CAND like pattern +          THEN LEAVE try again +        FI +    PER;  +    column := 1 + LENGTH record;  +    last search succeeded := FALSE ; +    LEAVE search down.  + +like pattern : +  correct position ; +  pat := any (column-1) ; +  pat CAT any ; +  pat CAT pattern0 ; +  pat CAT any ; +  record LIKE pat . + +correct position : +  IF s.lineno = start line +    THEN column := start col +    ELSE column := 1 +  FI . + +record : atom (s.index).line . + +ENDPROC search down ; + +PROC down in atoms (SEQUENCE VAR s, ATOMROW CONST atom, TEXT CONST pattern, +                    INT VAR column) : +  +  last search succeeded := FALSE ; +  search forwards in actual line ; +  IF NOT found AND s.line no < last search line +    THEN search in following lines +  FI ; +  IF found +    THEN last search succeeded := TRUE +    ELSE set column behind last char +  FI . + +set column behind last char : +  column := LENGTH atom (s.index).line + 1 . + +search forwards in actual line : +  IF pattern <> "" +    THEN column := pos (atom (s.index).line, pattern, column) +  ELIF column > LENGTH atom (s.index).line +    THEN column := 0 +  FI . + +search in following lines : +  next atom (s, atom) ; +  IF pattern = "" +    THEN column := 1 ; +         LEAVE search in following lines +  FI ; +  REP +    search forwards through segment ; +    update file position forwards ; +    IF found OR s.line no = last search line +      THEN LEAVE search in following lines +      ELSE next segment (s, atom) +    FI +  PER . + +search forwards through segment : +  INT VAR search index := s.index , +  last index := min (s.segment end, s.index+(last search line-s.line no)); +  REP +    column := pos (atom (search index).line, pattern) ; +    IF found OR search index = last index +      THEN LEAVE search forwards through segment +    FI ; +    search index INCR 1 +  PER . + +update file position forwards : +  disable stop ; +  s.line no INCR (search index - s.index) ; +  s.index := search index ; +  enable stop . + +found :  column > 0 . + +ENDPROC down in atoms ; + +TEXT PROC prefix (TEXT CONST pattern) :  +  +  INT VAR invalid char pos := pos (pattern, ""0"", ""31"", 1) ;  +  SELECT invalid char pos OF   +    CASE 0    : pattern  +    CASE 1    : ""                                               +    OTHERWISE : subtext (pattern, 1, invalid char pos - 1)  +  ENDSELECT .  +  +ENDPROC prefix ;  + +PROC search up (SEQUENCE VAR s, ATOMROW CONST atom, TEXT CONST pattern, +                INT CONST max lines, INT VAR column) : + +     last search line := max (1, s.lineno - max lines) ; +     pre:= prefix (pattern); +     pattern0 := pattern ** 0; +     remember start point ; +     up in atoms (s, atom, pre, column);  +     IF   NOT (last search succeeded CAND last pattern in line found) +     THEN try again  +     FI;  +     last search succeeded := TRUE ; +     column := matchpos (0) .  +  +  try again:  +     WHILE s.lineno > last search line OR column > 1 +     REP   previous atom (s, atom);  +           column := LENGTH record ; +           up in atoms (s, atom, pre, column);  +           IF last search succeeded CAND last pattern in line found +             THEN LEAVE try again +           FI  +     PER;  +     column := 1;  +     last search succeeded := FALSE ; +     LEAVE search up.  + +  remember start point : +     INT VAR c:= column, r:= s.lineno;. + +  last pattern in line found : +    column := 2 ; +    WHILE like pattern CAND right of start REP +      column := matchpos (0) +1 +    PER ; +    column DECR 1 ; +    like pattern CAND right of start . + +  like pattern : +     pat := any (column-1) ; +     pat CAT any ; +     pat CAT pattern0 ; +     pat CAT any ; +     record LIKE pat . + +  right of start : (r > s.lineno COR c >= matchpos(0)) . +  record         : atom (s.index).line . + +ENDPROC search up ; + +PROC up in atoms (SEQUENCE VAR s, ATOMROW CONST atom, TEXT CONST pattern, +                  INT VAR column) : + +  last search succeeded := FALSE ; +  search backwards in actual line ; +  IF NOT found AND s.line no > last search line +    THEN search in preceeding lines +  FI ; +  IF found +    THEN last search succeeded := TRUE +    ELSE column := 1 +  FI . + +search backwards in actual line : +  IF pattern = "" +    THEN LEAVE search backwards in actual line +  FI ; +  INT VAR last pos , new pos := 0 ; +  REP +    last pos := new pos ; +    new pos := pos (atom (s.index).line, pattern, last pos+1) ; +  UNTIL new pos = 0 OR new pos > column PER ; +  column := last pos . + +search in preceeding lines : +  previous atom (s, atom) ; +  IF pattern = "" +    THEN column := LENGTH atom (s.index).line + 1 ; +         last search succeeded := TRUE ; +         LEAVE search in preceeding lines +  FI ; +  REP +    search backwards through segment ; +    update file position backwards ; +    IF found OR s.line no = last search line +      THEN LEAVE search in preceeding lines +      ELSE previous segment (s, atom) +    FI +  PER . + +search backwards through segment : +  INT VAR search index := s.index , +  last index := max (s.segment begin, s.index-(s.line no-last search line)); +  REP +    new pos := 0 ; +    REP +      column := new pos ; +      new pos := pos (atom (search index).line, pattern, column+1) ; +    UNTIL new pos = 0 PER ; +    IF found OR search index = last index +      THEN LEAVE search backwards through segment +    FI ; +    search index DECR 1 +  PER . + +update file position backwards : +  disable stop ; +  s.line no DECR (s.index - search index) ; +  s.index := search index ; +  enable stop . + +found :  column > 0 . + +ENDPROC up in atoms ; + +BOOL VAR last search succeeded ; + +BOOL PROC pattern found : +  last search succeeded +ENDPROC pattern found ; + + + +PROC delete atom (SEQUENCE VAR used, free, ATOMROW VAR atom) : +  +  disable stop; +  IF used.line no <= used.lines +    THEN delete actual atom +    ELSE errorstop ("'delete' am Dateiende") +  FI . +  +delete actual atom : +  position behind actual free segment; +  split segment (used, atom); +  INT VAR actual index := used.index; +  cut off tail of actual used segment; +  delete segments (used, atom, actual index, actual index, 1); +  insert segments (free, atom, actual index, actual index, 1) . +  +position behind actual free segment : +  IF free.line no <= free.lines +    THEN next segment (free, atom) +  FI . +  +cut off tail of actual used segment : +  IF actual index <> used.segment end +    THEN used.index INCR 1; +         split segment (used, atom); +         used.index DECR 1  +  FI . +  +END PROC delete atom; +  +  +PROC insert atom (SEQUENCE VAR used, free,INT VAR unused, ATOMROW VAR atom) : +  +  disable stop; +  split segment (used, atom); +  IF free.lines > 0 +    THEN insert new atom from free sequence +  ELIF unused <= file size +    THEN insert new atom from unused tail +  ELSE   errorstop ("FILE-Ueberlauf") +  FI . +  +insert new atom from free sequence : +  get a free segments head; +  make this atom to actual segment; +  transfer from free to used chain . +  +get a free segments head : +  IF actual free segment is root segment +    THEN previous segment (free, atom) +  FI; +  position to actual segments head . +  +position to actual segments head : +  INT VAR actual index := free.segment begin; +  free.line no DECR (free.index - actual index); +  free.index := actual index . +  +make this atom to actual segment : +  IF free.segment end > actual index +    THEN free.index INCR 1; +         split segment (free, atom); +         free.index DECR 1 +  FI . +  +transfer from free to used chain : +  delete segments (free, atom, actual index, actual index, 1); +  insert segments (used, atom, actual index, actual index, 1); +  atom (actual index).line := "" . +  +insert new atom from unused tail : +  actual index := unused; +  atom (actual index).seg :=  +                      SEGMENT:(actual index, actual index, actual index); +  atom (actual index).line := ""; +  insert segments (used, atom, actual index, actual index, 1); +  unused INCR 1 . +  +actual free segment is root segment :    free.segment begin = free root . +  +END PROC insert atom; +  +  +PROC insert next (SEQUENCE VAR used, free, INT VAR unused, ATOMROW VAR atom, +                  TEXT CONST record) : +  +  IF used.line no > used.lines +    THEN insert atom (used, free, unused, atom) +  ELIF actual position before unused nonempty atomrow part +    THEN forward and insert atom by simple extension of used atomrow part +    ELSE next atom (used, atom); +         insert atom (used, free, unused, atom) +  FI; +  atom (used.index).line := record . +  +forward and insert atom by simple extension of used atomrow part : +  used.line no INCR 1; +  used.lines INCR 1; +  used.index INCR 1; +  used.segment end INCR 1; +  atom (used.segment begin).seg.end INCR 1; +  unused INCR 1 . +  +actual position before unused nonempty atomrow part : +  used.index = unused - 1 AND unused part not empty . +  +unused part not empty :  unused <= file size . +  +END PROC insert next; +  +  +PROC transfer subsequence (SEQUENCE VAR source, dest,  +                           ATOMROW VAR atom, INT CONST size) : +  +  IF size > 0 +    THEN INT VAR subsequence size := min (size, source.line no); +         mark begin of source part; +         mark end of source part; +         split destination sequence; +         transfer part +  FI . +  +mark begin of source part : +  previous atoms (source, atom, subsequence size - 1); +  split segment (source, atom); +  INT CONST first := source.segment begin . +  +mark end of source part : +  next atoms (source, atom, subsequence size - 1); +  INT CONST last := source.segment begin; +  next atom (source, atom); +  split segment (source, atom) . +  +split destination sequence : +  split segment (dest, atom) . +  +transfer part : +  disable stop; +  delete segments (source, atom, first, last, subsequence size); +  source.line no DECR subsequence size; +  insert segments (dest, atom, first, last, subsequence size); +  next atoms (dest, atom, subsequence size - 1) . +  +END PROC transfer subsequence; +  + + +(********************************************************************) +(*****                                                          *****) +(*****                  FILE handler                            *****) +(*****                                                          *****) +(********************************************************************) + + +  +LET file type    = 1003 , +    file type 16 = 1002 , + +    closed       = 0, +    inp          = 1, +    outp         = 2, +    mod          = 3, +    end          = 4, + +    max limit    = 16000, +    super limit  = 16001; + +  +TYPE TRANSPUTDIRECTION = INT; +  +  +TRANSPUTDIRECTION PROC input : +  TRANSPUTDIRECTION : (inp) +END PROC input; +  +  +TRANSPUTDIRECTION PROC output : +  TRANSPUTDIRECTION : (outp) +END PROC output; +  +  +TRANSPUTDIRECTION PROC modify : +  TRANSPUTDIRECTION : (mod) +END PROC modify; +  +  +FILE VAR result file; +  +  +FILE PROC sequential file (TRANSPUTDIRECTION CONST mode, +                            DATASPACE CONST ds) : +  IF   type (ds) = file type +  THEN result := ds +  ELIF type (ds) < 0 +  THEN result := ds; type (ds, file type); initialize (result file) +  ELSE enable stop; errorstop ("Datenraum hat falschen Typ") +  FI; +  reset (result file, mode); +  result file . +  +result : CONCR (result file) . + +END PROC sequential file; + + +FILE PROC sequential file (TRANSPUTDIRECTION CONST mode, TEXT CONST name) : + +  IF   exists (name) +  THEN get dataspace if file +  ELIF CONCR (mode) <> inp +  THEN get new file space +  ELSE errorstop (""""+name+""" gibt es nicht") ; enable stop +  FI; +  update status if necessary; +  reset (result file, mode); +  result file . + +get dataspace if file : +  IF type (old (name)) = file type 16 +    THEN reorganize (name) +  FI ; +  result := old (name, file type) ; +  IF is 170 file +    THEN result.col := 1 ; +         result.mark line := 0 ; +         result.mark col  := 0 +  FI . + +is 170 file : result.mark col < 0 . + +get new file space : +  result := new (name); +  IF   NOT is error +  THEN type (old (name), file type); initialize (result file) +  FI . + +update status if necessary : +  IF   CONCR (mode) <> inp +  THEN status (name, ""); headline (result file, name) +  FI . +  +result : CONCR (result file) . +  +END PROC sequential file; +  +  +PROC reset (FILE VAR f) : + +  IF f.mode = end +    THEN reset (f, input) +    ELSE reset (f, TRANSPUTDIRECTION:(f.mode)) +  FI . + +ENDPROC reset ; + +PROC reset (FILE VAR f, TRANSPUTDIRECTION CONST mode) : + +  IF f.mode <> mod OR new mode <> mod +    THEN f.mode := new mode ; +         initialize file index  +  FI . + +initialize file index : +  IF new mode = outp +    THEN to line without check (f, f.used.lines); +         col := super limit +    ELSE to line without check (f, 1); +         col := 1 ; +         IF new mode = inp AND file is empty +           THEN f.mode := end +         FI +  FI . +  +file is empty : f.used.lines = 0 . +  +new mode  : CONCR (mode) . + +col :   CONCR (CONCR (f)).col . +  +END PROC reset; +  +  +PROC input (FILE VAR f) : +  +  reset (f, input) . +  +END PROC input; +  +  +PROC output (FILE VAR f) : +  +  reset (f, output) +  +END PROC output; +  +  +PROC modify (FILE VAR f) : +  +  reset (f, modify) + +END PROC modify; +  +  +PROC close (FILE VAR f) : +  +  f.mode := closed . + +END PROC close; +  +  +PROC check mode (FILE CONST f, INT CONST mode) : +  +  IF f.mode = mode +    THEN LEAVE check mode +    ELIF f.mode = closed +    THEN errorstop ("Datei zu!") +    ELIF f.mode = mod +    THEN errorstop ("unzulaessiger Zugriff auf modify-FILE") +    ELIF mode = mod +    THEN errorstop ("Zugriff nur auf modify-FILE zulaessig") +    ELIF f.mode = end +    THEN errorstop ("Leseversuch nach Dateiende") +    ELIF mode = inp +    THEN errorstop ("Leseversuch auf output-FILE") +    ELIF mode = outp +    THEN errorstop ("Schreibversuch auf input-FILE") +  FI . +  +END PROC check mode; +  +  +PROC to line without check (FILE VAR f, INT CONST destination line) : +  +  INT CONST distance := destination line - f.used.line no; +  IF   distance > 0 +    THEN next atoms (f.used, f.atoms, distance) +  ELIF distance < 0 +    THEN previous atoms (f.used, f.atoms, - distance) +  FI . +  +END PROC to line without check; +  +  +PROC to line (FILE VAR f, INT CONST destination line) : +  +  check mode (f, mod); +  to line without check (f, destination line) +  +END PROC to line; +  +  +PROC to first record (FILE VAR f) : +  +  to line (f, 1) +  +END PROC to first record; +  +  +PROC to eof (FILE VAR f) : +  +  to line (f, f.used.lines + 1) . +  +END PROC to eof; +  +  +PROC putline (FILE VAR f, TEXT CONST word) : +  +  write (f, word); +  col := super limit . +  +col : CONCR (CONCR (f)).col . +  +END PROC putline; +  +  +PROC delete record (FILE VAR f) : +  +  check mode (f, mod); +  delete atom (f.used, f.free, f.atoms) . +  +END PROC delete record; +  +  +PROC insert record (FILE VAR f) : +  +  check mode (f, mod); +  insert atom (f.used, f.free, f.unused tail, f.atoms) . +  +END PROC insert record; +  +  +PROC down (FILE VAR f) : +  +  check mode (f, mod); +  next atom (f.used, f.atoms) . +  +END PROC down ; +  +PROC up (FILE VAR f) : +  +  check mode (f, mod); +  previous atom (f.used, f.atoms) . +  +END PROC up ; + +PROC down (FILE VAR f, INT CONST n) : + +  to line (f, lineno (f) + n) + +ENDPROC down ; + +PROC up (FILE VAR f, INT CONST n) : + +  to line (f, lineno (f) - n) + +ENDPROC up ; + +  +PROC write record (FILE VAR f, TEXT CONST record) : +  +  check mode (f, mod); +  IF   not at eof +    THEN f.atoms (f.used.index).line := record +    ELSE errorstop ("'write' nach Dateiende") +  FI . +  +not at eof :  f.used.line no <= f.used.lines . +  +END PROC write record; +  +  +PROC read record (FILE CONST f, TEXT VAR record) : +  +  check mode (f, mod); +  record := f.atoms (f.used.index).line . +  +END PROC read record; +  +  +PROC line (FILE VAR f) : +  +  IF   mode = end +    THEN errorstop ("Leseversuch nach Dateiende") +    ELIF mode = inp +    THEN next atom (f.used, f.atoms); col := 1; check eof +    ELIF mode = outp +    THEN IF col <= max limit +           THEN col := super limit +           ELSE append empty line +         FI +  FI . +  +append empty line : +  insert next (f.used, f.free, f.unused tail, f.atoms, "") . +  +col : CONCR (CONCR (f)).col . +  +mode : CONCR (CONCR (f)).mode . +  +check eof : +  IF eof (f) THEN mode := end FI . +  +END PROC line; +  +  +PROC line (FILE VAR f, INT CONST lines) : +  +  INT VAR i; FOR i FROM 1 UPTO lines REP line (f) PER +  +END PROC line; +  + +PROC getline (FILE VAR f, TEXT VAR text) : + +  check mode (f, inp); +  text := subtext (record, f.col); +  IF f.used.line no >= f.used.lines +    THEN f.mode := end ; +         set end of file +    ELSE to next line ; +         f.col := 1 +  FI . + +to next line : +  next atom (f.used, f.atoms) . + +set end of file : +  f.col := LENGTH record + 1 . + +record : f.atoms (f.used.index).line . + +END PROC getline; +  +  +BOOL PROC is first record (FILE CONST f) : +  +  check mode (f, mod); +  f.used.line no = 1 . +  +END PROC is first record; +  +  +BOOL PROC eof (FILE CONST f) : +  +  IF   line no < lines THEN FALSE +  ELIF line no = lines THEN col > LENGTH record +  ELSE                      TRUE +  FI . + +line no :  f.used.line no . +lines   :  f.used.lines . +col     :  f.col . +record  :  f.atoms (f.used.index).line . +  +END PROC eof; +  +  +INT PROC line no (FILE CONST f) : +  +  f.used.line no . +  +END PROC line no; + + +PROC line type (FILE VAR f, INT CONST t) : + +  f.atoms (f.used.index).type := t . + +ENDPROC line type ; + +INT PROC line type (FILE CONST f) : + +  f.atoms (f.used.index).type . + +ENDPROC line type ; +  +  +PROC put (FILE VAR f, TEXT CONST word) : +  +  check mode (f, outp); +  IF col + LENGTH word > f.limit +    THEN append new line +    ELSE record CAT word +  FI; +  record CAT " "; +  col := LENGTH record + 1 . +  +append new line : +  insert next (f.used, f.free, f.unused tail, f.atoms, word) . +  +record : f.atoms (f.used.index).line . +col :    f.col . +  +END PROC put; + +  +PROC put (FILE VAR f, INT CONST value) : +  +  put (f, text (value)) +  +END PROC put; +  +  +PROC put (FILE VAR f, REAL CONST real) : +  +  put (f, text (real)) +  +END PROC put; +  +  +PROC write (FILE VAR f, TEXT CONST word) : +  +  check mode (f, outp); +  IF col + LENGTH word - 1 > f.limit +    THEN append new line +    ELSE record CAT word +  FI; +  col := LENGTH record + 1 . +  +append new line : +  insert next (f.used, f.free, f.unused tail, f.atoms, word) . +  +record : f.atoms (f.used.index).line . +col    : f.col . +  +END PROC write; +  +  +PROC get (FILE VAR f, TEXT VAR word, TEXT CONST separator) : +  +  check mode (f, inp); +  skip separators; +  IF word found +    THEN get word +    ELSE try to find word in next line +  FI . +  +skip separators : +  INT CONST separator length := LENGTH separator; +  WHILE is separator REP col INCR separator length PER . + +is separator :  +  subtext (record, col, col + separator length - 1) = separator . +  +word found : col <= LENGTH record . +  +get word : +  INT VAR end of word := pos (record, separator, col) - 1; +  IF separator found +    THEN get text upto separator +    ELSE get rest of record +  FI . +  +separator found : end of word >= 0 . +  +get text upto separator : +  word := subtext (record, col, end of word); +  col := end of word + separator length + 1; +  IF col > LENGTH record THEN line (f) FI . +  +get rest of record : +  word := subtext (record, col); line (f) . +  +record : f.atoms (f.used.index).line . +col    : f.col . +  +try to find word in next line : +  line (f); IF eof (f) THEN word := "" ELSE get (f, word, separator) FI . +  +END PROC get; +  +  +PROC get (FILE VAR f, TEXT VAR word, INT CONST max length) : +  +  check mode (f, inp); +  IF word is only a part of record +    THEN get text of certain length +    ELSE get rest of record +  FI . +  +word is only a part of record : +  col <= LENGTH record - max length . +  +get text of certain length : +  word := text (record, max length, col); +  col INCR max length . + +get rest of record : +  word := subtext (record, col); line (f) . +  +record : f.atoms (f.used.index).line . +col    : f.col . +  +END PROC get; +  +  +PROC get (FILE VAR f, TEXT VAR word) : +  +  get (f, word, " ") +  +END PROC get; +  +  +TEXT VAR number word; +  +  +PROC get (FILE VAR f, INT VAR number) : +  +  get (f, number word); +  number := int (number word) +  +END PROC get; +  +  +PROC get (FILE VAR f, REAL VAR number) : +  +  get (f, number word); +  number := real (number word) +  +END PROC get; +  +  +TEXT VAR split record ; +INT VAR indentation ; + +PROC split line (FILE VAR f, INT CONST split col) : + +  split line (f, split col, TRUE) + +ENDPROC split line ; + +PROC split line (FILE VAR f, INT CONST split col, BOOL CONST note indentation ) : + +  IF note indentation  +    THEN get indentation  +    ELSE indentation := 0 +  FI ; +  get split record ; +  insert split record and indentation ; +  cut off old record . + +get indentation : +  indentation := pos (actual record,""33"",""254"",1) - 1 ; +  IF indentation < 0 OR indentation >= split col +    THEN indentation := split col - 1 +  FI . + +get split record : +  split record := subtext (actual record, split col, max limit) . + +insert split record and indentation : +  down (f) ; +  insert record (f) ; +  INT VAR i ; +  FOR i FROM 1 UPTO indentation REP +    actual record CAT " " +  PER ;  +  actual record CAT split record ; +  up (f) . + +cut off old record : +  actual record := subtext (actual record, 1, split col-1) . + +actual record : f.atoms (f.used.index).line . + +ENDPROC split line ; + +PROC concatenate line (FILE VAR f, BOOL CONST delete blanks) : + +  down (f) ; +  split record := actual record ; +  IF delete blanks +    THEN delete leading blanks +  FI ; +  delete record (f) ; +  up (f) ; +  actual record CAT split record . + +delete leading blanks : +  INT CONST non blank col := pos (split record, ""33"", ""254"", 1) ; +  IF non blank col > 0 +    THEN split record := subtext (split record, non blank col) +  FI . + +actual record :  f.atoms (f.used.index).line . + +ENDPROC concatenate line ; + +PROC concatenate line (FILE VAR f) : +  concatenate line (f, TRUE) +ENDPROC concatenate line ; + +PROC reorganize : +  +  reorganize (last param) +  +END PROC reorganize; +  +  +TEXT VAR file record ; + +PROC reorganize (TEXT CONST file name) : +  +  enable stop ; +  FILE VAR input file, output file; +  DATASPACE VAR scratch space; +  INT CONST type of dataspace := type (old (file name)) ; +  INT VAR counter; +  +  last param (file name); +  IF type of dataspace = file type +    THEN reorganize new to new +  ELIF type of dataspace = file type 16 +    THEN reorganize old to new +    ELSE errorstop ("Datenraum hat falschen Typ") +  FI; +  replace file space by scratch space . +  +reorganize new to new : +  input  file := sequential file (input, file name); +  disable stop ; +  scratch space := nilspace ; +  output file := sequential file (output, scratch space); +  copy attributes (input file, output file) ; + +  FOR counter FROM 1 UPTO 9999 +  WHILE NOT eof (input file) REP +    cout (counter); +    getline (input file, file record); +    putline (output file, file record); +    check for interrupt +  PER . +  +reorganize old to new : +  LET OLDRECORD = STRUCT (INT succ, pred, x, y, TEXT record); +  LET OLDFILE = BOUND ROW 4075 OLDRECORD; +  LET dateianker = 2, freianker = 1; +  INT VAR index := dateianker; +  +  OLDFILE VAR old file := old (file name); +  disable stop; +  scratch space := nilspace; +  output file := sequential file (output, scratch space); +  get old attributes ; +  +  say ("Datei wird in 1.7-Format gewandelt: ") ; + +  FOR counter FROM 1 UPTO 9999 +  WHILE NOT end of old file REP +    cout (counter); +    index := next record; +    file record := record of old file ; +    IF pos (file record, ""128"", ""250"", 1) > 0 +      THEN change special chars +    FI ; +    putline (output file, file record); +    check for interrupt +  PER . +  +get old attributes : +  get old headline ; +  get old limit and tabs . + +get old headline : +  headline (output file, old file (dateianker).record) . + +get old limit and tabs : +  file record := old file (freianker).record ; +  max line length (output file, int (subtext (file record, 11, 15))) ; +  put tabs (output file, subtext (file record, 16)) . + +change special chars : +  change all (file record, ""193"", ""214"") (* Ae *) ; +  change all (file record, ""207"", ""215"") (* Oe *) ; +  change all (file record, ""213"", ""216"") (* Ue *) ; +  change all (file record, ""225"", ""217"") (* ae *) ; +  change all (file record, ""239"", ""218"") (* oe *) ; +  change all (file record, ""245"", ""219"") (* ue *) ; +  change all (file record, ""235"", ""220"") (* k  *) ; +  change all (file record, ""173"", ""221"") (* -  *) ; +  change all (file record, ""163"", ""222"") (* fis   *) ; +  change all (file record, ""160"", ""223"") (* blank *) ; +  change all (file record, ""194"", ""251"") (* eszet *) . + +end of old file :      next record = dateianker . + +next record :          old file (index).succ . +  +record of old file :   old file (index).record . +  +check for interrupt : +  INT VAR size, used ; +  storage (size, used) ; +  IF used > size +    THEN errorstop ("Speicherengpass") +  FI ; +  IF is error +    THEN forget (scratch space) ; LEAVE reorganize +  FI . +  +replace file space by scratch space : +  headline (output file, file name); +  forget (file name, quiet) ; +  type (scratch space, file type); +  copy (scratch space, file name); +  forget (scratch space) . + +END PROC reorganize; + + +PROC set range (FILE VAR f, INT CONST start line, start col, +                FRANGE VAR old range) : + +  check mode (f, mod); +  IF valid restriction parameters +    THEN prepare last line ; +         prepare first line ; +         save old range ; +         set new range +    ELSE errorstop ("FRANGE ungueltig") +  FI . + +valid restriction parameters : +  start line > 0 AND start col > 0 AND start before or at actual point . + +start before or at actual point : +  start line < line no (f)  OR +  start line = line no (f) AND start col <= col (f) . + +prepare last line : +  INT VAR last line ; +  IF col (f) > 1 +    THEN split line (f, col(f), FALSE) +  FI . + +prepare first line : +  IF start col > 1 +    THEN split start line ; +  FI . + +split start line : +  INT VAR old line no := line no (f) ; +  to line (f, start line) ; +  split line (f, start col, FALSE) ; +  to line (f, old line no + 1) . + +save old range : +  old range.pre := f.prefix lines ; +  old range.post:= f.postfix lines . + +set new range : +  get pre lines ; +  get post lines ; +  disable stop ; +  f.prefix lines INCR pre lines ; +  f.postfix lines INCR post lines ; +  f.used.lines DECR (post lines + pre lines) ; +  f.used.line no DECR pre lines . + +get pre lines : +  INT VAR pre lines ; +  IF start col = 1 +    THEN old range.pre was split := FALSE ; +         pre lines := start line - 1 +    ELSE old range.pre was split := TRUE ; +         pre lines := start line +  FI . + +get post lines : +  INT VAR post lines ; +  IF col (f) = 1 +    THEN old range.post was split := FALSE ; +         post lines := lines (f) - line no (f) + 1 +    ELSE old range.post was split := TRUE ; +         post lines := lines (f) - line no (f) +  FI . + +END PROC set range; + + +PROC set range (FILE VAR f, FRANGE VAR new range) : + +  check mode (f, mod); +  INT CONST pre add  := prefix - new range.pre, +            post add := postfix - new range.post; +  IF pre add < 0 OR post add < 0 +    THEN errorstop ("FRANGE ungueltig") +    ELSE set new range; +         undo splitting if necessary ; +         make range var invalid +  FI . +  +set new range : +  disable stop; +  prefix DECR pre add; +  postfix DECR post add; +  used.line no INCR pre add; +  used.lines INCR (pre add + post add) . + +undo splitting if necessary : +  IF new range.pre was split +    THEN concatenate first line +  FI ; +  IF new range.post was split +    THEN concatenate last line +  FI . + +concatenate first line : +  INT VAR old line := line no (f) ; +  to line (f, pre add) ; +  concatenate line (f, FALSE) ; +  to line (f, old line - 1) . + +concatenate last line : +  old line := line no (f) ; +  to line (f, lines (f) - post add) ; +  concatenate line (f, FALSE) ; +  to line (f, old line) . + +make range var invalid : +  new range.pre := maxint . +  +used :    f.used . +prefix :  f.prefix lines . +postfix : f.postfix lines . +  +END PROC set range; +  +PROC reset range (FILE VAR f) : + +  FRANGE VAR complete ; +  complete.pre := 0 ; +  complete.post:= 0 ; +  complete.pre was split := FALSE ; +  complete.post was split:= FALSE ; +  set range (f, complete) + +ENDPROC reset range ; + +PROC remove (FILE VAR f, INT CONST size) : +  +  check mode (f, mod); +  transfer subsequence (f.used, f.scratch, f.atoms, size) . +  +END PROC remove; +  +  +PROC clear removed (FILE VAR f) : +  +  check mode (f, mod); +  transfer subsequence (f.scratch, f.free, f.atoms, f.scratch.lines) . +  +END PROC clear removed; +  +  +PROC reinsert (FILE VAR f) : +  +  check mode (f, mod); +  transfer subsequence (f.scratch, f.used, f.atoms, f.scratch.lines) . +  +END PROC reinsert; + + +PROC copy attributes (FILE CONST source file, FILE VAR dest file) : + +  dest.limit                     := source.limit ; +  dest.atoms (free root).line    := source.atoms (free root).line ; +  dest.atoms (scratch root).line := source.atoms (scratch root).line ; +  dest.edit info                 := source.edit info . + +dest   : CONCR (CONCR (dest file)) . +source : CONCR (CONCR (source file)) . + +ENDPROC copy attributes ; +  +  +INT PROC max line length (FILE CONST f) : +  +  f.limit . +  +END PROC max line length; +  +  +PROC max line length (FILE VAR f, INT CONST new limit) : +  +  IF new limit > 0 AND new limit <= max limit +    THEN f.limit := new limit +  FI . +  +END PROC max line length; +  +  +TEXT PROC headline (FILE CONST f) : +  +  f.atoms (free root).line . + +END PROC headline; +  +  +PROC headline (FILE VAR f, TEXT CONST head) : +  +  f.atoms (free root).line := head . +  +END PROC headline; +  +  +PROC get tabs (FILE CONST f, TEXT VAR tabs) : +  +  tabs := f.atoms (scratch root).line . +  +END PROC get tabs; +  +  +PROC put tabs (FILE VAR f, TEXT CONST tabs) : +  +  f.atoms (scratch root).line := tabs . +  +END PROC put tabs; + +  +INT PROC edit info (FILE CONST f) : +  +  f.edit info . +  +END PROC edit info; +  +  +PROC edit info (FILE VAR f, INT CONST info) :  +  +  f.edit info := info . +  +END PROC edit info; +  +  +INT PROC lines (FILE CONST f) : +  +  f.used.lines . +  +END PROC lines; +  +  +INT PROC removed lines (FILE CONST f) : +  +  f.scratch.lines . +  +END PROC removed lines; + + +INT PROC segments (FILE CONST f) : + +  segs(f.used,f.atoms) + segs(f.scratch,f.atoms) + segs(f.free,f.atoms) - 2 . + +ENDPROC segments ; + + +INT PROC col (FILE CONST f) : + +  f.col + +ENDPROC col ; + +PROC col (FILE VAR f, INT CONST new column) : + +  IF new column > 0 +    THEN f.col := new column +  FI + +ENDPROC col ; + +TEXT PROC word (FILE CONST f) : + +  word (f, " ") + +ENDPROC word ; + +TEXT PROC word (FILE CONST f, TEXT CONST delimiter) : + +  INT VAR del pos := pos (f, delimiter, col (f)) ; +  IF del pos = 0 +    THEN del pos := len (f) + 1 +  FI ; +  subtext (f, col (f), del pos - 1) + +ENDPROC word ; + +TEXT PROC word (FILE CONST f, INT CONST max length) : + +  subtext (f, col (f), col (f) + max length - 1) + +ENDPROC word ; + +BOOL PROC at (FILE CONST f, TEXT CONST word) : + +  pat := any (column-1) ; +  pat CAT word ; +  pat CAT any ; +  record LIKE pat . + +column : f.col . +record : f.atoms (f.used.index).line . + +ENDPROC at ; + +  +PROC exec (PROC (TEXT VAR, TEXT CONST) proc, FILE VAR f, TEXT CONST t) : +  +  proc (record, t) . +  +record : f.atoms (f.used.index).line . +  +END PROC exec; +  +  +PROC exec (PROC (TEXT VAR, INT CONST) proc, FILE VAR f, INT CONST i) : +  +  proc (record, i) . + +record : f.atoms (f.used.index).line . +  +END PROC exec; +  +INT PROC pos (FILE CONST f, TEXT CONST pattern, INT CONST i) : +  +  pos (record, pattern, i) . +  +record : f.atoms (f.used.index).line . +  +END PROC pos ; + +PROC down (FILE VAR f, TEXT CONST pattern) : + +  down (f, pattern, file size) + +ENDPROC down ; + +PROC down (FILE VAR f, TEXT CONST pattern, INT CONST max line) : + +  check mode (f,mod) ; +  INT VAR pattern pos := f.col + 1 ; +  search down (f.used, f.atoms, pattern, max line, pattern pos) ; +  f.col := pattern pos + +ENDPROC down ; + +PROC downety (FILE VAR f, TEXT CONST pattern) : +  +  downety (f, pattern, file size) + +ENDPROC downety ; + +PROC downety (FILE VAR f, TEXT CONST pattern, INT CONST max line) : + +  check mode (f,mod) ; +  INT VAR pattern pos := f.col ; +  search down (f.used, f.atoms, pattern, max line, pattern pos) ; +  f.col := pattern pos + +ENDPROC downety ; + +PROC up (FILE VAR f, TEXT CONST pattern) : + +  up (f, pattern, file size) + +ENDPROC up ; + +PROC up (FILE VAR f, TEXT CONST pattern, INT CONST max line) : + +  check mode (f,mod) ; +  INT VAR pattern pos := f.col - 1 ; +  search up (f.used, f.atoms, pattern, max line, pattern pos) ; +  f.col := pattern pos + +ENDPROC up ; + +PROC uppety (FILE VAR f, TEXT CONST pattern) : + +  uppety (f, pattern, file size) + +ENDPROC uppety ; + +PROC uppety (FILE VAR f, TEXT CONST pattern, INT CONST max line) : + +  check mode (f,mod) ; +  INT VAR pattern pos := f.col ; +  search up (f.used, f.atoms, pattern, max line, pattern pos) ; +  f.col := pattern pos + +ENDPROC uppety ; + + +INT PROC len (FILE CONST f) : + +  length (record) . + +record : f.atoms (f.used.index).line . + +ENDPROC len ; + +TEXT PROC subtext (FILE CONST f, INT CONST from, to) : + +  subtext (record, from, to) . + +record : f.atoms (f.used.index).line . + +ENDPROC subtext ; + +PROC change (FILE VAR f, INT CONST from, to, TEXT CONST new) : + +  check mode (f, mod) ; +  change (record, from, to, new) . + +record : f.atoms (f.used.index).line . + +ENDPROC change ; + +  +BOOL PROC mark (FILE CONST f) : + +  f.mark line > 0 + +ENDPROC mark ; + +PROC mark (FILE VAR f, INT CONST line no, col) : + +  IF line no > 0 +    THEN f.mark line := line no + f.prefix lines ; +         f.mark col  := col +    ELSE f.mark line := 0 ; +         f.mark col  := 0 +  FI  + +ENDPROC mark ; + +INT PROC mark line no (FILE CONST f) : + +  IF f.mark line = 0 +    THEN 0 +    ELSE max (1, f.mark line - f.prefix lines) +  FI + +ENDPROC mark line no ; + +INT PROC mark col (FILE CONST f) : + +  IF f.mark line = 0 +    THEN 0 +  ELIF f.mark line <= f.prefix lines +    THEN 1 +  ELSE f.mark col +  FI + +ENDPROC mark col ; + +PROC set marked range (FILE VAR f, FRANGE VAR old range) : + +  IF mark (f) +    THEN set range (f, mark line no (f), mark col (f), old range) +    ELSE old range := previous range of file +  FI . + +previous range of file : +  FRANGE : (f.prefix lines, f.postfix lines, FALSE, FALSE) . + +ENDPROC set marked range ; + + +(*****************************************************************) + +                                                  (* Autor: P.Heyderhoff *)  +                                                  (* Stand: 11.10.83     *)  +  +BOUND LIST VAR datei;  +INT  VAR sortierstelle, sortanker; +BOOL VAR ascii sort; +TEXT VAR median, tausch , links, rechts; +  +PROC sort (TEXT CONST dateiname) :  +     sort (dateiname, 1) +END PROC sort;  +  +PROC sort (TEXT CONST dateiname, INT CONST sortieranfang) :  +     ascii sort := TRUE ; +     sortierstelle := sortieranfang; sortiere (dateiname) +END PROC sort;  +  +PROC lex sort (TEXT CONST dateiname) : +     lex sort (dateiname, 1) +ENDPROC lex sort ; + +PROC lex sort (TEXT CONST dateiname, INT CONST sortieranfang) : +     ascii sort := FALSE ; +     sortierstelle := sortieranfang; sortiere (dateiname) +ENDPROC lex sort ; + +PROC sortiere (TEXT CONST dateiname) : + +  reorganize file if necessary ; +  sort file . + +reorganize file if necessary : +  FILE VAR f := sequential file (modify, dateiname) ; +  IF segments (f) > 1 +    THEN reorganize (dateiname) +  FI . + +sort file : +  f := sequential file (modify, dateiname) ; +  INT CONST sortende := lines (f) + 3 ; +  sortanker := 1 + 3 ; +  datei := old (dateiname) ; +  quicksort(sortanker, sortende) . + +END PROC sortiere;  +  +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, sortierstelle) .  +  +   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 links := subtext (datei p, sortierstelle) ; +            IF ascii sort +              THEN median >= links +              ELSE median LEXGREATEREQUAL links +            FI +       ELSE FALSE  +     FI .  +  +   q kann kleiner werden :  +     IF q >= anfang  +       THEN rechts := subtext(datei q, sortierstelle) ; +            IF ascii sort +              THEN rechts >= median  +              ELSE rechts LEXGREATEREQUAL median +            FI +       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 .  +  +   datei m :  datei.atoms (m).line .  +   datei p :  datei.atoms (p).line .  +   datei q :  datei.atoms (q).line .  +  +END PROC spalte;  + +END PACKET file handling; +  | 
