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