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