helphtml.red 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. % helphtml.red
  2. %
  3. % interfacing reduce help file to HTML (world wide web)
  4. %
  5. % Author: Herbert Melenk, ZIB Berlin
  6. %
  7. % November 1992
  8. %
  9. % PSL dependent
  10. fluid '(outc newl par !*font !*newline !*html html_specials!* !*windows !*secondrun);
  11. fluid '(node_file_name!* current_base_dir !*directory_open CURRENT_NODE_NUMBER!*);
  12. !*HTML := t;
  13. !*windows := t;
  14. helvetica:= "R";
  15. courier:= "TT";
  16. !#if (member 'csl lispsystem!*)
  17. symbolic procedure rootname();
  18. "r36";
  19. symbolic procedure dest_directory();
  20. "html";
  21. !#else
  22. symbolic procedure rootname();
  23. getenv "package";
  24. symbolic procedure dest_directory();
  25. getenv "tdir";
  26. !#endif
  27. fluid '(node_file_labels filenumber indexfilename labels2nodes);
  28. filenumber:=0;
  29. symbolic procedure reset_html();
  30. <<
  31. indexfilename := make_html_file_name "index";
  32. filenumber := 0;
  33. >>;
  34. symbolic procedure html_open(u);
  35. myprin2(compress ('!" . ( '!< . append(explode2 u, '(!> !")) )) );
  36. symbolic procedure html_close(u);
  37. myprin2(compress ('!" . ( '!< . ( '!/ . append(explode2 u, '(!> !")) )) ));
  38. symbolic procedure open_current_base_dir u;
  39. % myprin2 " open_current_base_dir "; myprin2 u;
  40. nil;
  41. symbolic procedure close_current_base_dir ();
  42. % myprin2 " close_current_base_dir ";
  43. nil;
  44. symbolic procedure make_html_file_name u;
  45. begin scalar base,num;
  46. base := reversip explode2 rootname();
  47. while length base > 4 do base := cdr base;
  48. base := compress ('!" . reversip ('!" . base));
  49. !#if (member 'csl lispsystem!*)
  50. if u="main_index" then return bldmsg("%w.html",base)
  51. else if u="index" then num:="idx"
  52. else <<filenumber:=filenumber+1;
  53. num := compress('!" . append(cdr explode2
  54. (10000+filenumber),'(!")));
  55. >>;
  56. return bldmsg("%w_%w.html",base,num);
  57. !#else
  58. if u="main_index" then num:="_dir"
  59. else if u="index" then num:="_idx"
  60. else <<filenumber:=filenumber+1;
  61. num := compress('!" . append(cdr explode2
  62. (10000+filenumber),'(!")));
  63. >>;
  64. return bldmsg("%w%w.html",base,num);
  65. !#endif
  66. end;
  67. symbolic procedure open_node_file u;
  68. begin scalar dir,name;
  69. dir:=if (dir:=dest_directory()) then bldmsg("%w/",dir) else "";
  70. name := node_file_name!* := make_html_file_name u;
  71. labels2nodes := (name . u) . labels2nodes;
  72. % non-unix and PSL: open with suffix "htm".
  73. if not member('unix,lispsystem!*) and member('psl, lispsystem!*) then
  74. name:= compress ('!" . reversip('!" . cdr reversip explode2 name));
  75. if outfile!* then close outfile!*;
  76. outfile!* := open(bldmsg("%w%w",dir,name), 'output);
  77. return outfile!*;
  78. end;
  79. symbolic procedure close_node_file ();
  80. if outfile!* then << close outfile!*; outfile!* := nil;
  81. node_file_name!* := nil;
  82. >>;
  83. symbolic procedure node_file_name(); node_file_name!*;
  84. symbolic procedure initoutput (); nil;
  85. symbolic procedure endoutput(); nil;
  86. symbolic procedure verbatim u;
  87. !*verbatim := u;
  88. symbolic procedure newfont(f);
  89. if currentfont neq f then
  90. <<fontoff(); currentfont:=f; fonton()>>;
  91. symbolic procedure fontoff();
  92. <<% if !*font then channelprin2(outfile!*,"}");
  93. outc:=nil;
  94. !*font:=nil>>;
  95. symbolic procedure fonton();
  96. <<if not !*font then
  97. <<% channelprintf(outfile!*,"{\%w ",currentfont); outc := nil
  98. >>;
  99. !*font:=t>>;
  100. symbolic procedure myprin2 u;
  101. <<!*newline:=nil; channelprin2(outfile!*,u)>>;
  102. deflist( '((!< "&lt;")
  103. (!> "&gt;")
  104. (!" "&quot;")
  105. (!& "&amp;")),
  106. 'HTML_Symbol_Name);
  107. html_specials!* := '(!< !> !" !&);
  108. symbolic procedure myprin2_protected u;
  109. <<if u memq html_specials!* then myprin2 get(u, 'HTML_Symbol_Name)
  110. else myprin2 u;
  111. u
  112. >>;
  113. fluid '(!*verbescape);
  114. symbolic procedure emit_start_verbatim();
  115. <<html_open "P"; html_open "PRE"; html_open "TT">>;
  116. symbolic procedure emit_end_verbatim();
  117. <<html_close "TT"; html_close "PRE"; html_open "P">> ;
  118. symbolic procedure verbprin2 u;
  119. if u = '!\ then << !*verbescape :=t>>
  120. else
  121. if u=!$eol!$ then << myterpri();!*verbescape := nil>>
  122. else
  123. if (u = '!&) then
  124. <<myprin2 " _ _ _ "; !*verbescape:=par:=newl:=outc:=nil>>
  125. else
  126. if u memq html_specials!* then
  127. <<if not !*verbescape then myprin2_protected u else myprin2 u;
  128. !*verbescape := nil>>
  129. else
  130. <<myprin2 u; !*verbescape := nil>>;
  131. symbolic procedure myterpri();
  132. channelterpri outfile!*;
  133. symbolic procedure number4out n;
  134. % print number with 4 digits.
  135. << if n<10 then textout "0";
  136. if n<100 then textout "0";
  137. if n<1000 then textout "0";
  138. textout n>>;
  139. % par = t: paragraph has been terminated - no new data so far
  140. % newl = t: last character has been an EOL
  141. symbolic procedure textout(u);
  142. if par and (u=!$eol!$ or u='! ) then nil else
  143. if stringp u then mapc(explode2 u, 'textout) else
  144. <<fonton();
  145. if u=!$eol!$ and (!*verbatim or newl)
  146. then <<print_newline();
  147. outc:='! ;
  148. if not !*verbatim then second_newline();
  149. newl:=nil;
  150. par:=t
  151. >>
  152. else
  153. if (u = '!&) then
  154. <<myprin2 " _ _ _ "; par:=newl:=outc:=nil>>
  155. else
  156. if (u = '!$) then
  157. newfont(if currentfont = helvetica then courier else helvetica)
  158. else
  159. if (u memq html_specials!*) then <<myprin2_protected u>> else
  160. if (u neq '! ) or (outc neq '! ) or !*verbatim
  161. then
  162. <<if u=!$eol!$ and outc neq '! then myprin2 '! ;
  163. myprin2(u); outc := u;
  164. if u=!$eol!$ then newl:=t else
  165. if u neq '! then newl:=nil;
  166. par:=nil;
  167. >>;
  168. >>;
  169. % -------- paragraph heading ---------------------------
  170. symbolic procedure par_heading(type);
  171. <<myprin2 " <P> <H3> ";
  172. verbprin2 !$eol!$;
  173. for each x in explode type do verbprin2 x;
  174. verbprin2 ": </H3>";
  175. verbprin2 !$eol!$;
  176. >>;
  177. % -------- directory structure -------------------------
  178. symbolic procedure base_new_dir(name);
  179. <<%myprin2 "base_new_dir name="; myprin2 name;
  180. close_current_base_dir();
  181. open_current_base_dir name;
  182. current_base_dir := name>>;
  183. symbolic procedure emit_dir_new();
  184. <<%print current_base_dir;
  185. %open_node_file current_base_dir
  186. nil>>;
  187. symbolic procedure emit_dir_key u;
  188. emit_node_key u;
  189. symbolic procedure emit_dir_separator();
  190. emit_node_separator();
  191. symbolic procedure emit_dir_label u;
  192. emit_node_label u;
  193. symbolic procedure emit_dir_title u;
  194. emit_node_title(u,nil,'section);
  195. symbolic procedure emit_dir_browse(u,n);
  196. emit_node_browse(u,n);
  197. % ---- node structure
  198. symbolic procedure emit_node_separator();
  199. <<fonton();
  200. if !*directory_open then <<html_close "MENU" ;
  201. !*directory_open := nil>>;
  202. %myterpri(); myterpri();
  203. %channelprin2(outfile!*,"emit_node_separator");
  204. %myterpri(); myterpri();
  205. outc:='! ; par:=t;
  206. close_node_file();
  207. >>;
  208. symbolic procedure set_tab(); nil;
  209. % myprin2 "set_tab ";
  210. symbolic procedure release_tab(); nil;
  211. % myprin2 "release_tab ";
  212. symbolic procedure textout_name(l);
  213. % l is a list of characters to be printed.
  214. % special action for names: \ in front of _ suppressed because
  215. % of Microsoft HC logic (don't know why).
  216. if atom l then textout l else
  217. while l do
  218. <<if not(car l = '!\) or null cdr l or not(cadr l = '!_)
  219. then textout car l;
  220. l := cdr l>>;
  221. symbolic procedure textout2(l);
  222. if l then
  223. if atom l then myprin2 l else
  224. for each x in l do myprin2
  225. if x='! then '!_ else x;
  226. symbolic procedure printem(s);
  227. % print italic
  228. begin
  229. html_open "em";
  230. mapc(s,'myprin2);
  231. html_close "em";
  232. end;
  233. symbolic procedure printem(s);
  234. begin
  235. fontoff();
  236. html_open "em";
  237. mapc(s,'myprin2_protected);
  238. html_close "em";
  239. end;
  240. symbolic procedure printref u;
  241. begin scalar r,s;
  242. % print ( ">>>" . u);
  243. r:= get_label u;
  244. % s := assoc (u,node_file_labels);
  245. s := assoc (r,node_file_labels);
  246. if s then s := cdr s
  247. % Debug lines here...
  248. else if run!* > 1 then <<
  249. prin2 "### reference to "; prin u;
  250. prin2 " with label "; prin r;
  251. prin2t " not found."
  252. >>;
  253. if null r then return printem u;
  254. fontoff();
  255. myterpri();
  256. myprin2 "<A HREF="; myprin2 s;
  257. %myprin2 "#"; mapc(r, 'myprin2);
  258. myprin2 ">";
  259. mapc(u,'myprin2); html_close "A";
  260. end;
  261. symbolic procedure printnameref u;
  262. printref u;
  263. fluid '(key_database);
  264. symbolic procedure emit_node_keys u;
  265. begin scalar keys;
  266. keys := assoc(u,key_database);
  267. if null keys then return;
  268. keys := cdr keys;
  269. fonton();
  270. myterpri();
  271. while keys do
  272. << %myprin2 "<A NAME="; textout_name car keys;
  273. % number4out current_node_number!* ; myprin2 ">";
  274. % textout_name car keys;
  275. % myprin2 " . </A>";
  276. prin2 "### add node "; prin car keys, prin2 " "; print node_file_name!*;
  277. node_file_labels := ( car keys . node_file_name!*) . node_file_labels;
  278. % print ( "<=>" . car keys);
  279. keys:= cdr keys;
  280. %if keys then myprin2";"
  281. >>;
  282. myterpri();
  283. end;
  284. symbolic procedure emit_node_key u;
  285. emit_hidden_node_key u;
  286. symbolic procedure emit_hidden_node_key u;
  287. if current_node!* then
  288. begin scalar q;
  289. q:= assoc(current_node!*,key_database);
  290. if null q then
  291. key_database := (current_node!* . {u}).key_database
  292. else
  293. if not member(u,cdr q) then cdr q:=u.cdr q;
  294. end;
  295. symbolic procedure emit_node_label u;
  296. <<open_node_file u;
  297. fonton();
  298. myterpri();
  299. myprin2 "<A NAME=";
  300. textout_name u;
  301. myprin2 ">";
  302. myterpri();
  303. prin2 "#### add node "; prin u, prin2 " "; print node_file_name!*;
  304. node_file_labels := ( u . node_file_name!* ) . node_file_labels;
  305. >>;
  306. symbolic procedure emit_node_title(u,dummy,type);
  307. <<fonton();
  308. myterpri();
  309. html_open "TITLE";
  310. textout_name u;
  311. html_close "TITLE";
  312. html_close "A"; % from emit_node_label
  313. myterpri();
  314. channelprintf(outfile!*,"<b><a href=%w>INDEX</a></b><p><p>%n",indexfilename);
  315. >>;
  316. symbolic procedure emit_node_browse(u,n);
  317. <<fonton();
  318. % myterpri();
  319. % myprin2 "<A NAME=";
  320. % textout2 u;
  321. % number4out n;
  322. current_node_number!* := n;
  323. % myprin2 "> . </A>";
  324. % myterpri();
  325. prin2 "##### add node "; prin u, prin2 " "; print node_file_name!*;
  326. node_file_labels := ( u . node_file_name!* ) . node_file_labels;
  327. >>;
  328. symbolic procedure print_bold u;
  329. <<fontoff();
  330. html_open "B";
  331. mapc(u,'myprin2);
  332. html_close "B";
  333. >>;
  334. symbolic procedure emit_dir_header();
  335. <<
  336. fontoff();
  337. html_open "MENU";
  338. !*directory_open := t;
  339. myterpri();
  340. >>;
  341. symbolic procedure emit_dir_entry(name,lab);
  342. begin scalar alias, s;
  343. s:= assoc(lab,node_file_labels); if s then s := cdr s;
  344. fontoff();
  345. html_open "LI"; myprin2 "<A HREF=";
  346. textout2 s; % myprin2 ".html";
  347. % myprin2 "#"; textout2 lab;
  348. myprin2 ">";
  349. mapc(name,'myprin2);
  350. html_close "A";
  351. % myterpri();
  352. % myprin2 "{\v\f2 ";
  353. if (alias:=assoc(lab,aliases)) then
  354. <<myprin2 "alias= "; myprin2 cdr alias>>;
  355. % myprin2 " ENDemit_dir_entry";
  356. print_newline();
  357. end;
  358. symbolic procedure print_newline();
  359. <<if null !*newline then
  360. <<fonton(); channelprin2(outfile!*,"<P>"); channelterpri outfile!*>>;
  361. !*newline:=t
  362. >>;
  363. symbolic procedure second_newline();
  364. <<!*newline :=nil; print_newline()>>;
  365. symbolic procedure print_tab ();
  366. <<fonton(); myprin2 " _ _ _ ">>;
  367. %------------------- HTML index file --------------------------------
  368. symbolic procedure html_indexfile();
  369. begin scalar u,v,q,r,s,rr,!*lower;
  370. prin2t "..... compiling html index file";
  371. s := for each q in node_file_labels join
  372. if pairp car q then {sort_term car q . q};
  373. s := sort(s,'html_indexfile_sort);
  374. % remove trivial entries
  375. r:=s;
  376. while r do
  377. <<u:=car r; r:=cdr r;
  378. if car u member
  379. '((c o m m a n d)
  380. (c o n c e p t)
  381. (c o n s t a n t)
  382. (d e c l a r a t i o n)
  383. (i n t r o d u c t i o n)
  384. (o p e r a t o r)
  385. (p a c k a g e)
  386. (s w i t c h)
  387. (v a r i a b l e)
  388. )
  389. then s:=deletip(u,s);
  390. >>;
  391. % remove duplicates
  392. r:=s;
  393. while r and cdr r do
  394. <<u:=car r; rr:=r:=cdr r;
  395. while rr and html_indexfile_subsetp(car u,car (v:=car rr)) do
  396. <<if cddr u = cddr v then s:=deletip(u,s); rr:=cdr rr>>;
  397. >>;
  398. open_node_file "index";
  399. channelprintf(outfile!*, "<title>%w search index</title>%n",rootname());
  400. channelprintf(outfile!*, "<dl compact><isindex>%n");
  401. channelprintf(outfile!*, "<menu>%n");
  402. for each x in s do
  403. <<channelprin2(outfile!*, "<dt>");
  404. for each c in cadr x do
  405. if c='!_ then channelprin2(outfile!*," ") else
  406. if not(c='!\) then channelprin2(outfile!*,c);
  407. channelprintf(outfile!*, ": <a href=%w>",cddr x);
  408. q := cdr assoc(cddr x,labels2nodes);
  409. for each c in q do
  410. if c='!_ then channelprin2(outfile!*," ") else
  411. if not(c='!\) then channelprin2(outfile!*,c);
  412. channelprin2t(outfile!*, "</a>");
  413. >>;
  414. channelprintf(outfile!*, "</menu>%n");
  415. close outfile!*;
  416. outfile!*:=nil;
  417. end;
  418. symbolic procedure sort_term u;
  419. for each c in raisestring u join
  420. if liter c or digit c then {c};
  421. symbolic procedure html_indexfile_sort(u,v);
  422. html_indexfile_sort1(car u,car v);
  423. symbolic procedure html_indexfile_sort1(u,v);
  424. if null u then t else
  425. if null v then nil else
  426. if car u = car v then html_indexfile_sort1(cdr u,cdr v) else
  427. id2int car u < id2int car v;
  428. symbolic procedure html_indexfile_subsetp(a,b);
  429. null a or
  430. b and car a = car b and html_indexfile_subsetp(cdr a,cdr b);
  431. %------------------- LISP index file --------------------------------
  432. symbolic procedure LISP_indexfile();
  433. begin scalar u,v,q,r,s,rr,!*lower,pack;
  434. prin2t "..... compiling independent index file";
  435. pack := rootname();
  436. s := for each q in node_file_labels join
  437. if pairp car q then {sort_term car q . q};
  438. s := sort(s,'html_indexfile_sort);
  439. % remove trivial entries
  440. r:=s;
  441. while r do
  442. <<u:=car r; r:=cdr r;
  443. if car u member
  444. '((c o m m a n d)
  445. (c o n c e p t)
  446. (c o n s t a n t)
  447. (d e c l a r a t i o n)
  448. (i n t r o d u c t i o n)
  449. (o p e r a t o r)
  450. (p a c k a g e)
  451. (s w i t c h)
  452. (v a r i a b l e)
  453. )
  454. then s:=deletip(u,s);
  455. >>;
  456. % remove duplicates
  457. r:=s;
  458. while r and cdr r do
  459. <<u:=car r; rr:=r:=cdr r;
  460. while rr and html_indexfile_subsetp(car u,car (v:=car rr)) do
  461. <<if cddr u = cddr v then s:=deletip(u,s); rr:=cdr rr>>;
  462. >>;
  463. outfile!*:= open(bldmsg("%w.hdx",pack),'output);
  464. channelprintf(outfile!*, "%w generated from reference manual >%w< %n",'!%,pack);
  465. channelprintf(outfile!*, "%w (node text description status details) %n",'!%,pack);
  466. for each x in s do
  467. <<channelprin2(outfile!*, "(");
  468. q := cdr assoc(cddr x,labels2nodes);
  469. for each c in q do
  470. if not(c='!\) then
  471. <<c:=id2int c;
  472. if c> 64 and c<91 then c:=c+32;
  473. channelprin2(outfile!*,int2id c)>>;
  474. channelprin2(outfile!*,'! );
  475. channelprin2(outfile!*,'!");
  476. for each c in cadr x do
  477. if not(c='!\) then channelprin2(outfile!*,c);
  478. channelprin2(outfile!*,'!");
  479. channelprin2(outfile!*,'! );
  480. channelprintf(outfile!*," %w help nil)%n", pack);
  481. >>;
  482. close outfile!*;
  483. outfile!*:=nil;
  484. end;
  485. %------------------- printstruct -------------------------------
  486. symbolic procedure printstruct();
  487. <<terpri(); printstruct1(car record,1)>>;
  488. symbolic procedure printstruct1(r,n);
  489. <<for i:=1:n do prin2 " ";
  490. mapc(name r,'prin2);
  491. terpri();
  492. for each x in reverse seq r do
  493. printstruct1(nil . x,n+1);
  494. >>;
  495. end;
  496.