fehelp.cc
Go to the documentation of this file.
1 /****************************************
2 * Computer Algebra System SINGULAR *
3 ****************************************/
4 /*
5 * ABSTRACT: help system
6 */
7 
8 #include <string.h>
9 #include <unistd.h>
10 #include <stdio.h>
11 #include <stddef.h>
12 #include <stdlib.h>
13 #include <time.h>
14 
15 
16 
17 
18 #include <kernel/mod2.h>
19 
20 #include <omalloc/omalloc.h>
21 #include <misc/mylimits.h>
22 
23 #include <resources/feResource.h>
24 #include <reporter/reporter.h>
25 
26 #include <resources/omFindExec.h>
27 
28 #include <reporter/si_signals.h>
29 
30 #include "ipid.h"
31 #include "ipshell.h"
32 #include "libparse.h"
33 #include "feOpt.h"
34 
35 #include "tok.h"
36 #include "fehelp.h"
37 
38 /*****************************************************************
39  *
40  * Declarations: Data structures
41  *
42  *****************************************************************/
43 #define MAX_HE_ENTRY_LENGTH 160
44 typedef struct
45 {
47  char node[MAX_HE_ENTRY_LENGTH];
49  long chksum;
50 } heEntry_s;
51 typedef heEntry_s * heEntry;
52 
53 typedef void (*heBrowserHelpProc)(heEntry hentry, int br);
54 typedef BOOLEAN (*heBrowserInitProc)(int warn, int br);
55 
56 typedef struct
57 {
58  const char* browser;
61  const char* required;
62  const char* action;
63 } heBrowser_s;
65 
66 /*****************************************************************
67  *
68  * Declarations: Local functions
69  *
70  *****************************************************************/
71 static char* strclean(char* str);
72 static BOOLEAN heKey2Entry(char* filename, char* key, heEntry hentry);
73 static int heReKey2Entry (char* filename, char* key, heEntry hentry);
74 static BOOLEAN strmatch(char* s, char* re);
75 static BOOLEAN heOnlineHelp(char* s);
76 static void heBrowserHelp(heEntry hentry);
77 static long heKeyChksum(char* key);
78 
79 // browser functions
80 static BOOLEAN heGenInit(int,int); static void heGenHelp(heEntry hentry,int);
81  static void heBuiltinHelp(heEntry hentry,int);
82 static BOOLEAN heDummyInit(int,int); static void heDummyHelp(heEntry hentry,int);
83 static BOOLEAN heEmacsInit(int,int); static void heEmacsHelp(heEntry hentry,int);
84 
87 
88 
89 /*****************************************************************
90  *
91  * Definition: available help browsers
92  *
93  *****************************************************************/
94 // order is important -- first possible help is chosen
95 // moved to LIB/help.cnf
97 
98 /*****************************************************************
99  *
100  * Implementation: public function
101  *
102  *****************************************************************/
103 void feHelp(char *str)
104 {
105  str = strclean(str);
106  if (str == NULL) {heBrowserHelp(NULL); return;}
107 
108  if (strlen(str) > MAX_HE_ENTRY_LENGTH - 2) // need room for extra **
109  str[MAX_HE_ENTRY_LENGTH - 3] = '\0';
110 
111  BOOLEAN key_is_regexp = (strchr(str, '*') != NULL);
112 
113  // try proc help and library help
114  if (! key_is_regexp && heOnlineHelp(str)) return;
115 
116  heEntry_s hentry;
117  memset(&hentry,0,sizeof(hentry));
118  char* idxfile = feResource('x' /*"IdxFile"*/);
119 
120  // Try exact match of help string with key in index
121  if (!key_is_regexp && (idxfile != NULL) && heKey2Entry(idxfile, str, &hentry))
122  {
123  heBrowserHelp(&hentry);
124  return;
125  }
126 
127  // Try to match approximately with key in index file
128  if (idxfile != NULL)
129  {
130  if (heCurrentHelpBrowser == NULL) feHelpBrowser(NULL, 0);
131  assume(heCurrentHelpBrowser != NULL);
132 
133  StringSetS("");
134  int found = heReKey2Entry(idxfile, str, &hentry);
135 
136  // Try to match with str*
137  if (found == 0)
138  {
139  char mkey[MAX_HE_ENTRY_LENGTH];
140  strcpy(mkey, str);
141  strcat(mkey, "*");
142  found = heReKey2Entry(idxfile, mkey, &hentry);
143  // Try to match with *str*
144  if (found == 0)
145  {
146  mkey[0] = '*';
147  strcpy(mkey + 1, str);
148  strcat(mkey, "*");
149  found = heReKey2Entry(idxfile, mkey, &hentry);
150  }
151 
152  // Print warning and return if nothing found
153  if (found == 0)
154  {
155  Warn("No help for topic '%s' (not even for '*%s*')", str, str);
156  WarnS("Try '?;' for general help");
157  WarnS("or '?Index;' for all available help topics.");
158  return;
159  }
160  }
161 
162  // do help if unique match was found
163  if (found == 1)
164  {
165  heBrowserHelp(&hentry);
166  return;
167  }
168  // Print warning about multiple matches and return
169  if (key_is_regexp)
170  Warn("No unique help for '%s'", str);
171  else
172  Warn("No help for topic '%s'", str);
173  Warn("Try one of");
174  char *matches=StringEndS();
175  PrintS(matches);
176  omFree(matches);
177  PrintLn();
178  return;
179  }
180 
181  // no idx file, let Browsers deal with it, if they can
182  strcpy(hentry.key, str);
183  *hentry.node = '\0';
184  *hentry.url = '\0';
185  hentry.chksum = 0;
186  heBrowserHelp(&hentry);
187 }
188 static void feBrowserFile()
189 {
190  FILE *f=feFopen("help.cnf","r",NULL,TRUE);
191  int br=0;
192  if (f!=NULL)
193  {
194  char buf[512];
195  while (fgets( buf, sizeof(buf), f))
196  {
197  if ((buf[0]!='#') && (buf[0]>' ')) br++;
198  }
199  fseek(f,0,SEEK_SET);
200  // for the 4(!) default browsers
201  heHelpBrowsers=(heBrowser_s*)omAlloc0((br+4)*sizeof(heBrowser_s));
202  br = 0;
203  while (fgets( buf, sizeof(buf), f))
204  {
205  if ((buf[0]!='#') && (buf[0]>' '))
206  {
207  char *name=strtok(buf,"!");
208  char *req=strtok(NULL,"!");
209  char *cmd=strtok(NULL,"!");
210  if ((name!=NULL) && (req!=NULL) && (cmd!=NULL))
211  {
212  while ((cmd[0]!='\0') && (cmd[strlen(cmd)-1]<=' '))
213  cmd[strlen(cmd)-1]='\0';
214  //Print("name %d >>%s<<\n\treq:>>%s<<\n\tcmd:>>%s<<\n",br,name,req,cmd);
215  heHelpBrowsers[br].browser=(char *)omStrDup(name);
216  heHelpBrowsers[br].init_proc=heGenInit;
217  heHelpBrowsers[br].help_proc=heGenHelp;
218  heHelpBrowsers[br].required=omStrDup(req);
219  heHelpBrowsers[br].action=omStrDup(cmd);
220  br++;
221  }
222  else
223  {
224  Print("syntax error in help.cnf, at line starting with %s\n",buf);
225  }
226  }
227  }
228  fclose(f);
229  }
230  else
231  {
232  // for the 4(!) default browsers
233  heHelpBrowsers=(heBrowser_s*)omAlloc0(4*sizeof(heBrowser_s));
234  }
235  heHelpBrowsers[br].browser="builtin";
236  heHelpBrowsers[br].init_proc=heGenInit;
237  heHelpBrowsers[br].help_proc=heBuiltinHelp;
238  heHelpBrowsers[br].required="i";
239  //heHelpBrowsers[br].action=NULL;
240  br++;
241  heHelpBrowsers[br].browser="dummy";
242  heHelpBrowsers[br].init_proc=heDummyInit;
243  heHelpBrowsers[br].help_proc=heDummyHelp;
244  //heHelpBrowsers[br].required=NULL;
245  //heHelpBrowsers[br].action=NULL;
246  br++;
247  heHelpBrowsers[br].browser="emacs";
248  heHelpBrowsers[br].init_proc=heEmacsInit;
249  heHelpBrowsers[br].help_proc=heEmacsHelp;
250  //heHelpBrowsers[br].required=NULL;
251  //heHelpBrowsers[br].action=NULL;
252  //br++;
253  //heHelpBrowsers[br].browser=NULL;
254  //heHelpBrowsers[br].init_proc=NULL;
255  //heHelpBrowsers[br].help_proc=NULL;
256  //heHelpBrowsers[br].required=NULL;
257  //heHelpBrowsers[br].action=NULL;
258 }
259 
260 const char* feHelpBrowser(char* which, int warn)
261 {
262  int i = 0;
263 
264  // if no argument, choose first available help browser
265  if (heHelpBrowsers==NULL) feBrowserFile();
266  if (which == NULL || *which == '\0')
267  {
268  // return, if already set
269  if (heCurrentHelpBrowser != NULL)
270  return heCurrentHelpBrowser->browser;
271 
272  // First, try emacs, if emacs-option is set
273  if (feOptValue(FE_OPT_EMACS) != NULL)
274  {
275  while (heHelpBrowsers[i].browser != NULL)
276  {
277  if (strcmp(heHelpBrowsers[i].browser, "emacs") == 0 &&
278  (heHelpBrowsers[i].init_proc(0,i)))
279  {
280  heCurrentHelpBrowser = &(heHelpBrowsers[i]);
282  goto Finish;
283  }
284  i++;
285  }
286  i=0;
287  }
288  while (heHelpBrowsers[i].browser != NULL)
289  {
290  if (heHelpBrowsers[i].init_proc(0,i))
291  {
292  heCurrentHelpBrowser = &(heHelpBrowsers[i]);
294  goto Finish;
295  }
296  i++;
297  }
298  // should never get here
299  dReportBug("should never get here");
300  }
301 
302  // with argument, find matching help browser
303  while (heHelpBrowsers[i].browser != NULL &&
304  strcmp(heHelpBrowsers[i].browser, which) != 0)
305  {i++;}
306 
307  if (heHelpBrowsers[i].browser == NULL)
308  {
309  if (warn) Warn("No help browser '%s' available.", which);
310  }
311  else
312  {
313  // see whether we can init it
314  if (heHelpBrowsers[i].init_proc(warn,i))
315  {
316  heCurrentHelpBrowser = &(heHelpBrowsers[i]);
318  goto Finish;
319  }
320  }
321 
322  // something went wrong
323  if (heCurrentHelpBrowser == NULL)
324  {
325  feHelpBrowser();
326  assume(heCurrentHelpBrowser != NULL);
327  if (warn)
328  Warn("Setting help browser to '%s'.", heCurrentHelpBrowser->browser);
329  return heCurrentHelpBrowser->browser;
330  }
331  else
332  {
333  // or, leave as is
334  if (warn)
335  Warn("Help browser stays at '%s'.", heCurrentHelpBrowser->browser);
336  return heCurrentHelpBrowser->browser;
337  }
338 
339  Finish:
340  // update value of Browser Option
341  if (feOptSpec[FE_OPT_BROWSER].value == NULL ||
342  strcmp((char*) feOptSpec[FE_OPT_BROWSER].value,
343  heCurrentHelpBrowser->browser) != 0)
344  {
345  omfree(feOptSpec[FE_OPT_BROWSER].value);
346  feOptSpec[FE_OPT_BROWSER].value
347  = (void*) omStrDup(heCurrentHelpBrowser->browser);
348  }
349  return heCurrentHelpBrowser->browser;
350 }
351 
353 {
354  int i;
355  StringAppendS("Available HelpBrowsers: ");
356 
357  i = 0;
358  if (heHelpBrowsers==NULL) feBrowserFile();
359  while (heHelpBrowsers[i].browser != NULL)
360  {
361  if (heHelpBrowsers[i].init_proc(warn,i))
362  StringAppend("%s, ", heHelpBrowsers[i].browser);
363  i++;
364  }
365  StringAppend("\nCurrent HelpBrowser: %s ", feHelpBrowser());
366 }
367 
368 
369 /*****************************************************************
370  *
371  * Implementation: local function
372  *
373  *****************************************************************/
374 // Remove whitspaces from beginning and end, return NULL if only whitespaces
375 static char* strclean(char* str)
376 {
377  if (str == NULL) return NULL;
378  char *s=str;
379  while ((*s <= ' ') && (*s != '\0')) s++;
380  if (*s == '\0') return NULL;
381  char *ss=s;
382  while (*ss!='\0') ss++;
383  ss--;
384  while ((*ss <= ' ') && (*ss != '\0'))
385  {
386  *ss='\0';
387  ss--;
388  }
389  if (*ss == '\0') return NULL;
390  return s;
391 }
392 
393 // Finds help entry for key:
394 // returns filled-in hentry and TRUE, on success
395 // FALSE, on failure
396 // Assumes that lines of idx file have the following form
397 // key\tnode\turl\tchksum\n (chksum ma be empty, then it is set to -1)
398 // and that lines are sorted alpahbetically w.r.t. index entries
399 static BOOLEAN heKey2Entry(char* filename, char* key, heEntry hentry)
400 {
401  FILE* fd;
402  int c, k;
403  int kl, i;
404  *(hentry->key) = '\0';
405  *(hentry->url) = '\0';
406  *(hentry->node) = '\0';
407  hentry->chksum = 0;
408  if (filename == NULL || key == NULL) return FALSE;
409  fd = fopen(filename, "r");
410  if (fd == NULL) return FALSE;
411  kl = strlen(key);
412 
413  k = key[0];
414  i = 0;
415  while ((c = getc(fd)) != EOF)
416  {
417  if (c < k)
418  {
419  /* Skip line */
420  while (getc(fd) != '\n') {};
421  if (i)
422  {
423  i=0;
424  k=key[0];
425  }
426  }
427  else if (c == k)
428  {
429  i++;
430  if (i == kl)
431  {
432  // \t must follow, otherwise only substring match
433  if (getc(fd) != '\t') goto Failure;
434 
435  // Now we found an exact match
436  if (hentry->key != key) strcpy(hentry->key, key);
437  // get node
438  i = 0;
439  while ((c = getc(fd)) != '\t' && c != EOF)
440  {
441  hentry->node[i] = c;
442  i++;
443  }
444  if (c == EOF) goto Failure;
445  if (hentry->node[0]=='\0')
446  strcpy(hentry->node,hentry->key);
447 
448  // get url
449  //hentry->node[i] = '\0';
450  i = 0;
451  while ((c = getc(fd)) != '\t' && c != EOF)
452  {
453  hentry->url[i] = c;
454  i++;
455  }
456  if (c == EOF) goto Failure;
457 
458  // get chksum
459  hentry->url[i] = '\0';
460 
461  if (si_fscanf(fd, "%ld\n", &(hentry->chksum)) != 1)
462  {
463  hentry->chksum = -1;
464  }
465  fclose(fd);
466  return TRUE;
467  }
468  else if (i > kl)
469  {
470  goto Failure;
471  }
472  else
473  {
474  k = key[i];
475  }
476  }
477  else
478  {
479  goto Failure;
480  }
481  }
482  Failure:
483  fclose(fd);
484  return FALSE;
485 }
486 
487 // return TRUE if s matches re
488 // FALSE, otherwise
489 // does not distinguish lower and upper cases
490 // inteprets * as wildcard
491 static BOOLEAN strmatch(char* s, char* re)
492 {
493  if (s == NULL || *s == '\0')
494  return (re == NULL || *re == '\0' || strcmp(re, "*") == 0);
495  if (re == NULL || *re == '\0') return FALSE;
496 
497  int i;
498  char ls[MAX_HE_ENTRY_LENGTH + 1];
499  char rs[MAX_HE_ENTRY_LENGTH + 1];
500  char *l, *r, *ll, *rr;
501 
502  // make everything to lower case
503  i=1;
504  ls[0] = '\0';
505  do
506  {
507  if (*s >= 'A' && *s <= 'Z') ls[i] = *s + ('a' - 'A');
508  else ls[i] = *s;
509  i++;
510  s++;
511  } while (*s != '\0');
512  ls[i] = '\0';
513  l = &(ls[1]);
514 
515  i=1;
516  rs[0] = '\0';
517  do
518  {
519  if (*re >= 'A' && *re <= 'Z') rs[i]= *re + ('a' - 'A');
520  else rs[i] = *re;
521  i++;
522  re++;
523  } while (*re != '\0');
524  rs[i] = '\0';
525  r = &(rs[1]);
526 
527  // chopp of exact matches from beginning and end
528  while (*r != '*' && *r != '\0' && *l != '\0')
529  {
530  if (*r != *l) return FALSE;
531  *r = '\0';
532  *s = '\0';
533  r++;
534  l++;
535  }
536  if (*r == '\0') return (*l == '\0');
537  if (*r == '*' && r[1] == '\0') return TRUE;
538  if (*l == '\0') return FALSE;
539 
540  rr = &r[strlen(r) - 1];
541  ll = &l[strlen(l) - 1];
542  while (*rr != '*' && *rr != '\0' && *ll != '\0')
543  {
544  if (*rr != *ll) return FALSE;
545  *rr = '\0';
546  *ll = '\0';
547  rr--;
548  ll--;
549  }
550  if (*rr == '\0') return (*ll == '\0');
551  if (*rr == '*' && rr[-1] == '\0') return TRUE;
552  if (*ll == '\0') return FALSE;
553 
554  // now *r starts with a * and ends with a *
555  r++;
556  *rr = '\0'; rr--;
557  while (*r != '\0')
558  {
559  rr = r + 1;
560  while (*rr != '*' && *rr != '\0') rr++;
561  if (*rr == '*')
562  {
563  *rr = '\0';
564  rr++;
565  }
566  l = strstr(l, r);
567  if (l == NULL) return FALSE;
568  r = rr;
569  }
570  return TRUE;
571 }
572 
573 // similar to heKey2Entry, except that
574 // key is taken as regexp (see above)
575 // and number of matches is returned
576 // if number of matches > 0, then hentry contains entry for first match
577 // if number of matches > 1, matches are printed as komma-separated
578 // into global string
579 static int heReKey2Entry (char* filename, char* key, heEntry hentry)
580 {
581  int i = 0;
582  FILE* fd;
583  char index_key[MAX_HE_ENTRY_LENGTH];
584 
585  if (filename == NULL || key == NULL) return 0;
586  fd = fopen(filename, "r");
587  if (fd == NULL) return 0;
588  memset(index_key,0,MAX_HE_ENTRY_LENGTH);
589  while (si_fscanf(fd, "%[^\t]\t%*[^\n]\n", index_key) == 1)
590  {
591  if ((index_key[MAX_HE_ENTRY_LENGTH-1]!='\0'))
592  {
593  index_key[MAX_HE_ENTRY_LENGTH-1]='\0';
594  Werror("index file corrupt at line >>%s<<",index_key);
595  break;
596  }
597  else if (strmatch(index_key, key))
598  {
599  i++;
600  if (i == 1)
601  {
602  heKey2Entry(filename, index_key, hentry);
603  }
604  else if (i == 2)
605  {
606  StringAppend("?%s; ?%s;", hentry->key, index_key);
607  }
608  else
609  {
610  StringAppend(" ?%s;", index_key);
611  }
612  }
613  }
614  fclose(fd);
615  return i;
616 }
617 
618 // test for h being a string and print it
619 static void hePrintHelpStr(const idhdl hh,const char *id,const char *pa)
620 {
621  if ((hh!=NULL) && (IDTYP(hh)==STRING_CMD))
622  {
623  PrintS(IDSTRING(hh));
624  PrintLn();
625  }
626  else
627  Print("`%s` not found in package %s\n",id,pa);
628 }
629 // try to find the help string as a loaded procedure or library
630 // if found, display the help and return TRUE
631 // otherwise, return FALSE
632 static BOOLEAN heOnlineHelp(char* s)
633 {
634  char *ss;
635  idhdl h;
636 
637  if ((ss=strstr(s,"::"))!=NULL)
638  {
639  *ss='\0';
640  ss+=2;
641  h=ggetid(s);
642  if (h!=NULL)
643  {
644  Print("help for %s from package %s\n",ss,s);
645  char s_help[200];
646  strcpy(s_help,ss);
647  strcat(s_help,"_help");
648  idhdl hh=IDPACKAGE(h)->idroot->get(s_help,0);
649  hePrintHelpStr(hh,s_help,s);
650  return TRUE;
651  }
652  else Print("package %s not found\n",s);
653  return TRUE; /* do not search the manual */
654  }
655  h=IDROOT->get(s,myynest);
656  // try help for a procedure
657  if (h!=NULL)
658  {
659  if (IDTYP(h)==PROC_CMD)
660  {
661  char *lib=iiGetLibName(IDPROC(h));
662  if((lib!=NULL)&&(*lib!='\0'))
663  {
664  Print("// proc %s from lib %s\n",s,lib);
665  s=iiGetLibProcBuffer(IDPROC(h), 0);
666  if (s!=NULL)
667  {
668  PrintS(s);
669  omFree((ADDRESS)s);
670  }
671  return TRUE;
672  }
673  }
674  else if (IDTYP(h)==PACKAGE_CMD)
675  {
676  idhdl hh=IDPACKAGE(h)->idroot->get("info",0);
677  hePrintHelpStr(hh,"info",s);
678  return TRUE;
679  }
680  return FALSE;
681  }
682 
683  // try help for a library
684  int ls = strlen(s);
685  char* str = NULL;
686  // check that it ends with "[.,_]lib"
687  if (strlen(s) >=4 && strcmp(&s[ls-3], "lib") == 0)
688  {
689  if (s[ls - 4] == '.') str = s;
690  else
691  {
692  str = omStrDup(s);
693  str[ls - 4] = '.';
694  }
695  }
696  else
697  {
698  return FALSE;
699  }
700 
701  char libnamebuf[128];
702  FILE *fp=NULL;
703  // first, search for library of that name
704  if ((str[1]!='\0') &&
705  ((iiLocateLib(str, libnamebuf) && (fp=feFopen(libnamebuf, "rb")) !=NULL)
706  ||
707  ((fp=feFopen(str,"rb", libnamebuf))!=NULL)))
708  {
709  extern FILE *yylpin;
710  lib_style_types lib_style; // = OLD_LIBSTYLE;
711 
712  yylpin = fp;
713  yylplex(str, libnamebuf, &lib_style, IDROOT, FALSE, GET_INFO);
714  reinit_yylp();
715  if(lib_style == OLD_LIBSTYLE)
716  {
717  char buf[256];
718  fseek(fp, 0, SEEK_SET);
719  Warn( "library %s has an old format. Please fix it for the next time",
720  str);
721  if (str != s) omFree(str);
723  while (fgets( buf, sizeof(buf), fp))
724  {
725  if (strncmp(buf,"//",2)==0)
726  {
727  if (found) return TRUE;
728  }
729  else if ((strncmp(buf,"proc ",5)==0)||(strncmp(buf,"LIB ",4)==0))
730  {
731  if (!found) WarnS("no help part in library found");
732  return TRUE;
733  }
734  else
735  {
736  found=TRUE;
737  PrintS(buf);
738  }
739  }
740  }
741  else
742  {
743  if (str != s) omFree(str);
744  fclose( yylpin );
748  }
749  return TRUE;
750  }
751 
752  if (str != s) omFree(str);
753  return FALSE;
754 }
755 
756 static long heKeyChksum(char* key)
757 {
758  if (key == NULL || *key == '\0') return 0;
759  idhdl h=IDROOT->get(key,myynest);
760  if ((h!=NULL) && (IDTYP(h)==PROC_CMD))
761  {
762  procinfo *pi = IDPROC(h);
763  if (pi != NULL) return pi->data.s.help_chksum;
764  }
765  return 0;
766 }
767 
768 /*****************************************************************
769  *
770  * Implementation : Help Browsers
771  *
772  *****************************************************************/
773 
775 
776 static void heBrowserHelp(heEntry hentry)
777 {
778  // check checksums of procs
779  int kchksum = (hentry != NULL && hentry->chksum > 0 ?
780  heKeyChksum(hentry->key) : 0);
781  if (kchksum && kchksum != hentry->chksum && heOnlineHelp(hentry->key))
782  return;
783 
784  if (heCurrentHelpBrowser == NULL) feHelpBrowser(NULL, 0);
785  assume(heCurrentHelpBrowser != NULL);
786  if (! feHelpCalled)
787  {
788  Warn("Displaying help in browser '%s'.", heCurrentHelpBrowser->browser);
789  //if (strcmp(heCurrentHelpBrowser->browser, "netscape") == 0 &&
790  // feResource('h', 0) == NULL)
791  //{
792  // Warn("Using URL '%s'.", feResource('u', 0));
793  //}
794  Warn("Use 'system(\"--browser\", <browser>);' to change browser,");
795  StringSetS("where <browser> can be: ");
796  int i = 0;
797  i = 0;
798  while (heHelpBrowsers[i].browser != NULL)
799  {
800  if (heHelpBrowsers[i].init_proc(0,i))
801  StringAppend("\"%s\", ", heHelpBrowsers[i].browser);
802  i++;
803  }
804  char *browsers=StringEndS();
805  if (browsers[strlen(browsers)-2] == ',')
806  {
807  browsers[strlen(browsers)-2] = '.';
808  browsers[strlen(browsers)-1] = '\0';
809  }
810  WarnS(browsers);
811  omFree(browsers);
812  }
813 
814  heCurrentHelpBrowser->help_proc(hentry, heCurrentHelpBrowserIndex);
815  feHelpCalled = TRUE;
816 }
817 
818 #define MAX_SYSCMD_LEN MAXPATHLEN*2
819 static BOOLEAN heGenInit(int warn, int br)
820 {
821  if (heHelpBrowsers[br].required==NULL) return TRUE;
822  const char *p=heHelpBrowsers[br].required;
823  while (*p>'\0')
824  {
825  switch (*p)
826  {
827  case '#': break;
828  case ' ': break;
829  case 'i': /* singular.hlp */
830  case 'x': /* singular.idx */
831  case 'h': /* html dir */
832  if (feResource(*p, warn) == NULL)
833  {
834  if (warn) Warn("resource `%c` not found",*p);
835  return FALSE;
836  }
837  break;
838  case 'D': /* DISPLAY */
839  if (getenv("DISPLAY") == NULL)
840  {
841  if (warn) WarnS("resource `D` not found");
842  return FALSE;
843  }
844  break;
845  case 'E': /* executable: E:xterm: */
846  case 'O': /* OS: O:ix86Mac-darwin/ppcMac-darwin: */
847  {
848  char name[128];
849  char exec[128];
850  char op=*p;
851  memset(name,0,128);
852  int i=0;
853  p++;
854  while (((*p==':')||(*p<=' ')) && (*p!='\0')) p++;
855  while((i<127) && (*p>' ') && (*p!=':'))
856  {
857  name[i]=*p; p++; i++;
858  }
859  if (i==0) return FALSE;
860 
861  if ((op=='O') && (strcmp(name,S_UNAME)!=0))
862  return FALSE;
863  if ((op=='E') && (omFindExec(name,exec)==NULL))
864  {
865  if (warn) Warn("executable `%s` not found",name);
866  return FALSE;
867  }
868  }
869  break;
870  default: Warn("unknown char %c",*p);
871  break;
872  }
873  p++;
874  }
875  return TRUE;
876 }
877 
878 static void heGenHelp(heEntry hentry, int br)
879 {
880  char sys[MAX_SYSCMD_LEN];
881  const char *p=heHelpBrowsers[br].action;
882  if (p==NULL) {PrintS("no action ?\n"); return;}
883  memset(sys,0,MAX_SYSCMD_LEN);
884  int i=0;
885  while ((*p>'\0')&& (i<MAX_SYSCMD_LEN))
886  {
887  if ((*p)=='%')
888  {
889  p++;
890  switch (*p)
891  {
892  case 'f': /* local html:file */
893  case 'h': /* local html:URL */
894  case 'H': /* www html */
895  {
896  char temp[256];
897  char *htmldir = feResource('h' /*"HtmlDir"*/);
898  if ((*p=='h')&&(htmldir!=NULL))
899  strcat(sys,"file://localhost");
900  else if ((*p=='H')||(htmldir==NULL))
901  htmldir = feResource('u' /* %H -> "ManualUrl"*/);
902  /* always defined */
903  if (hentry != NULL && *(hentry->url) != '\0')
904  #ifdef HAVE_VSNPRINTF
905  {
906  if (*p=='H')
907  snprintf(temp,256,"%s/%d-%d-%d/%s", htmldir,
908  SINGULAR_VERSION/1000,
909  (SINGULAR_VERSION % 1000)/100,
910  (SINGULAR_VERSION % 100)/10,
911  hentry->url);
912  else
913  snprintf(temp,256,"%s/%s", htmldir, hentry->url);
914  }
915  else
916  {
917  if (*p=='H')
918  snprintf(temp,256,"%s/%d-%d-%d/index.htm", htmldir,
919  SINGULAR_VERSION/1000,
920  (SINGULAR_VERSION % 1000)/100,
921  (SINGULAR_VERSION % 100)/10
922  );
923  else
924  snprintf(temp,256,"%s/index.htm", htmldir);
925  }
926  #else
927  {
928  if (*p=='H')
929  sprintf(temp,"%s/%d-%d-%d/%s", htmldir,
930  SINGULAR_VERSION/1000,
931  (SINGULAR_VERSION % 1000)/100,
932  (SINGULAR_VERSION % 100)/10,
933  hentry->url);
934  else
935  sprintf(temp,"%s/%d-%d-%d/%s", htmldir, hentry->url);
936  }
937  else
938  if (*p=='H')
939  sprintf(temp,"%s/%d-%d-%d/index.htm", htmldir,
940  SINGULAR_VERSION/1000,
941  (SINGULAR_VERSION % 1000)/100,
942  (SINGULAR_VERSION % 100)/10
943  );
944  else
945  sprintf(temp,"%s/index.htm", htmldir);
946  }
947  #endif
948  strcat(sys,temp);
949  if ((*p)=='f')
950  { // remove #SEC
951  char *pp=(char *)strchr(sys,'#');
952  if (pp!=NULL)
953  {
954  *pp='\0';
955  i=strlen(sys);
956  memset(pp,0,MAX_SYSCMD_LEN-i);
957  }
958  }
959  i=strlen(sys);
960  break;
961  }
962  case 'i': /* singular.hlp */
963  {
964  char *i_res=feResource('i');
965  if (i_res!=NULL) strcat(sys,i_res);
966  else
967  {
968  WarnS("singular.hlp not found");
969  return;
970  }
971  i=strlen(sys);
972  break;
973  }
974  case 'n': /* info node */
975  {
976  char temp[256];
977  if ((hentry!=NULL) && (*(hentry->node) != '\0'))
978  sprintf(temp,"%s",hentry->node);
979  //else if ((hentry!=NULL) && (hentry->key!=NULL))
980  // sprintf(temp,"Index '%s'",hentry->key);
981  else
982  sprintf(temp,"Top");
983  strcat(sys,temp);
984  i=strlen(sys);
985  break;
986  }
987  case 'v': /* version number*/
988  {
989  char temp[256];
990  sprintf(temp,"%d-%d-%d",SINGULAR_VERSION/1000,
991  (SINGULAR_VERSION % 1000)/100,
992  (SINGULAR_VERSION % 100)/10);
993  strcat(sys,temp);
994  i=strlen(sys);
995  break;
996  }
997  default: break;
998  }
999  p++;
1000  }
1001  else
1002  {
1003  sys[i]=*p;
1004  p++;i++;
1005  }
1006  }
1007  Print("running `%s`\n",sys);
1008  (void) system(sys);
1009 }
1010 
1011 static BOOLEAN heDummyInit(int /*warn*/, int /*br*/)
1012 {
1013  return TRUE;
1014 }
1015 static void heDummyHelp(heEntry /*hentry*/, int /*br*/)
1016 {
1017  Werror("No functioning help browser available.");
1018 }
1019 
1020 static BOOLEAN heEmacsInit(int /*warn*/, int /*br*/)
1021 {
1022  return TRUE;
1023 }
1024 static void heEmacsHelp(heEntry hentry, int /*br*/)
1025 {
1026  WarnS("Your help command could not be executed. Use");
1027  Warn("C-h C-s %s",
1028  (hentry != NULL && *(hentry->node) != '\0' ? hentry->node : "Top"));
1029  Warn("to enter the Singular online help. For general");
1030  Warn("information on Singular running under Emacs, type C-h m.");
1031 }
1032 static int singular_manual(char *str, BOOLEAN isIndexEntry);
1033 static void heBuiltinHelp(heEntry hentry, int /*br*/)
1034 {
1035  char* node = omStrDup(hentry != NULL && *(hentry->key) != '\0' ?
1036  hentry->key : "Top");
1037  singular_manual(node,(hentry != NULL) && (hentry->url!=NULL));
1038  omFree(node);
1039 }
1040 
1041 
1042 /* ========================================================================== */
1043 // old, stupid builtin_help
1044 // This could be implemented much more clever, but I'm too lazy to do this now
1045 //
1046 #define HELP_OK 0
1047 #define FIN_INDEX '\037'
1048 #define HELP_NOT_OPEN 1
1049 #define HELP_NOT_FOUND 2
1050 #define BUF_LEN 256
1051 #define IDX_LEN 256
1052 #define MAX_LINES 21
1053 
1054 static inline char tolow(char p)
1055 {
1056  if (('A'<=p)&&(p<='Z')) return p | 040;
1057  return p;
1058 }
1059 
1060 /*************************************************/
1061 static int show(unsigned long offset, char *close)
1062 { char buffer[BUF_LEN+1];
1063  int lines = 0;
1064  FILE * help;
1065 
1066  if( (help = fopen(feResource('i'), "rb")) == NULL)
1067  return HELP_NOT_OPEN;
1068 
1069  fseek(help, (long)(offset+1), (int)0);
1070  while( (!feof(help))
1071  && (*fgets(buffer, BUF_LEN, help) != EOF)
1072  && (buffer[0] != FIN_INDEX))
1073  {
1074  printf("%s", buffer);
1075  if(lines++> MAX_LINES)
1076  {
1077  printf("\n Press <RETURN> to continue or x to exit help.\n");
1078  fflush(stdout);
1079  *close = (char)getchar();
1080  if(*close=='x')
1081  {
1082  getchar();
1083  break;
1084  }
1085  lines=0;
1086  }
1087  }
1088  if(*close!='x')
1089  {
1090  printf("\nEnd of part. Press <RETURN> to continue or x to exit help.\n");
1091  fflush(stdout);
1092  *close = (char)getchar();
1093  if(*close=='x')
1094  getchar();
1095  }
1096  fclose(help);
1097  return HELP_OK;
1098 }
1099 
1100 /*************************************************/
1101 static int singular_manual(char *str, BOOLEAN isIndexEntry)
1102 { FILE *index=NULL;
1103  unsigned long offset;
1104  char *p,close=' ';
1105  int done = 0;
1106  char buffer[BUF_LEN+1],
1107  Index[IDX_LEN+1],
1108  String[IDX_LEN+1];
1109  Print("HELP >>%s>>\n",str);
1110 
1111  if( (index = fopen(feResource('i'), "rb")) == NULL)
1112  {
1113  return HELP_NOT_OPEN;
1114  }
1115 
1116  if (!isIndexEntry)
1117  {
1118  for(p=str; *p; p++) *p = tolow(*p);/* */
1119  do
1120  {
1121  p--;
1122  }
1123  while ((p != str) && (*p<=' '));
1124  p++;
1125  *p='\0';
1126  (void)sprintf(String, " %s ", str);
1127  }
1128  else
1129  {
1130  (void)sprintf(String, " %s", str);
1131  }
1132 
1133  while(!feof(index)
1134  && (fgets(buffer, BUF_LEN, index) != (char *)0)
1135  && (buffer[0] != FIN_INDEX));
1136 
1137  while(!feof(index))
1138  {
1139  if (fgets(buffer, BUF_LEN, index)==NULL) break; /*fill buffer */
1140  if (si_sscanf(buffer, "Node:%[^\177]\177%ld\n", Index, &offset)!=2)
1141  continue;
1142  if (!isIndexEntry)
1143  {
1144  for(p=Index; *p; p++) *p = tolow(*p);/* */
1145  (void)strcat(Index, " ");
1146  if( strstr(Index, String)!=NULL)
1147  {
1148  done++; (void)show(offset, &close);
1149  }
1150  }
1151  else if( strcmp(Index, String)==0)
1152  {
1153  done++; (void)show(offset, &close);
1154  break;
1155  }
1156  Index[0]='\0';
1157  if(close=='x')
1158  break;
1159  }
1160  if (index != NULL) (void)fclose(index);
1161  if(done==0)
1162  {
1163  Warn("`%s` not found",String);
1164  return HELP_NOT_FOUND;
1165  }
1166  return HELP_OK;
1167 }
1168 /*************************************************/
int status int fd
Definition: si_signals.h:59
const char * feHelpBrowser(char *which, int warn)
Definition: fehelp.cc:260
char url[MAX_HE_ENTRY_LENGTH]
Definition: fehelp.cc:48
const CanonicalForm int s
Definition: facAbsFact.cc:55
long chksum
Definition: fehelp.cc:49
void PrintLn()
Definition: reporter.cc:327
CanonicalForm fp
Definition: cfModGcd.cc:4043
static void * feOptValue(feOptIndex opt)
Definition: feOpt.h:40
int yylplex(const char *libname, const char *libfile, lib_style_types *lib_style, idhdl pl, BOOLEAN autoexport=FALSE, lp_modes=LOAD_LIB)
static int singular_manual(char *str, BOOLEAN isIndexEntry)
Definition: fehelp.cc:1101
#define FALSE
Definition: auxiliary.h:140
static BOOLEAN heOnlineHelp(char *s)
Definition: fehelp.cc:632
#define MAX_HE_ENTRY_LENGTH
Definition: fehelp.cc:43
return P p
Definition: myNF.cc:203
f
Definition: cfModGcd.cc:4022
#define SINGULAR_VERSION
Definition: mod2.h:94
static char * feResource(feResourceConfig config, int warn)
Definition: feResource.cc:252
static BOOLEAN heEmacsInit(int, int)
Definition: fehelp.cc:1020
static int show(unsigned long offset, char *close)
Definition: fehelp.cc:1061
static void feBrowserFile()
Definition: fehelp.cc:188
#define HELP_NOT_FOUND
Definition: fehelp.cc:1049
static BOOLEAN feHelpCalled
Definition: fehelp.cc:774
heBrowserInitProc init_proc
Definition: fehelp.cc:59
#define IDROOT
Definition: ipid.h:20
const char * required
Definition: fehelp.cc:61
const char * action
Definition: fehelp.cc:62
char * getenv()
#define TRUE
Definition: auxiliary.h:144
void * ADDRESS
Definition: auxiliary.h:161
char key[MAX_HE_ENTRY_LENGTH]
Definition: fehelp.cc:46
void * value
Definition: fegetopt.h:93
static int heReKey2Entry(char *filename, char *key, heEntry hentry)
Definition: fehelp.cc:579
int k
Definition: cfEzgcd.cc:93
const char * browser
Definition: fehelp.cc:58
char * StringEndS()
Definition: reporter.cc:151
static void heBrowserHelp(heEntry hentry)
Definition: fehelp.cc:776
#define WarnS
Definition: emacs.cc:81
Definition: idrec.h:34
poly pp
Definition: myNF.cc:296
static void heBuiltinHelp(heEntry hentry, int)
Definition: fehelp.cc:1033
#define MAX_LINES
Definition: fehelp.cc:1052
bool found
Definition: facFactorize.cc:56
static int heCurrentHelpBrowserIndex
Definition: fehelp.cc:86
void feStringAppendBrowsers(int warn)
Definition: fehelp.cc:352
#define IDPACKAGE(a)
Definition: ipid.h:138
int myynest
Definition: febase.cc:46
#define IDTYP(a)
Definition: ipid.h:118
static BOOLEAN heDummyInit(int, int)
Definition: fehelp.cc:1011
const ring r
Definition: syzextra.cc:208
char node[MAX_HE_ENTRY_LENGTH]
Definition: fehelp.cc:47
#define omFree(addr)
Definition: omAllocDecl.h:261
#define HELP_NOT_OPEN
Definition: fehelp.cc:1048
#define assume(x)
Definition: mod2.h:405
void StringSetS(const char *st)
Definition: reporter.cc:128
int status int void * buf
Definition: si_signals.h:59
void StringAppendS(const char *st)
Definition: reporter.cc:107
Print("running `%s`\n", sys)
#define omfree(addr)
Definition: omAllocDecl.h:237
static void heEmacsHelp(heEntry hentry, int)
Definition: fehelp.cc:1024
struct fe_option feOptSpec[]
procinfodata data
Definition: subexpr.h:62
static BOOLEAN heKey2Entry(char *filename, char *key, heEntry hentry)
Definition: fehelp.cc:399
static void heDummyHelp(heEntry hentry, int)
Definition: fehelp.cc:1015
void system(sys)
#define IDSTRING(a)
Definition: ipid.h:135
#define dReportBug(s)
Definition: reporter.h:110
FILE * feFopen(const char *path, const char *mode, char *where, short useWerror, short path_only)
Definition: feFopen.cc:47
#define StringAppend
Definition: emacs.cc:82
int i
Definition: cfEzgcd.cc:123
static heBrowser heCurrentHelpBrowser
Definition: fehelp.cc:85
#define FIN_INDEX
Definition: fehelp.cc:1047
void PrintS(const char *s)
Definition: reporter.cc:294
static void heGenHelp(heEntry hentry, int)
Definition: fehelp.cc:878
#define url
Definition: libparse.cc:1258
static void hePrintHelpStr(const idhdl hh, const char *id, const char *pa)
Definition: fehelp.cc:619
#define HELP_OK
Definition: fehelp.cc:1046
BOOLEAN iiLocateLib(const char *lib, char *where)
Definition: iplib.cc:799
#define help
Definition: libparse.cc:1228
static int index(p_Length length, p_Ord ord)
Definition: p_Procs_Impl.h:597
static long heKeyChksum(char *key)
Definition: fehelp.cc:756
#define IDPROC(a)
Definition: ipid.h:139
#define pi
Definition: libparse.cc:1143
BOOLEAN(* heBrowserInitProc)(int warn, int br)
Definition: fehelp.cc:54
void(* heBrowserHelpProc)(heEntry hentry, int br)
Definition: fehelp.cc:53
char name(const Variable &v)
Definition: variable.h:95
#define NULL
Definition: omList.c:10
char * text_buffer
Definition: libparse.cc:1097
static heBrowser_s * heHelpBrowsers
Definition: fehelp.cc:96
static BOOLEAN heGenInit(int, int)
Definition: fehelp.cc:819
#define MAX_SYSCMD_LEN
Definition: fehelp.cc:818
lib_style_types
Definition: libparse.h:9
heBrowserHelpProc help_proc
Definition: fehelp.cc:60
static char * strclean(char *str)
Definition: fehelp.cc:375
#define IDX_LEN
Definition: fehelp.cc:1051
char * iiGetLibName(procinfov pi)
Definition: iplib.cc:101
char * omFindExec(const char *name, char *exec)
Definition: omFindExec.c:279
static char tolow(char p)
Definition: fehelp.cc:1054
char libnamebuf[128]
Definition: libparse.cc:1096
heEntry_s * heEntry
Definition: fehelp.cc:51
#define SEEK_SET
Definition: mod2.h:125
heBrowser_s * heBrowser
Definition: fehelp.cc:64
static BOOLEAN strmatch(char *s, char *re)
Definition: fehelp.cc:491
int offset
Definition: libparse.cc:1091
char * iiGetLibProcBuffer(procinfo *pi, int part)
Definition: iplib.cc:210
static Poly * h
Definition: janet.cc:978
int BOOLEAN
Definition: auxiliary.h:131
void Werror(const char *fmt,...)
Definition: reporter.cc:199
idhdl ggetid(const char *n, BOOLEAN, idhdl *packhdl)
Definition: ipid.cc:490
#define omAlloc0(size)
Definition: omAllocDecl.h:211
int l
Definition: cfEzgcd.cc:94
void feHelp(char *str)
Definition: fehelp.cc:103
#define BUF_LEN
Definition: fehelp.cc:1050
#define Warn
Definition: emacs.cc:80
void reinit_yylp()
Definition: libparse.cc:3377
#define omStrDup(s)
Definition: omAllocDecl.h:263