help.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. /*=======================================================================
  2. /*
  3. /* REDUCE help interface
  4. /*
  5. /* Author: H. Melenk, ZIB-Berlin, Nov. 1992
  6. /*
  7. /*
  8. /*=======================================================================
  9. /*
  10. /* interface: Help file must have been compiled by
  11. /* GNU Texinfo system
  12. /*
  13. /* compile: UNIX: cc help.c -DUNIX -o help
  14. /* DOS: cl -DMSC -DANSI help.c
  15. /* (for Microsoft C, ansi.sys screen control)
  16. /* or cl -DMSC help.c
  17. /* (for Microsoft C, bare screen usage)
  18. /*
  19. /*
  20. /* call(Unix): help -f helpfile
  21. /* or help -f helpfile topic
  22. /* where <topic> is an initial help topic.
  23. /*
  24. /*=======================================================================*/
  25. #include <stdio.h>
  26. #include <setjmp.h>
  27. #if defined MSC
  28. #include <string.h>
  29. #include <dos.h>
  30. #endif
  31. #ifndef SEEK_SET
  32. #define SEEK_SET 0
  33. #endif
  34. FILE * helpfile;
  35. #define PAGE 0x1f
  36. #define EOL 0x0a
  37. #define MAX_NODE 1000
  38. #define MAX_TABLE 1000
  39. #define NAME_LENGTH 50
  40. char tag[30];
  41. char Node[NAME_LENGTH],Next[NAME_LENGTH],Prev[NAME_LENGTH],Up[NAME_LENGTH];
  42. int node_count;
  43. char * node_name[MAX_NODE];
  44. long node_adr[MAX_NODE];
  45. long table[MAX_TABLE];
  46. int table_count;
  47. long top_node,act_node;
  48. int bp; char buffer[100]; char out_buffer[100];
  49. long read_number();
  50. long find_node();
  51. #if defined MSC
  52. int strncasecmp(char * u, char * v,int n);
  53. int display(long);
  54. int video=0;
  55. int fg_color,bg_color;
  56. #endif
  57. jmp_buf more_base;
  58. main(argc,argv)
  59. char * argv[]; int argc;
  60. {
  61. int i;
  62. char cmd;
  63. char*search_node;
  64. long ll;
  65. #if defined UNIX
  66. printf(" UNIX ");
  67. #endif
  68. #if defined MSC
  69. #if defined ANSI
  70. {
  71. union REGS regs;
  72. regs.h.ah = 0x1a; /* read display code */
  73. regs.h.al = 0;
  74. int86(0x10, &regs, &regs);
  75. video=(regs.h.bl==2) || (regs.h.bl==4) || (regs.h.bl==6)
  76. || (regs.h.bl==8) || (regs.h.bl>=0x0c);
  77. regs.h.ah = 0x08; /* read actual color */
  78. regs.h.bh = 0;
  79. int86(0x10, &regs, &regs);
  80. fg_color=regs.h.ah & 0xf;
  81. bg_color=(regs.h.ah>>4) & 0x7;
  82. regs.h.ah = 5; /* set video page */
  83. regs.h.al = 1; /* page number */
  84. int86(0x10, &regs, &regs);
  85. }
  86. #endif
  87. printf(" DOS ");
  88. #endif
  89. printf(" REDUCE help system \n");
  90. if(argc<2 || strcmp(argv[1],"-f")) wrong_call(argc,argv);
  91. #if defined MSC
  92. helpfile = fopen(argv[2],"r+b");
  93. #else
  94. helpfile = fopen(argv[2],"r");
  95. #endif
  96. if(!helpfile)
  97. {printf("cannot open help file >%s<\n",argv[2]); my_exit(1);};
  98. /* find table of contents */
  99. find_TOC();
  100. top_node = find_node("Top");
  101. if(!top_node)
  102. { printf("Top node not found\n"); my_exit(1);};
  103. act_node=top_node;
  104. if(argc>3)
  105. {
  106. ll=find_matching_nodes(argv[3],strlen(argv[3]));
  107. if(ll) goto next_command;
  108. else printf("**** no item matching >%s<\n",argv[3]);
  109. };
  110. loop:
  111. display(act_node);
  112. next_command:
  113. cmd = command();
  114. if(cmd == 'q' || cmd == 'Q' || cmd == 'x' || cmd == 'X') my_exit(0);
  115. else
  116. if(cmd == '+' || cmd == 'n' || cmd == 'N')
  117. { if(Next[0]) {search_node=Next; goto search;}; goto loop;}
  118. else
  119. if(cmd == '-' || cmd == 'p' || cmd == 'P')
  120. { if(Prev[0]) {search_node=Prev; goto search;}; goto loop;}
  121. else
  122. if(cmd == 't' || cmd == 'T')
  123. { act_node=top_node; goto loop;}
  124. else
  125. if(cmd == 'U' || cmd == 'u' || cmd == 'U')
  126. { if(liter(Up[0])) {search_node=Up; goto search;}; goto loop;}
  127. goto loop;
  128. search:
  129. ll = find_node(search_node);
  130. if(ll) {act_node=ll; goto loop;};
  131. /* printf("\n ****** node >%s< not found\n",search_node); /* */
  132. goto loop;
  133. }
  134. my_exit(n)
  135. int n;
  136. {
  137. #if defined ANSI
  138. if(n) getch();
  139. {
  140. union REGS regs;
  141. more_putc(0x1b); more_putc('[');
  142. more_putc('0'); more_putc(';');
  143. more_putc('4'); more_putc('0'+bg_color); more_putc(';');
  144. more_putc('3'); more_putc('0'+fg_color);
  145. more_putc('m');
  146. regs.h.ah = 5; /* set video page */
  147. regs.h.al = 0; /* page number */
  148. int86(0x10, &regs, &regs);
  149. }
  150. #endif
  151. exit(n);
  152. }
  153. command()
  154. {
  155. char c; int n;
  156. long ll;
  157. loop:
  158. printf("\n Enter: ");
  159. printfhighlight("+ - u t s q ?");
  160. if(table_count>0) printf(" or a reference number\n");
  161. nextchar:
  162. n=0;
  163. #if defined MSC
  164. c=getch(); putchar(c); /* input without return */
  165. #else
  166. c=getchar();
  167. #endif
  168. if(digit(c)) goto number;
  169. if(c == ' ' || c == EOL) goto nextchar;
  170. if (c == '+' || c == '-' || c == 'u' || c == 'U'
  171. || c == 't' || c == 'T'
  172. || c == 'q' || c == 'Q'
  173. || c == 'x' || c == 'X'
  174. ) return(c);
  175. if (c == '?' || c== 'h' || c == 'H') goto help;
  176. if (c == 's' || c== 'S') goto find;
  177. goto loop;
  178. number:
  179. n= 10*n+(c-'0');
  180. c=getchar();
  181. if(digit(c)) goto number;
  182. if(0<n && n<=table_count)
  183. {act_node = table[n]; return('d');}
  184. /* search item entered from terminal */
  185. find:
  186. bp =0;
  187. while((c=getchar()) != EOL)
  188. if(c!=' ' || bp>0) buffer[bp++]=c;
  189. buffer[bp] = 0;
  190. ll=find_matching_nodes(buffer,bp);
  191. if(!ll) printf("**** no item matching >%s<\n",buffer);
  192. goto loop;
  193. help:
  194. printf("\n Enter command terminated by Return Key:\n");
  195. printf(" + browse forwards to next topic on same level.\n");
  196. printf(" - browse backwards on same level.\n");
  197. printf(" u return to next upper level (directory).\n");
  198. printf(" t return to top directory.\n");
  199. printf(" nnn (nnn a number): \n");
  200. printf(" select the nnn-th topic from menu or context,\n");
  201. printf(" don't enclose number in sqare brackets.\n");
  202. printf(" s cccc (cccc sequence of characters): \n");
  203. printf(" search topics which match the character sequence:\n");
  204. printf(" not case sensitive, no wildcard;\n");
  205. printf(" result is a selection menu.\n");
  206. printf(" q quit help.\n");
  207. goto loop;
  208. }
  209. display(adr)
  210. long adr;
  211. {
  212. char c;
  213. int i;
  214. int state;
  215. long ll;
  216. char * bv;
  217. /* printf("display node: %ld\n",adr); /* */
  218. if(seek_char(adr))
  219. {printf("cannot find file position %lx\n",adr); my_exit(1);};
  220. Next[0]=0; Prev[0]=0; Up[0]=0;
  221. loop:
  222. read_tag();
  223. if(!strcmp(tag,"File:"))
  224. {read_string(tag); goto loop;}
  225. else
  226. if(!strcmp(tag,"Node:"))
  227. {read_string(Node); goto loop;}
  228. else
  229. if(!strcmp(tag,"Next:"))
  230. {read_string(Next); goto loop;}
  231. else
  232. if(!strcmp(tag,"Prev:"))
  233. {read_string(Prev); goto loop;}
  234. else
  235. if(!strcmp(tag,"Up:"))
  236. read_string(Up);
  237. else
  238. {printf("\n *** unknown node tag:>%s<",tag); /*exit(1);*/};
  239. if(setjmp(more_base)) goto done;
  240. more_open();
  241. for(i=0;i<71;i++) more_putc('=');
  242. more_putc(EOL);
  243. state = 0; bp=0; table_count=0;
  244. while((c=read_char()) != PAGE)
  245. {
  246. more_putc(c);
  247. /* look for menu and note entries */
  248. if(c == '*' && state==0) state=2;
  249. else if(c == ':' && state==2) state=4;
  250. else if(c == ':' && state==4)
  251. { /* menu entry found */
  252. buffer[bp]=0;
  253. /* printf("menu entry: >%s<\n",buffer); */
  254. bv = buffer;
  255. if(!strncmp(bv,"note ",5)) bv=bv+5;
  256. ll = find_node(bv);
  257. if(ll && table_count<MAX_TABLE)
  258. { table_count++;
  259. table[table_count]=ll;
  260. sprintf(out_buffer,"[%d]",table_count);
  261. highlight_on();
  262. for(i=0;out_buffer[i];i++) more_putc(out_buffer[i]);
  263. highlight_off();
  264. state=0; bp=0;
  265. };
  266. }
  267. else if(state==2 && bp<NAME_LENGTH
  268. && (liter(c) || digit(c) || c==' '))
  269. {if(c!=' ' || bp>0) buffer[bp++]=c;}
  270. else {
  271. if(c=='*') state=2; else state=0;
  272. bp=0;
  273. };
  274. };
  275. done:
  276. more_close();
  277. }
  278. FILE * pfeife = NULL;
  279. int use_pipe = 0, more_line_count;
  280. more_open()
  281. {
  282. FILE * loc;
  283. more_line_count=0;
  284. pfeife = stdout;
  285. use_pipe = 0;
  286. #if defined UNIX
  287. loc = popen("more","w");
  288. if(loc) { pfeife = loc; use_pipe = 1;}
  289. #endif
  290. #if defined ANSI
  291. more_putc(0x1b); more_putc('[');
  292. more_putc('3'); more_putc('7');
  293. more_putc(';'); more_putc('4'); more_putc('4'); more_putc('m');
  294. more_putc(0x1b); more_putc('[');
  295. more_putc('2'); more_putc('J');
  296. #endif
  297. }
  298. more_putc(c)
  299. char c;
  300. {
  301. int i;
  302. char d=0;
  303. if(use_pipe) putc(c,pfeife);
  304. else
  305. {
  306. putchar(c);
  307. if(c==EOL)
  308. { if(more_line_count++ >= 22)
  309. {more_line_count=0;
  310. #if defined MSC
  311. highlight_on();
  312. printf("--More--");
  313. highlight_off();
  314. d = getch();
  315. for (i=0;i<30;i++) putchar(8);
  316. #else
  317. printf("--More--\n");
  318. d = getchar();
  319. #endif
  320. if(d == 'q' || d == 'Q') longjmp(more_base,1);
  321. }} }
  322. }
  323. more_close()
  324. {
  325. #if defined UNIX
  326. if(use_pipe) pclose(pfeife);
  327. #endif
  328. use_pipe=0;
  329. }
  330. long find_node(s)
  331. char * s;
  332. { int i;
  333. i=0;
  334. while(i<node_count && (s[0] !=node_name[i][0] ||strcmp(s,node_name[i])))
  335. {
  336. i++;
  337. /* printf("%d(%d) suchen: >%s< >%s< \n",i,node_count,s,node_name[i]); */
  338. }
  339. if(i<node_count) return(node_adr[i]);
  340. printf("node not found: >%s< \n",s);
  341. return(0);
  342. }
  343. find_matching_nodes (s,lth)
  344. char * s; int lth;
  345. { int i=0,j=0,k=1; char * t;
  346. /* printf("find_node_case >%s< %d\n",s,lth); */
  347. more_open();
  348. while(i<node_count && (t=node_name[i]))
  349. { k=1;
  350. while (t[0] && (k=strncasecmp(s,t,lth))) t++;
  351. /* { printf(">%s< >%s< %x\n",s,t,k);t++;};*/
  352. if(!k && j<MAX_TABLE)
  353. {
  354. j++;
  355. table[j]=node_adr[i];
  356. t=node_name[i];
  357. while(*t) more_putc(*t++);
  358. sprintf(out_buffer,"[%d]",j);
  359. highlight_on();
  360. t=out_buffer; while(*t) more_putc(*t++);
  361. highlight_off();
  362. more_putc(EOL);
  363. }
  364. i++;
  365. }
  366. more_close();
  367. if(j) table_count=j;
  368. return (j);
  369. }
  370. find_TOC()
  371. {
  372. node_count=0;
  373. loop1:
  374. skip_char(PAGE);
  375. skip_char(EOL);
  376. read_tag();
  377. /* printf("tag: %s\n",tag); /* */
  378. if(strcmp(tag,"TagTable:")) goto loop1;
  379. skip_char(EOL);
  380. loop2:
  381. read_tag();
  382. /* printf("tag(Node?): %s\n",tag); /* */
  383. if(strcmp(tag,"Node:")) return(0);
  384. read_string(buffer);
  385. node_name[node_count] = (char*)malloc(strlen(buffer)+1);
  386. if(!node_name[node_count])
  387. {printf("ran out of memory\n"); my_exit(1);};
  388. strcpy(node_name[node_count],buffer);
  389. node_adr[node_count]=read_number();
  390. /* printf("node %s %d\n",node_name[node_count],
  391. node_adr[node_count]); /* */
  392. node_count++;
  393. if (node_count > MAX_NODE)
  394. {printf("too many nodes found\n"); my_exit(1);};
  395. goto loop2;
  396. }
  397. read_tag()
  398. {
  399. char c; int i;
  400. i=0;
  401. while((c=read_char()) && i<30
  402. && (digit(c) || liter(c) || c==' ' || (i==0 && c==EOL)))
  403. if(c!=EOL && c!=' ')tag[i++]=c;
  404. if(c==':') tag[i++]=c;
  405. tag[i]=0;
  406. return(0);
  407. }
  408. liter(c)
  409. char c;
  410. { return( (c>='a' && c<='z') || (c>='A' && c<='Z') || c == '_');}
  411. digit(c)
  412. char c;
  413. { return(c>='0' && c<='9');}
  414. read_string(s)
  415. char * s;
  416. {
  417. char c; int i;
  418. i=0;
  419. while((c=read_char())
  420. && (digit(c) || liter(c) || c==':' || c==' ' || c=='.'
  421. || c=='(' || c==')' || c=='!' || c=='_' || c=='-'|| c=='?'
  422. || c=='*'))
  423. { s[i++]=c; if(i==1 && c==' ')i--;}
  424. s[i]=0;
  425. return(0);
  426. }
  427. long read_number()
  428. {
  429. char c; long n;
  430. n=0;
  431. while((c=read_char()) && digit(c)) n = n*10 + (c-'0');
  432. return(n);
  433. }
  434. /* buffered file io */
  435. int b_ptr=0,b_size=-1;
  436. #define BUFFLEN 2048
  437. char buffo[BUFFLEN];
  438. read_char()
  439. {
  440. char c;
  441. if(b_ptr<b_size) return(buffo[b_ptr++]);
  442. if(feof(helpfile))
  443. {printf("unexpected EOF found in help file\n"); my_exit(1);};
  444. b_size = fread(buffo,1,BUFFLEN,helpfile);
  445. b_ptr=1;
  446. return(buffo[0]);
  447. }
  448. skip_char(u)
  449. char u;
  450. {
  451. char c;
  452. loop:
  453. if(read_char()==u) return(0);
  454. goto loop;
  455. }
  456. seek_char(adr)
  457. long adr;
  458. {
  459. b_size=-2;
  460. return(fseek(helpfile,adr,SEEK_SET));
  461. }
  462. /* error handlers */
  463. wrong_call(argc,argv)
  464. char * argv[]; int argc;
  465. {
  466. int i;
  467. for(i=0;i<argc;i++) printf("%s\n",argv[i]);
  468. printf("usage: help -f <file> [ <topic> ]\n ");
  469. my_exit(1);
  470. }
  471. #if defined MSC
  472. /* Microsoft C does not support strncasecmp */
  473. strncasecmp(char * u, char * v,int n)
  474. {
  475. char cu,cv;
  476. int r=1;
  477. while(r && (n-- > 0))
  478. { cu = *u++; cv = *v++;
  479. if('a' <= cu) cu = cu-32;
  480. if('a' <= cv) cv = cv-32;
  481. r = (cu == cv);
  482. }
  483. return(!r);
  484. }
  485. #endif
  486. printfhighlight(s)
  487. char * s;
  488. {
  489. while(*s)
  490. {if(*s !=' ' && *s != EOL)
  491. {
  492. highlight_on();
  493. putchar(' ');
  494. putchar(*s);
  495. putchar(' ');
  496. highlight_off();
  497. }
  498. else putchar(*s);
  499. s++;
  500. } }
  501. highlight_on()
  502. {
  503. #if defined ANSI
  504. if(video)
  505. {
  506. putchar(0x1b); putchar('[');
  507. putchar('4'); putchar('3'); putchar('m');
  508. }
  509. else
  510. {
  511. putchar(0x1b); putchar('[');
  512. putchar('5'); putchar('m');
  513. }
  514. #endif
  515. }
  516. highlight_off()
  517. {
  518. #if defined ANSI
  519. more_putc(0x1b); more_putc('[');
  520. more_putc('0'); more_putc(';');
  521. more_putc('4'); more_putc('4');
  522. more_putc('m');
  523. #endif
  524. }