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