| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- IMPLEMENTATION MODULE TermCfg ;
- FROM Posix IMPORT open, read, close ;
- FROM SYSTEM IMPORT ADR, BYTE ;
- CONST
- ESC = 27 ;
- CR = 13 ;
- LF = 10 ;
- BS = 92 ; (* backslash, as a number: Modula-2 string escaping is
- not something to rely on for a single character *)
- MaxFile = 4095 ;
- PROCEDURE Clear (VAR s : ARRAY OF CHAR) ;
- VAR i : CARDINAL ;
- BEGIN
- i := 0 ;
- WHILE i <= HIGH (s) DO
- s [i] := 0C ;
- INC (i)
- END
- END Clear ;
- PROCEDURE Copy (VAR dst : ARRAY OF CHAR ; src : ARRAY OF CHAR) ;
- VAR i : CARDINAL ;
- BEGIN
- i := 0 ;
- WHILE (i <= HIGH (dst)) AND (i <= HIGH (src)) AND (src [i] # 0C) DO
- dst [i] := src [i] ;
- INC (i)
- END ;
- IF i <= HIGH (dst) THEN
- dst [i] := 0C
- END
- END Copy ;
- PROCEDURE Up (ch : CHAR) : CHAR ;
- BEGIN
- IF (ch >= 'a') AND (ch <= 'z') THEN
- RETURN CHR (ORD (ch) - 32)
- END ;
- RETURN ch
- END Up ;
- PROCEDURE KeyIs (key : ARRAY OF CHAR ; want : ARRAY OF CHAR) : BOOLEAN ;
- VAR i : CARDINAL ;
- BEGIN
- i := 0 ;
- LOOP
- IF (i > HIGH (key)) OR (i > HIGH (want)) THEN
- RETURN FALSE
- END ;
- IF Up (key [i]) # Up (want [i]) THEN
- RETURN FALSE
- END ;
- IF want [i] = 0C THEN
- RETURN TRUE
- END ;
- INC (i)
- END
- END KeyIs ;
- PROCEDURE ParseValue (src : ARRAY OF CHAR ; VAR dst : ARRAY OF CHAR) ;
- (* \e, \r, \n, \t, \\, ^X; everything else is a literal character. *)
- VAR i, o, c : CARDINAL ; ch : CHAR ;
- BEGIN
- i := 0 ; o := 0 ;
- WHILE (i <= HIGH (src)) AND (src [i] # 0C) DO
- ch := src [i] ;
- IF (ORD (ch) = BS) AND (i + 1 <= HIGH (src)) AND (src [i + 1] # 0C) THEN
- INC (i) ;
- ch := src [i] ;
- IF (ch = 'e') OR (ch = 'E') THEN
- c := ESC
- ELSIF ch = 'r' THEN
- c := CR
- ELSIF ch = 'n' THEN
- c := LF
- ELSIF ch = 't' THEN
- c := 9
- ELSIF ORD (ch) = BS THEN
- c := BS
- ELSE
- c := ORD (ch)
- END
- ELSIF (ch = '^') AND (i + 1 <= HIGH (src)) AND (src [i + 1] # 0C) THEN
- INC (i) ;
- c := ORD (Up (src [i])) - 64
- ELSE
- c := ORD (ch)
- END ;
- IF o <= HIGH (dst) THEN
- dst [o] := CHR (c) ;
- INC (o)
- END ;
- INC (i)
- END ;
- IF o <= HIGH (dst) THEN
- dst [o] := 0C
- END
- END ParseValue ;
- PROCEDURE Apply (VAR c : Cfg ; key, val : ARRAY OF CHAR) ;
- BEGIN
- IF KeyIs (key, "NAME") THEN
- Copy (c.name, val)
- ELSIF KeyIs (key, "CLEAR") THEN
- ParseValue (val, c.clear)
- ELSIF KeyIs (key, "HOME") THEN
- ParseValue (val, c.home)
- ELSIF KeyIs (key, "GOTO") OR KeyIs (key, "MOVETO") THEN
- ParseValue (val, c.moveTo)
- ELSIF KeyIs (key, "NORMAL") THEN
- ParseValue (val, c.normal)
- ELSIF KeyIs (key, "MARKED") THEN
- ParseValue (val, c.marked)
- ELSIF KeyIs (key, "BEEP") THEN
- ParseValue (val, c.beep)
- END
- (* an unknown key is ignored on purpose: TINST's files and ours can then
- share a file without one rejecting the other's fields *)
- END Apply ;
- PROCEDURE Default (VAR c : Cfg) ;
- BEGIN
- Copy (c.name, "ANSI") ;
- ParseValue ("\e[2J\e[H", c.clear) ;
- ParseValue ("\e[H", c.home) ;
- ParseValue ("\e[%r;%cH", c.moveTo) ;
- ParseValue ("\e[0m", c.normal) ;
- ParseValue ("\e[1;7m", c.marked) ;
- ParseValue ("^G", c.beep)
- END Default ;
- PROCEDURE Load (path : ARRAY OF CHAR ; VAR c : Cfg ; VAR ok : BOOLEAN) ;
- VAR fd : INTEGER ;
- k : LONGINT ;
- b : BYTE ;
- buf : ARRAY [0..MaxFile] OF CHAR ;
- n, i, ls, le, eq, j : CARDINAL ;
- key : ARRAY [0..31] OF CHAR ;
- val : ARRAY [0..255] OF CHAR ;
- bad : BOOLEAN ;
- BEGIN
- Default (c) ;
- ok := FALSE ;
- fd := open (ADR (path), 0, 0) ;
- IF fd < 0 THEN
- RETURN
- END ;
- n := 0 ;
- LOOP
- k := read (fd, ADR (b), 1) ;
- IF k # 1 THEN
- EXIT
- END ;
- IF b = 26 THEN (* ^Z ends the text *)
- EXIT
- END ;
- IF n <= HIGH (buf) THEN
- buf [n] := CHR (ORD (b)) ;
- INC (n)
- END
- END ;
- k := close (fd) ;
- bad := FALSE ;
- i := 0 ;
- WHILE i < n DO
- ls := i ;
- WHILE (i < n) AND (buf [i] # CHR (CR)) AND (buf [i] # CHR (LF)) DO
- INC (i)
- END ;
- le := i ;
- WHILE (i < n) AND ((buf [i] = CHR (CR)) OR (buf [i] = CHR (LF))) DO
- INC (i)
- END ;
- (* trim blanks *)
- WHILE (ls < le) AND ((buf [ls] = ' ') OR (buf [ls] = CHR (9))) DO
- INC (ls)
- END ;
- WHILE (le > ls) AND ((buf [le - 1] = ' ') OR (buf [le - 1] = CHR (9))) DO
- DEC (le)
- END ;
- IF (ls < le) AND (buf [ls] # ';') THEN
- eq := ls ;
- WHILE (eq < le) AND (buf [eq] # '=') DO
- INC (eq)
- END ;
- IF eq = le THEN
- bad := TRUE (* a line with no '=' *)
- ELSE
- j := 0 ;
- WHILE (ls < eq) AND (j <= HIGH (key)) DO
- key [j] := buf [ls] ;
- INC (j) ;
- INC (ls)
- END ;
- key [j] := 0C ;
- INC (eq) ; (* skip '=' *)
- j := 0 ;
- WHILE (eq < le) AND (j <= HIGH (val)) DO
- val [j] := buf [eq] ;
- INC (j) ;
- INC (eq)
- END ;
- val [j] := 0C ;
- Apply (c, key, val)
- END
- END
- END ;
- ok := NOT bad
- END Load ;
- END TermCfg.
|