123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503 |
- module ftr; % Various utilities for working with files and modules.
- % Author: Anthony C. Hearn.
- % NOTE: This module uses Standard Lisp global *RAISE as a fluid.
- % This module supports several applications of file-transform.
- % Currently we have:
- % make-dist-files:
- % module_file_split:
- % downcase_file:
- % trunc:
- create!-package('(ftr),'(util));
- fluid '(!*echo !*downcase !*upcase current!-char!* previous!-char!*
- member!-channel!* old!-channel!*);
- global '(!*raise charassoc!*);
- global '(dir!*); % output directory name.
- % global '(dirchar!*);
- switch downcase,upcase;
- dir!* := ""; % default.
- % dirchar!* := "/";
- % ***** utility functions *****.
- symbolic procedure s!-match(u,v);
- % Returns true if list of characters u begins with same characters
- % (regardless of case) as lower case string v.
- s!-match1(u,explode2 v);
- symbolic procedure s!-match1(u,v);
- null v
- or u and (car u eq car v
- or red!-uppercasep car u
- and red!-char!-downcase car u eq car v)
- and s!-match1(cdr u,cdr v);
- symbolic procedure reverse!-chars!-to!-string u;
- compress('!" . reversip('!" . u));
- symbolic procedure red!-lowercasep u;
- u memq '(!a !b !c !d !e !f !g !h !i !j !k !l !m !n !o !p !q !r !s
- !t !u !v !w !x !y !z);
- symbolic procedure red!-uppercasep u;
- u memq '(!A !B !C !D !E !F !G !H !I !J !K !L !M !N !O !P !Q !R !S !T
- !U !V !W !X !Y !Z);
- symbolic procedure red!-char!-downcase u;
- (if x then cdr x else u) where x = atsoc(u,charassoc!*);
- symbolic procedure string!-upcase u;
- begin scalar z;
- if not stringp u then u := '!" . append(explode2 u,'(!"))
- else u := explode u;
- for each x in u do z := red!-char!-upcase x . z;
- return compress reverse z
- end;
- symbolic procedure red!-char!-upcase u;
- (if x then car x else u) where x = rassoc(u,charassoc!*);
- % ***** functions for manipulating regular REDUCE module files *****.
- symbolic procedure module_file_split u;
- file!-transform(u,function module!-file!-split1);
- symbolic procedure module!-file!-split1;
- begin scalar x,!*raise;
- while not errorp (x := errorset!*('(uread),t))
- and (x := car x) neq !$eof!$
- and x neq 'END!; do
- if x neq 'MODULE then rerror(ftr,1,"Invalid module format")
- else begin scalar ochan,oldochan,y;
- y := xread t; % Should be module name.
- ochan:= open(concat(dir!*,concat(mkfil y,".red")),'output);
- oldochan := wrs ochan;
- prin2 "module "; prin2 y; prin2 ";";
- read!-module();
- wrs oldochan;
- close ochan
- end
- end;
- symbolic procedure uread;
- begin scalar !*raise; !*raise := t; return read() end;
- symbolic procedure read!-module;
- begin integer eolcount; scalar x,y;
- eolcount := 0;
- a: if errorp (x := errorset!*('(readch),t))
- or (x := car x) = !$eof!$
- or eolcount > 20
- then rerror(ftr,2,"Invalid module format")
- else if x = !$eol!$ then eolcount := eolcount+1
- else eolcount := 0;
- prin2 x;
- if x memq '(!e !E)
- then if y = '(L U D O M D N E)
- or y = '(!l !u !d !o !m !d !n !e)
- then <<prin2 readch();
- terpri();
- terpri();
- prin2t "end;";
- return nil>>
- else y := list x
- else if x memq '(N D M O U L !n !d !m !o !u !l)
- then y := x . y
- else y := nil;
- go to a
- end;
- symbolic procedure make!-dist!-files u;
- % Makes a set of distribution files from the list of packages u.
- % Setting u to packages* in $rsrc/build/packages.red makes complete
- % set.
- for each x in u do make_dist_file x;
- symbolic procedure make_dist_file x;
- begin scalar !*downcase,!*echo,!*int,!*lower,msg,!*raise,ochan,
- oldochan,v;
- !*downcase := t;
- v := concat(string!-downcase x,".red");
- prin2 "Creating ";
- prin2 v;
- prin2t " ...";
- ochan := open(mkfil v,'output);
- oldochan := wrs ochan;
- evload list x; % To get package list.
- v := get(x,'package);
- if null v then v := list x;
- for each j in v do
- file!-transform(module2file(j,x),function write_module);
- prin2t if !*downcase then "end;" else "END;";
- wrs oldochan;
- close ochan
- end;
- symbolic procedure module2file(u,v);
- % Converts the module u to a fully rooted file name with v the
- % package name, assuming files exist on $rsrc followed by path
- % defined by package given by associate of u in modules!*.
- begin scalar x;
- x := "$reduce/src/";
- for each j in get(v,'path) do
- % x := concat(x,concat(string!-downcase j,dirchar!*));
- x := concat(x,concat(string!-downcase j,"/"));
- return concat(x,concat(string!-downcase u,".red"))
- end;
- symbolic procedure write_module;
- begin scalar x; repeat (x := write!-line nil) until x eq 'done end;
- symbolic procedure write!-line bool;
- begin integer countr; scalar x,y;
- countr := 0;
- % EOF kludge.
- while (x := readline()) = "" and countr<10 do countr := countr+1;
- if countr=10 then return 'done
- else if countr>0 then for i:=1:countr do terpri();
- y := explode2 x;
- if null bool and s!-match(y,"endmodule;")
- % or bool and s!-match(x,"end;")
- then <<prin2t if !*upcase then string!-upcase x
- else if !*downcase then string!-downcase x
- else x;
- if null bool then <<terpri(); terpri()>>;
- return 'done>>;
- x := y;
- a: if null x then return terpri();
- y := car x;
- b: if y = '!% then return <<for each j in x do prin2 j; terpri()>>
- else if y = '!"
- then <<prin2 y;
- x := write!-until(cdr x,'(!"))>>
- else if y = '!!
- then <<prin2 y;
- x := cdr x;
- if null x then rerror(ftr,3,"Missing character after !");
- prin2 car x>>
- else if s!-match(x,"comment")
- then <<if !*upcase then prin2 "COMMENT" else prin2 "comment";
- for j := 1:7 do x := cdr x;
- x := write!-until(x,'(!; !$))>>
- else if y = '! then
- <<countr := 1;
- while (x := cdr x) and (y := car x) = '! do
- countr := countr + 1;
- if null x then return terpri(); % Trailing blanks.
- for i:=1:countr do prin2 " ";
- go to b>>
- else <<prin2 if !*upcase and red!-lowercasep y
- then red!-char!-upcase y
- else if !*downcase and red!-uppercasep y
- then red!-char!-downcase y
- else y>>;
- x := cdr x;
- go to a
- end;
- symbolic procedure write!-until(x,u);
- begin scalar y;
- a: if null x
- then <<terpri();
- x := explode2 readline(); go to a>>;
- y := car x;
- prin2 y;
- if y memq u then return x;
- x := cdr x;
- go to a
- end;
- % ***** Converting a file to lower case *****.
- symbolic procedure downcase_file u;
- % Convert file named u to lower case version.
- begin scalar ochan,oldochan,!*downcase,!*echo,!*int,!*raise;
- prin2t "*** Output is in file 'output'";
- !*downcase := t;
- ochan := open("output",'output);
- oldochan := wrs ochan;
- file!-transform(u,function write!-file);
- wrs oldochan;
- close ochan
- end;
- symbolic procedure write!-file;
- begin scalar x;
- repeat (x := write!-line t) until x eq 'done end;
- % ***** truncating a file to 80 characters *****.
- symbolic procedure trunc u;
- % Truncate a file to 80 characters.
- <<lprim "output is in file 'output'";
- file!-transform(u,function read!-trunc)>>;
- symbolic procedure read!-trunc;
- begin integer count;
- scalar !*echo,!*int,!*raise,bool,ochan,oldochan,x;
- oldochan := wrs (ochan := open("output",'output));
- while (x := readch()) neq !$eof!$ do
- if x eq !$eol!$ then <<bool := nil; count := 0; terpri()>>
- else if null bool
- then <<prin2 x; bool := (count := count+1)>79>>;
- write oldochan;
- close ochan
- end;
- endmodule;
- end;
- % The material in the rest of this file is obsolete.
- % ***** Functions for manipulating files on the HP 9836 *****.
- symbolic procedure merge!-9836!-files u;
- % merges a list of 9836 files into a Cambridge format file v
- % corresponding to a UNIX directory.
- % Files are separated by the string "./ ADD NAME= <file name>.
- % Last file is terminated by "./ ENDUP".
- begin scalar ochan,oldochan,!*echo,!*int,!*raise;
- ochan := open(mkfil u,'output);
- oldochan := wrs ochan;
- for each x in get(u,'file!-list) do
- begin scalar y;
- if null(y := get(u,'alias)) then y := u;
- y := mkfilename(x,y);
- prin2 "./ ADD NAME=";
- if atom x then prin2t string!-upcase x
- else <<prin2 string!-upcase car x;
- prin2 ".";
- prin2t string!-upcase cdr x>>;
- file!-transform(y,function writefile)
- end;
- prin2t "./ ENDUP";
- wrs oldochan;
- close ochan
- end;
- symbolic procedure mkfilename(u,v);
- begin
- if atom u then u := u . "red";
- return concat(string!-downcase v,
- concat(":",concat(string!-downcase car u,
- concat(".",
- string!-downcase cdr u))))
- end;
- symbolic procedure writefile;
- begin scalar countr,x;
- countr := 0;
- repeat
- <<x := readline();
- if x = "" then countr := countr+1
- else <<if countr>0
- then <<for i:=1:countr do terpri(); countr := 0>>;
- prin2t x>>>>
- until countr = 10;
- end;
- % ***** functions for manipulating Cambridge PDS files *****.
- % To use the first function, connect to the directory where you want the
- % modules written, and then say
- % file!-transform("<source file>",
- % function split!-cambridge!-format);
- symbolic smacro procedure read!-ch(); current!-char!* := readch();
- symbolic procedure split!-cambridge!-format;
- % splits a file in Cambridge PDS format with ./ ADD records preceding
- % each member into constituent components.
- begin scalar x,!*echo,!*raise;
- while not((x := read!-ch()) eq !$eof!$) do
- if not previous!-char!*
- then if x eq '!. and readch() eq '!/
- then begin!-new!-cambridge!-member()
- else rerror(ftr,4,
- "File has incorrect format in first line")
- else if previous!-char!* eq !$eol!$ and x eq '!.
- then if read!-ch() eq '!/
- then begin!-new!-cambridge!-member()
- else rerror(ftr,5,
- "File has unmatched period in first column")
- else <<prin2 x; previous!-char!* := x>>;
- close!-cambridge!-member()
- end;
- symbolic procedure begin!-new!-cambridge!-member;
- begin scalar x,y,z;
- if member!-channel!* then close!-cambridge!-member();
- z := readline();
- x := cdr explode z;
- previous!-char!* := !$eol!$;
- if not ( x := matched2(x,'(! A D D ! N A M E !=)))
- then <<terpri(); prin2 "Ignoring line ./"; prin2 z; terpri();
- return nil>>;
- x := car x;
- while cdr x do
- <<y := (if red!-uppercasep car x then red!-char!-downcase car x
- else if car x eq '!$ then '!@
- else car x) . y;
- x := cdr x>>;
- y := reverse!-chars!-to!-string y;
- terpri();
- prin2 "Processing module "; prin2 y; prin2t " ...";
- y := concat(y,".red");
- member!-channel!* := open(y,'output);
- old!-channel!* := wrs member!-channel!*
- end;
- symbolic procedure matched2(u,v);
- if null v then list u
- else if null u then nil
- else car u eq car v and matched2(cdr u,cdr v);
- symbolic procedure close!-cambridge!-member;
- if not member!-channel!* then nil
- else <<close member!-channel!*; wrs old!-channel!*;
- member!-channel!* := old!-channel!* := nil>>;
- symbolic procedure merge!-cambridge!-format(u,v);
- % merges a list of files u into Cambridge PDS format file v
- % with ./ ADD records preceding each member.
- begin scalar ochan,oldochan,!*echo,!*raise;
- ochan := open(mkfil v,'output);
- oldochan := wrs ochan;
- for each x in u do write!-cambridge!-member x;
- prin2t "./ ENDUP";
- wrs oldochan;
- close ochan
- end;
- symbolic procedure write!-cambridge!-member u;
- begin scalar y;
- u := explode2 u;
- for each x in u do y := red!-char!-downcase x . y;
- y := concat(reverse!-chars!-to!-string y,".red"); %file name.
- y := concat(dir!*,y);
- prin2 "./ ADD NAME=";
- if eqcar(u,'!@) then u := '!$ . cdr u;
- for each x in u do prin2 x;
- terpri();
- file!-transform(y,function print!-cambridge!-file)
- end;
- symbolic procedure print!-cambridge!-file;
- begin scalar x;
- while not((x := readch()) eq !$eof!$) do
- % if x eq '![ then prin2 string 0 % PSL dependent
- % else if x eq '!] then prin2 string 4 else % PSL dependent
- prin2 x
- end;
- % ***** and to manipulate a message from Cambridge *****.
- % Note this code is PSL dependent.
- symbolic procedure cambs!-msg u;
- <<lprim "output is in file 'output'";
- file!-transform(u,function read!-cambridge!-message)>>;
- symbolic procedure read!-cambridge!-message;
- begin scalar !*echo,!*int,!*raise,ochan,oldochan,x;
- oldochan := wrs (ochan := open("output",'output));
- while (x := readch()) neq !$eof!$ do
- if x eq intern string 13 % PSL dependent
- then if readch() neq intern string 11 % PSL dependent
- then rerror(ftr,8,"missing ^L after ^M")
- else terpri()
- else prin2 x;
- wrs oldochan;
- close ochan
- end;
- % ***** functions for manipulating mfe document files *****.
- symbolic procedure mfe!-6to8bit(u,v);
- % converts six-bit file u into eight-bit file v.
- begin scalar ochan,oldochan;
- oldochan := wrs (ochan := open(v,'output));
- file!-transform(u,function mfe!-6to8bit1);
- wrs oldochan;
- close ochan
- end;
- symbolic procedure mfe!-6to8bit1;
- begin scalar oll,x,y;
- oll := linelength 100;
- while (x := readch()) neq !$eof!$ do
- if x eq '!^
- then if red!-uppercasep(y := readch()) then prin2 y
- else if y eq '![ then '!{
- else if y eq '!] then '!}
- else <<prin2 x; prin2 y>>
- else if x eq '!&
- then if (y := readch()) eq '!& then prin2 y
- else if y eq 'e
- and readch() eq 'p and readch() eq 'x
- then prin2 '!!
- else if y eq 'v
- and (y := readch()) and readch() eq 'x
- then prin2 y
- else if y eq 'f
- and readch() eq 'u and readch() eq 'x
- then prin2 '!|
- else if y eq 'i then prin2 "\&i"
- else rerror(ftr,9,"Invalid character after &")
- else if x eq '!$ then prin2 "\$"
- else if x eq '!% then prin2 "\%"
- else if red!-uppercasep x then prin2 red!-char!-downcase x
- else prin2 x;
- linelength oll
- end;
- symbolic procedure mfe!-8to6bit(u,v);
- % converts eight-bit file u into six-bit file v.
- begin scalar ochan,oldochan;
- oldochan := wrs (ochan := open(v,'output));
- file!-transform(u,function mfe!-8to6bit1);
- wrs oldochan;
- close ochan
- end;
- symbolic procedure mfe!-8to6bit1;
- begin scalar !*raise,oll,x;
- oll := linelength 160;
- while (x := readch()) neq !$eof!$ do
- if x eq '!& then prin2 "&&"
- else if x eq '!\ then prin2 readch()
- else if x eq '!! then prin2 "&EPX"
- else if x eq '!$ then prin2 "&V$X"
- else if x eq '!% then prin2 "&V%X"
- else if x eq '!| then prin2 "$FUX"
- else if x eq '!{ then prin2 "^["
- else if x eq '!} then prin2 "^]"
- else if red!-uppercasep x then <<prin2 '!^; prin2 x>>
- else if red!-lowercasep x then prin2 red!-char!-upcase x
- else prin2 x;
- linelength oll
- end;
|