comphelp.red 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081
  1. % comphelp.red:
  2. %
  3. % first part of the REDUCE help compiler: syntax analysis
  4. % and structure generation.
  5. %
  6. % the second part contains target specific code.
  7. %
  8. % Author: Herbert Melenk, ZIB Berlin
  9. %
  10. % November 1992
  11. %
  12. symbolic;
  13. fluid '(char!* infile!* outfile!* !*windows !*test !*myeof);
  14. fluid '(printfunction!* sect_count endchar current_node!*);
  15. fluid '(!*verbatim !*sqbkt !*opennode currentfont topiccount!*);
  16. fluid '(courier helvetica outc beginstack filestack level);
  17. fluid '(nodechain undo match_point_lft match_point_rgt);
  18. fluid '(run!* dir_src);
  19. fluid '(aliases package);
  20. fluid '(section_list regoup_sections);
  21. fluid '(help_gensym_count);
  22. run!* := 0;
  23. % !*test := t;
  24. regoup_sections := nil;
  25. %------------------------------------------------------------
  26. %
  27. % MAIN PROGRAM
  28. %
  29. %------------------------------------------------------------
  30. symbolic procedure job(infile,outfile);
  31. begin scalar !*raise, !*lower;
  32. help_gensym_count := 1;
  33. section_list := nil;
  34. !*myeof := nil;
  35. if getenv "echo" then !*echo:=t;
  36. run!* := run!* + 1;
  37. reset(); terpri();
  38. if run!* = 2 then update_labels();
  39. !*opennode := nil;
  40. sect_count:=1;
  41. topiccount!* := 0;
  42. printfunction!*:=nil;
  43. if infile!* then close infile!*;
  44. if outfile!* then close outfile!*;
  45. infile!*:=open(bldmsg("%w%w",dir_src,infile),'input);
  46. outfile!*:=open(outfile,'output);
  47. channellinelength(outfile!*,200);
  48. initoutput();
  49. newfont helvetica;
  50. mainloop();
  51. close_section 'document;
  52. write_sections();
  53. fontoff();
  54. endoutput();
  55. close infile!*;
  56. infile!* :=nil;
  57. if outfile!* then close outfile!*;
  58. outfile!*:=nil;
  59. % printstruct();
  60. end;
  61. %------------------------------------------------------------
  62. %
  63. % file input
  64. %
  65. %------------------------------------------------------------
  66. fluid '(oldchar !*myecho !*myeof);
  67. !*myecho := nil;
  68. !*myeof := nil;
  69. symbolic procedure rdch(); rdchr0(nil);
  70. symbolic procedure rdch!*(); rdchr0(t);
  71. symbolic procedure rdchr0(q);
  72. if !*myeof then !$eof!$ else
  73. if oldchar then <<oldchar := nil; old>> where old = oldchar
  74. else
  75. <<char!*:= channelreadch(infile!*);
  76. if !*myecho then prin2 char!*;
  77. if inf char!* = 9 then char!* := tab!* else % tab
  78. if not q and prevchar neq '!\ and char!*='!% then
  79. <<while !$eol!$ neq channelreadch(infile!*) do nil;
  80. rdch()>>
  81. else char!*
  82. >> where prevchar = char!*;
  83. symbolic procedure unrdch(); oldchar := char!*;
  84. symbolic procedure myskip c;
  85. while (c neq rdch()) do nil;
  86. symbolic procedure myskipl l;
  87. begin scalar c;
  88. while not memq(c:=rdch(),l) do nil;
  89. return c;
  90. end;
  91. symbolic procedure myskipstring(s1,s2);
  92. begin scalar l,c,r;
  93. l:=explode2 s2;
  94. while l do
  95. <<c:=rdch(); r:=c.r;
  96. if c neq car l then
  97. error(99, {"EXPECTED:", {s1,s2},"FOUND:",{s1,reversip r}});
  98. l:=cdr l;
  99. >>;
  100. end;
  101. fluid '(case!*);
  102. case!*:= if '!N!I!L then 'lower else 'upper;
  103. symbolic procedure mytoken(fold);
  104. begin scalar tok,c,n;
  105. tok:={'!"};
  106. while digit(c:=rdch()) or liter c do
  107. << n:=id2int c;
  108. if fold then
  109. if case!* = 'upper and n then
  110. c:=int2id(n-32)
  111. else if case!*='lower and 64<n and n<91 then
  112. c:=int2id(n+32);
  113. tok:=c.tok;
  114. >>;
  115. % if we have found a token, eat up the following blanks.
  116. % if cdr tok then while c='! do c:=rdch(); % ACH: loses a char.
  117. if null cdr tok then return nil;
  118. tok := compress reverse('!".tok);
  119. return intern tok;
  120. end;
  121. symbolic procedure mystring();
  122. begin scalar tok,c;
  123. while digit(c:=rdch()) or liter c or c='! or
  124. (endchar and c neq endchar) do
  125. tok:=c.tok;
  126. return reversip(tok);
  127. end;
  128. symbolic procedure mystring2();
  129. % read string util }, but ignore \}
  130. begin scalar tok,c;
  131. while (c:=rdch()) neq '!} do tok:=c.tok;
  132. return reversip(tok);
  133. end;
  134. symbolic procedure mystring2!]();
  135. % read string util ], but ignore \}
  136. begin scalar tok,c;
  137. while (c:=rdch!*()) neq '!] do tok:=c.tok;
  138. return reversip(tok);
  139. end;
  140. symbolic procedure mystring_nodename();
  141. % read node name, eventually updating the name translation table
  142. % for entries like "\begin{Command}[percent]{%}"
  143. % read string util }, but ignore \}
  144. begin scalar tok,c,alt;
  145. c:=myskipl '(!{ ![);
  146. if c='![ then
  147. << alt := mystring2!](); myskip '!{ >>;
  148. while (c:=rdch!*()) neq '!} do tok:=c.tok;
  149. tok := reversip tok;
  150. if alt then aliases := (alt . tok) . aliases;
  151. return alt or tok;
  152. end;
  153. symbolic procedure mystring3();
  154. begin scalar tok,c;
  155. loop:
  156. c:=rdch();
  157. if c='!\ then <<tok := rdch().tok; goto loop>>;
  158. if c= '!} then return reversip(tok);
  159. tok := c.tok; goto loop;
  160. end;
  161. symbolic procedure raisestring(s);
  162. begin scalar n;
  163. return for each c in s collect
  164. if (n:=id2int c)>95 then
  165. int2id(n-32) else c;
  166. end;
  167. symbolic procedure lowerstring(s);
  168. begin scalar n;
  169. return for each c in s collect
  170. if liter c and (n:=id2int c)<95 then
  171. int2id(n+32) else c;
  172. end;
  173. symbolic procedure mycompress u;
  174. compress reversip('!" . reverse('!" . u));
  175. %---------------------- main loop ----------------------------
  176. symbolic procedure mainloop();
  177. begin scalar u,c,tok,f,undo;
  178. loop:
  179. c:=rdch();
  180. if c=!$eof!$ then goto finis;
  181. if endchar and c=endchar then
  182. <<endchar:=nil; goto finis>>;
  183. if c='!{ then
  184. <<
  185. begin scalar endchar;
  186. endchar := '!};
  187. mainloop();
  188. end;
  189. goto loop;
  190. >>;
  191. if c='!\ then
  192. <<tok:=mytoken(t);
  193. if tok='ENDINPUT then <<!*myeof := t; goto finis>>;
  194. if null tok then
  195. <<c:=if char!*='!\ then !$eol!$ else c:=char!*;
  196. goto char>>;
  197. if tok='documentstyle then
  198. <<myskip('!}); goto loop>>
  199. else
  200. if tok='end then
  201. <<u:=mytoken(t);
  202. if !*test then <<prin2 " \end{"; prin2 u; prin2 "} ">>;
  203. if u neq car beginstack then
  204. <<prin2t {"****** begin(",car beginstack,
  205. ") ended with end (",u,")"};
  206. exitlisp(1);
  207. >>;
  208. if !*test then printf(" (main pop %w)",beginstack);
  209. beginstack := cdr beginstack;
  210. goto finis>>
  211. else
  212. if(f:=get(tok,'act)) then
  213. <<
  214. if !*test then <<prin2 " \"; prin2 tok; prin2 " ">>;
  215. apply1(f,tok);
  216. if flagp(f,'simple) then oldchar := char!*;
  217. goto loop;
  218. >>
  219. else
  220. printf("**** unknown token: %w %n",tok);
  221. >>;
  222. char:
  223. if printfunction!* then apply1(printfunction!*,c);
  224. goto loop;
  225. finis:
  226. for each u in undo do eval(u);
  227. end;
  228. %-----------------\input{...} \include{ ...}-----------------
  229. symbolic procedure include(u);
  230. begin scalar file,fname,fname1,endchar;
  231. endchar := '!};
  232. fname:=mycompress mystring();
  233. if fname = "intro" then return;
  234. fname:=bldmsg("%w%w",dir_src,fname);
  235. endchar := nil;
  236. file:=errorset({'open,mkquote fname,mkquote 'input},nil,nil);
  237. if not errorp file then goto found;
  238. fname1:=bldmsg("%w.tex",fname);
  239. file:=errorset({'open,mkquote fname1,mkquote 'input},nil,nil);
  240. if not errorp file then goto found;
  241. printf("***** cannot open file >%w< resp. >%w< %n",fname,fname1);
  242. return nil;
  243. found:
  244. if fname1 then fname := fname1;
  245. filestack:=infile!*.filestack;
  246. infile!* :=car file;
  247. terpri(); prin2 "--- input file "; prin2t fname;
  248. mainloop();
  249. terpri(); prin2 "--- return from file "; prin2t fname;
  250. close infile!*;
  251. !*myeof := nil;
  252. infile!*:=car filestack;
  253. filestack := cdr filestack;
  254. end;
  255. put('input,'act,'include);
  256. put('include,'act,'include);
  257. put('makeindex,'act,'null);
  258. put('tt,'act,'null);
  259. %-------------------section hierarchy -----------------------
  260. symbolic procedure print_indent();
  261. if numberp level then for i:=1:level do prin2 " ";
  262. fluid '(record act_rec node_count);
  263. node_count := 0;
  264. smacro procedure type(u); car u;
  265. smacro procedure seq(u); cadr u;
  266. smacro procedure lab(u); caddr u;
  267. smacro procedure count(u); cadddr u;
  268. smacro procedure name(u);car cddddr u;
  269. symbolic procedure reset();
  270. <<
  271. record :=
  272. {
  273. % type seq lab nr name
  274. {'document, nil, "main_index",
  275. 1, '(!T !o !p)},
  276. % 1, "Top"},
  277. {'section, nil, nil, 1, nil},
  278. {'subsection,nil, nil, 1, nil},
  279. {'subsubsection,nil, nil, 1, nil}};
  280. act_rec:= car record;
  281. >>;
  282. symbolic procedure sectappend r;
  283. % link tail from next record to cont of first one
  284. car cdar r :=(cdr cadr r) . seq car r;
  285. %-------------------- section -------------------------------
  286. symbolic procedure section(s);
  287. begin scalar name;
  288. current_node!* := nil;
  289. name:=mystring2();
  290. close_section(s);
  291. open_section(s,name);
  292. end;
  293. symbolic procedure close_section(s);
  294. begin scalar r;
  295. r:=record;
  296. while r and caar r neq s do r:= cdr r;
  297. if null r then error({"record empty",s},99);
  298. for each u in reverse r do close_section1 u;
  299. end;
  300. symbolic procedure close_section1(rec);
  301. if name rec then
  302. begin
  303. if !*windows then
  304. << print_indent(); reporttopic(" section end: ");
  305. terpri();
  306. >>;
  307. if regoup_sections then
  308. section_list := append(rec,nil) . section_list
  309. else
  310. write_section(rec);
  311. cdr rec:={nil,nil,0,nil};
  312. end;
  313. symbolic procedure write_sections();
  314. for each s in section_list do write_section s;
  315. symbolic procedure write_section(rec);
  316. if name rec then
  317. begin
  318. if !*opennode then emit_node_separator();
  319. !*opennode:=nil;
  320. emit_dir_new();
  321. emit_dir_label(lab rec);
  322. emit_dir_title name rec;
  323. emit_dir_browse('index,count rec);
  324. emit_dir_key(name rec);
  325. print_bold name rec;
  326. emit_dir_header();
  327. for each x in reverse seq rec do
  328. make_dir_entry (nil.x);
  329. emit_dir_separator();
  330. end;
  331. symbolic procedure make_dir_entry rec;
  332. emit_dir_entry(name rec,lab rec);
  333. symbolic procedure help_gensym();
  334. compress ('!g . explode2 (help_gensym_count := help_gensym_count+1));
  335. symbolic procedure open_section(s,n);
  336. begin scalar r;
  337. sect_count:=sect_count+1;
  338. r:= record;
  339. while r and cdr r and caadr r neq s do r:=cdr r;
  340. if null r then error({"record empty",s},99);
  341. % initialize new section and link to parent
  342. if not !*windows then n:=append(n, '(! !s !e !c !t !i !o !n));
  343. cdr cadr r:={nil,help_gensym(),sect_count,n};
  344. sectappend r;
  345. r:= cadr r;
  346. level := if s='section then 0 else
  347. if s='subsection then 1 else
  348. if s='subsubsection then 2 else 3;
  349. print_indent();
  350. for each c in lowerstring explode2 s do prin2 c;
  351. prin2 " ";
  352. prin2 count r; prin2 " ";
  353. prin2 lab r; prin2 " ";
  354. mapc(name r,'prin2); terpri();
  355. act_rec := r;
  356. base_new_dir name r;
  357. level := if s='section then 1 else
  358. if s='subsection then 2 else
  359. if s='subsubsection then 3 else 4;
  360. end;
  361. put('section,'act,'section);
  362. put('subsection,'act,'section);
  363. put('subsubsection,'act,'section);
  364. %------------------- begin-end contexts ---------------------------
  365. symbolic procedure beg(u);
  366. begin scalar tok,f,w;
  367. tok:=mytoken(t);
  368. for each c in beginstack do w:=w or (get(c,'context)='node);
  369. if w and 'node=get(tok,'context) then
  370. <<printf("===== missing end of node; hierarchy: %w",beginstack);
  371. exitlisp()>>;
  372. if !*test then <<terpri(); prin2 "\begin{"; prin2 tok;prin2 "}">>;
  373. if !*test then printf(" (push %w)",tok);
  374. beginstack := tok.beginstack;
  375. f:=get(tok,'context);
  376. if f then apply1(f,tok) else
  377. <<prin2t {"******* unknown begin-context:",tok};
  378. mainloop()>>;
  379. end;
  380. put('begin,'act,'beg);
  381. symbolic procedure mmain(u); mainloop();
  382. put('document,'context,'mmain);
  383. %------------------- generate unique labels ----------------------
  384. fluid '(labels!* l_list name_trans);
  385. symbolic procedure clean_name u;
  386. if null u then nil else
  387. if car u memq '(!- !, !? !* !> !< !. ! )
  388. then '!_ . clean_name cdr u else
  389. car u . clean_name cdr u;
  390. name_trans :='(
  391. ((!,) . COMMA_sign)
  392. ((!.) . DOT_sign)
  393. ((!;) . SEMICOLON_sign)
  394. ((!%) . PERCENT_sign)
  395. ((!$) . DOLLAR_sign)
  396. ((!: !=) . ASSIGN_sign)
  397. ((!=) . EQUAL_sign)
  398. ((!+) . PLUS_sign)
  399. ((!-) . MINUS_sign)
  400. ((!*) . TIMES_sign)
  401. ((!/) . SLASH_sign)
  402. ((!* !*) . POWER_sign)
  403. ((!$ !> != !$) . GEQ_sign)
  404. ((!> !=) . GEQ_sign)
  405. ((!>) . GREATER_sign)
  406. ((!$ !< != !$) . LEQ_sign)
  407. ((!< != ) . LEQ_sign)
  408. ((!<) . LESS_sign)
  409. ((!< !<) . BLOCK));
  410. symbolic procedure make_label(name, type, alias);
  411. begin scalar u,s,w,uname;
  412. uname := raisestring name;
  413. if !*windows then
  414. << alias := clean_name alias;
  415. name := clean_name name>>;
  416. s := uname . type;
  417. u := assoc (s,labels!*);
  418. if u and run!* = 1 then
  419. <<prin2 " ######## duplicate node ";
  420. prin2 name;
  421. terpri();
  422. >>;
  423. if u then return cadr u;
  424. labels!* := (s.(w:=alias.name.type)). labels!*;
  425. if not member(uname,l_list) then
  426. l_list := uname . l_list;
  427. return car w;
  428. end;
  429. symbolic procedure get_label name;
  430. (if l then car l) where l=get_label1 name;
  431. symbolic procedure patch_ u;
  432. if null u then nil else
  433. if car u = '!_ then '!\ . '!_ . patch_ cdr u
  434. else car u . patch_ cdr u;
  435. symbolic procedure get_label1 name;
  436. begin scalar u,uname;
  437. uname := raisestring name;
  438. u := get_label2 uname or get_label2 patch_ uname;
  439. if null u and (run!* > 1) then
  440. <<prin2 " ######## reference to ";
  441. prin2 name;
  442. prin2t " not found,";
  443. >>;
  444. return if u then cdr u else nil;
  445. end;
  446. symbolic procedure get_label2 uname;
  447. begin scalar u,uname;
  448. u := assoc((uname . 'operator),labels!*)
  449. or assoc((uname . 'function),labels!*)
  450. or assoc((uname . 'switch),labels!*)
  451. or assoc((uname . 'statement),labels!*)
  452. or assoc((uname . 'command),labels!*)
  453. or assoc((uname . 'declaration),labels!*)
  454. or assoc((uname . 'variable),labels!*)
  455. or assoc((uname . 'type),labels!*)
  456. or assoc((uname . 'constant),labels!*)
  457. or assoc((uname . 'concept),labels!*)
  458. or assoc((uname . 'package),labels!*)
  459. or assoc((uname . 'introduction),labels!*);
  460. return u;
  461. end;
  462. symbolic procedure update_labels();
  463. % for unique names use the name as label.
  464. begin scalar new,old;
  465. terpri();
  466. prin2t "------ updating node labels -----";
  467. for each p in l_list do
  468. if (p:=get_label1 p) then
  469. <<old := car p; new := cadr p;
  470. car p := new;
  471. if nodechain then
  472. nodechain := substipq(new,old,nodechain);
  473. >>;
  474. prin2t "------ updating done ------------";
  475. end;
  476. %------------------- nodes ------------------------------------
  477. symbolic procedure node(type);
  478. begin scalar name,name2,rname,type2,name3,rec,type3,name4,label;
  479. scalar altname,alias;
  480. printfunction!* := 'textout;
  481. if !*opennode then emit_node_separator();
  482. !*opennode:=t;
  483. % myskip '!{;
  484. name:=mystring_nodename();
  485. if altname:=assoc(name,name_trans) then
  486. name := explode2 cdr altname;
  487. % alias := if !*windows and assoc(name,aliases) then
  488. % cdr assoc(name,aliases);
  489. alias := if assoc(name,aliases) then
  490. cdr assoc(name,aliases);
  491. type3 := lowerstring (type2:=explode2 type);
  492. name2 :=type . '! . (rname:=raisestring name);
  493. name3 := append(type3,'! . name);
  494. name4 := append(name, '! . type3);
  495. label := make_label(name,type,name4);
  496. rec := {'node,
  497. nil,
  498. label,
  499. node_count:=add1 node_count,
  500. name4};
  501. car cdr act_rec:= cdr rec . seq act_rec;
  502. fonton();
  503. print_indent();
  504. mapc(name3,'prin2); reporttopic(" "); terpri();
  505. emit_node_label(lab rec);
  506. emit_node_title(lab rec,name,type);
  507. emit_node_browse(lab act_rec,count rec);
  508. emit_node_keys(name4);
  509. current_node!* := name4;
  510. emit_hidden_node_key(type3);
  511. emit_hidden_node_key(name rec);
  512. % header line;
  513. myterpri();
  514. if alias then <<print_bold alias; print_tab();>>;
  515. print_bold rname;
  516. if type2 neq '(C O N C E P T) then
  517. << print_tab(); print_tab(); print_tab(); print_tab();
  518. print_bold type2;
  519. >>;
  520. print_newline(); second_newline();
  521. mainloop ();
  522. end;
  523. put('switch,'context,'node);
  524. put('variable,'context,'node);
  525. put('operator,'context,'node);
  526. put('function,'context,'node);
  527. put('command,'context,'node);
  528. put('statement,'context,'node);
  529. put('declaration,'context,'node);
  530. put('concept,'context,'node);
  531. put('introduction,'context,'node);
  532. put('package,'context,'node);
  533. put('type,'context,'node);
  534. put('constant,'context,'node);
  535. symbolic procedure part(type);
  536. begin
  537. outc:='! ;
  538. if type='examples or type='syntax or type='related
  539. then par_heading(type) else
  540. if type='bigexample then par_heading('example);
  541. if type='bigexample or type='verbatim then return vpart(type) else
  542. if type='examples then return examples_part(type);
  543. if type='syntax or type='examples then newfont courier;
  544. mainloop();
  545. second_newline(); second_newline();
  546. newfont helvetica;
  547. end;
  548. symbolic procedure par_heading(type);
  549. <<verbprin2 !$eol!$;
  550. for each x in explode type do verbprin2 x;
  551. verbprin2 ":";
  552. verbprin2 !$eol!$; verbprin2 !$eol!$;
  553. >>;
  554. symbolic procedure vpart(type);
  555. % formatted / verbatim part.
  556. begin
  557. emit_start_verbatim();
  558. set_tab();
  559. newfont courier;
  560. vpart0();
  561. emit_end_verbatim();
  562. newfont helvetica;
  563. end;
  564. symbolic procedure vpart0();
  565. begin scalar c,c1,c2,c3;
  566. loop:
  567. c:=rdch();
  568. if c=!$eof!$ then rederr "#### EOF in verbatim part";
  569. if c='!\ then
  570. <<c2:=c3:=nil;
  571. if (c1:=rdch()) = '!\ then <<verbprin2 !$eol!$; goto loop>>;
  572. if c1 = '!e and (c2:=rdch()) = '!n and (c3:=rdch()) = '!d
  573. then goto done;
  574. verbprin2 '!\; verbprin2 c1;
  575. if c2 then verbprin2 c2;
  576. if c3 then verbprin2 c3;
  577. goto loop>>;
  578. verbprin2 c;
  579. goto loop;
  580. done:
  581. rdch();
  582. mytoken(t);
  583. if !*test then printf(" (vpart pop %w)",beginstack);
  584. beginstack := cdr beginstack;
  585. release_tab();
  586. end;
  587. symbolic procedure compareahead(seq,l); compareahead1(seq,cdr seq,l);
  588. symbolic procedure compareahead1(base,seq,l);
  589. if null l then t else
  590. if null seq then compareahead1(nconc(base,c),c,l) where c={rdch()}
  591. else
  592. if not(car seq = car l) then nil else
  593. compareahead1(base,cdr seq,cdr l);
  594. macro procedure look_ahead(m);
  595. {'compareahead,'inlist,mkquote explode2 cadr m};
  596. symbolic procedure examples_part(type);
  597. % formatted / verbatim part.
  598. begin scalar c,pg,state,tab_flag,pg,ll,l,endflag,eolflag,inlist;
  599. emit_start_verbatim();
  600. set_tab();
  601. newfont courier;
  602. state := 'lhs;
  603. read_next:
  604. eolflag := nil;
  605. ll := nil;
  606. read_loop:
  607. c:=rdch();
  608. if c=!$eof!$ then rederr "#### EOF in examples part";
  609. if c='!\ then
  610. <<inlist :={nil};
  611. if look_ahead "\" then
  612. <<eolflag := t;
  613. if state = 'rhs then goto rhs_line
  614. else goto tab_label>>;
  615. if look_ahead "end{Examples}"
  616. then <<endflag := t;
  617. if !*test then prin2t "\end{Examples}";
  618. if state = 'rhs then goto rhs_line else goto done;
  619. >>
  620. else
  621. if look_ahead "explanation"
  622. then << myskip '!{;
  623. non_verb_block() where endchar='!};
  624. goto read_next;
  625. >> else
  626. if look_ahead "begin{multilineinput}"
  627. then <<
  628. beginstack := 'multilineinput.beginstack;
  629. vpart0();
  630. goto read_next;
  631. >>;
  632. if state neq 'rhs and look_ahead "begin{multilineoutput}"
  633. then <<
  634. beginstack := 'multilineoutput.beginstack;
  635. vpart0();
  636. goto read_next;
  637. >>;
  638. ll := '!\ . ll;
  639. for each q in cdr inlist do if q then ll := q . ll;
  640. goto read_loop
  641. >>
  642. else if c='!& then
  643. <<if state = 'lhs then goto tab_label else
  644. <<mapc(reverse ll,'prin2); rederr "#### second & in example">>
  645. >>
  646. else ll := c . ll;
  647. goto read_loop;
  648. tab_label:
  649. while ll and cdr ll and car ll = '! and cadr ll = '! do
  650. ll := cdr ll; % remove trailing blanks.
  651. l := reversip ll;
  652. for each c in l do
  653. % if not c=!$eol!$ then
  654. verbprin2 c;
  655. if eolflag then
  656. <<verbprin2 !$eol!$; goto read_next>>;
  657. if length l > 35 then verbprin2 !$eol!$;
  658. %% verbprin2 '!&;
  659. %% verbprin2 "=>";
  660. state := 'rhs;
  661. goto read_next;
  662. rhs_line:
  663. verbprin2 !$eol!$;
  664. ll:=reversip ll;
  665. % remove leading blanks
  666. ll := delete(!$eol!$,ll);
  667. while ll and car ll = '! do ll:= cdr ll;
  668. goto no_expla;
  669. if matchleft(ll,'(!\ !e !x !p !l !a !n !a))
  670. then
  671. <<while ll and not (car ll = '!{) do ll := cdr ll;
  672. ll:= cdr ll;
  673. newfont helvetica;
  674. while ll and not(car ll = '!}) do
  675. <<textout car ll;ll:= cdr ll>>;
  676. ll := cdr ll;
  677. >>;
  678. no_expla:
  679. % provide for multiline
  680. if matchleft(ll,'(!\ !b !e !g !i !n
  681. !{ !m !u !l !t !i !l !i !n !e !o !u !t !p !u !t !}))
  682. then pg:=make_multi_out() ELSE pg:=minitex ll;
  683. if null pg then goto nix;
  684. tab_flag := t;
  685. %% if cadr pg > 35 then
  686. <<verbprin2 !$eol!$; verbprin2 " "; tab_flag := nil>>;
  687. pg := cddr pg;
  688. while pg do
  689. <<l := car pg; pg := cdr pg;
  690. for each c in l do verbprin2 c;
  691. if pg then
  692. <<verbprin2 !$eol!$;
  693. if tab_flag then verbprin2 '!&;
  694. verbprin2 " ";
  695. >>;
  696. >>;
  697. verbprin2 !$eol!$;
  698. nix:
  699. verbprin2 !$eol!$;
  700. state := 'lhs;
  701. if endflag then goto done;
  702. goto read_next;
  703. done:
  704. emit_end_verbatim();
  705. if !*test then printf(" (examples pop %w)",beginstack);
  706. beginstack := cdr beginstack;
  707. release_tab();
  708. newfont helvetica;
  709. end;
  710. symbolic procedure non_verb_block();
  711. begin
  712. emit_end_verbatim();
  713. release_tab();
  714. newfont helvetica;
  715. mainloop ();
  716. newfont courier;
  717. set_tab();
  718. emit_start_verbatim();
  719. end;
  720. symbolic procedure make_multi_out();
  721. begin scalar con,w,pg,m,q;
  722. con:=t;
  723. w := cdr match_point_rgt;
  724. % get rid of "{6cm}"
  725. while w and car w neq '!} do w:=cdr w;
  726. if w then w:=cdr w;
  727. if member(!$eol!$,w) then
  728. <<q:=cut_lines(w,nil); w:= car q; q:=cdr q>>;
  729. pg:=nil;
  730. m:=0;
  731. mult_loop:
  732. match_point_lft:=nil;
  733. if matcharb(w, '(!\ !e !n !d !{ !m !u !l !t !i !l !i !n !e ))
  734. then<< con:=nil;
  735. if match_point_lft then cdr match_point_lft:=nil else w:=nil;
  736. >>;
  737. if w then
  738. <<if length w>m then m:=length w;
  739. if memq('!^,w) or memq('!{,w) then
  740. pg := append(pg,cddr minitex w)
  741. else
  742. pg:=append(pg,{w})
  743. >>;
  744. if con then
  745. <<
  746. if q then <<w:=car q;q:=cdr q>> else w:=read_one_line();
  747. goto mult_loop
  748. >>;
  749. pg := length pg . m . pg;
  750. return pg;
  751. end;
  752. symbolic procedure cut_lines(l,q);
  753. if null l then {reversip q} else
  754. if car l = !$eol!$ then reversip q . cut_lines(cdr l,nil)
  755. else cut_lines(cdr l,car l . q);
  756. % match_point_lft: pair before match position
  757. % match_point_rgt: last pair of matched string
  758. symbolic procedure matchleft(a,pat);
  759. if null pat then t else
  760. if null a then nil else
  761. if car a neq car pat then
  762. <<match_point_lft:=a; nil>>
  763. else <<match_point_rgt:=a;
  764. matchleft(cdr a,cdr pat)>>;
  765. symbolic procedure matcharb(a,pat);
  766. if null a then nil else
  767. matchleft(a,pat) or matcharb(cdr a,pat);
  768. symbolic procedure read_one_line();
  769. begin scalar l,c;
  770. loop:
  771. c := rdch();
  772. if c=!$eol!$ then return reversip l;
  773. l := c.l;
  774. goto loop;
  775. end;
  776. put('comments,'context,'part);
  777. put('examples,'context,'part);
  778. put('bigexample,'context,'part);
  779. put('syntax,'context,'part);
  780. put('related,'context,'part);
  781. put('text,'context,'part);
  782. put('verbatim,'context,'part);
  783. put('quote,'context,'part); % QUOTE -> VERBATIM (temporal)
  784. symbolic procedure do!-itemize(type);
  785. begin
  786. outc:='! ;
  787. mainloop();
  788. second_newline();
  789. end;
  790. put('itemize,'context,'do!-itemize);
  791. symbolic procedure context_error(p,q);
  792. <<
  793. terpri();
  794. prin2 "######### error in context ";
  795. prin2 p;
  796. prin2 " ### : ";
  797. prin2t q;
  798. >>;
  799. %-------------------- special item routines ----------------------
  800. symbolic procedure verb(u);
  801. begin scalar endchar,!*verbose;
  802. endchar := char!*; !*verbose:=t;
  803. mainloop();
  804. end;
  805. put('verb,'act,'verb);
  806. symbolic procedure ldots(u); textout "...";
  807. put('ldots,'act,'ldots);
  808. flag('(ldots),'simple);
  809. symbolic procedure cdots(u); textout "...";
  810. put('cdots,'act,'cdots);
  811. flag('(cdots),'simple);
  812. symbolic procedure cdot(u); textout ". ";
  813. put('cdot,'act,'cdot);
  814. flag('(cdot),'simple);
  815. symbolic procedure write_pi(u); textout "pi";
  816. put('pi,'act,'write_pi);
  817. flag('(write_pi),'simple);
  818. symbolic procedure emphase(u); printem mystring3();
  819. put('key,'act,'emphase);
  820. symbolic procedure meta(u);
  821. <<textout "<"; mapc(mystring2(),'textout); textout ">">>;
  822. put('meta,'act,'meta);
  823. symbolic procedure italic(u);
  824. <<switchitalic(t);
  825. unrdch();
  826. undo := '(switchitalic nil).undo>>;
  827. symbolic procedure switchitalic u; nil;
  828. put('bf,'act,'italic);
  829. put('em,'act,'italic);
  830. put('it,'act,'italic);
  831. symbolic procedure nameref(u); printnameref mystring3();
  832. put('nameref,'act,'nameref);
  833. symbolic procedure ref(u); printref mystring2();
  834. put('ref,'act,'ref);
  835. symbolic procedure see(u);
  836. begin
  837. u:=mystring2();
  838. % textout2 u; textout '! ;
  839. emit_node_key u;
  840. end;
  841. put ('see,'act,'see);
  842. symbolic procedure myname(u);
  843. printem mystring3();
  844. put ('name,'act,'myname);
  845. symbolic procedure myindex(u);
  846. <<textout '! ;emit_node_key mystring2()>>;
  847. put('index,'act,'myindex);
  848. symbolic procedure nameindex(u);
  849. begin scalar s;
  850. s:= mystring2();
  851. textout '! ;
  852. emit_hidden_node_key s;
  853. printem s;
  854. end;
  855. put('nameindex,'act,'nameindex);
  856. symbolic procedure reduce(u); textout "REDUCE";
  857. put('reduce,'act,'reduce);
  858. flag('(reduce),'simple);
  859. symbolic procedure rept(u); textout "+";
  860. put('repeated,'act,'rept);
  861. flag('(rept),'simple);
  862. symbolic procedure optional(u); textout "*";
  863. put('optional,'act,'optional);
  864. flag('(optional),'simple);
  865. symbolic procedure myexp(u); <<textout"(";textout "exp">>;
  866. put('exp,'act,'myexp);
  867. symbolic procedure formula(u); textoutl mystring2();
  868. put('variable,'act,'formula);
  869. put('arg,'act,'formula);
  870. symbolic procedure rfrac(u);
  871. <<textoutl mystring2();
  872. rdch();
  873. textout "/";
  874. textoutl mystring2();
  875. >>;
  876. put('rfrac,'act,'rfrac);
  877. symbolic procedure item(u);
  878. begin scalar endchar;
  879. endchar := '!];
  880. print_newline();
  881. if !*windows then print_tab();
  882. mainloop();
  883. end;
  884. put('item,'act,'item);
  885. %-------------------- support for iftex etc. ---------------------
  886. symbolic procedure texonly1(u);
  887. begin scalar endchar,c;
  888. integer count;
  889. count:=1;
  890. loop:
  891. c:= rdch();
  892. if c='!\ then c:= rdch() else
  893. if c='!{ then count:=count+1 else
  894. if c='!} then count:=count-1;
  895. if count>0 then goto loop;
  896. myskip('!{);
  897. endchar:='!};
  898. mainloop();
  899. end;
  900. put('iftex,'act,'texonly1);
  901. symbolic procedure texonly2(u);
  902. begin scalar endchar,c,tok;
  903. integer count;
  904. count:=1;
  905. loop:
  906. c:= rdch();
  907. if c='!\ then
  908. <<tok:=mytoken(t);
  909. if tok='begin then count:=count+1 else
  910. if tok='end then count:=count-1;
  911. >>;
  912. if count>0 then goto loop;
  913. tok:=mytoken(t);
  914. if tok neq 'tex then
  915. <<printf("****** \begin{tex} ends with \end{%w}%n",tok);
  916. exitlisp();
  917. >>;
  918. if !*test then printf(" (texonly pop %w)",beginstack);
  919. beginstack := cdr beginstack;
  920. end;
  921. put('tex,'context,'texonly2);
  922. symbolic procedure infoonly(u);
  923. begin scalar endchar;
  924. mainloop();
  925. end;
  926. put('info,'context,'infoonly);
  927. symbolic procedure reporttopic u;
  928. if !*windows then
  929. <<prin2 u; prin2(topiccount!* := topiccount!*+1); prin2 " ">>;
  930. %----------------- untilities ------------------------------
  931. symbolic procedure substipq(new,old,l);
  932. % destructive substip based on eq test.
  933. if not pairp l then l else
  934. <<
  935. if car l eq old then car l := new;
  936. if cdr l eq old then cdr l := new;
  937. substipq(new,old,car l);
  938. substipq(new,old,cdr l);
  939. l>>;
  940. end;
  941.