helphtml.red 17 KB

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