source: git/Singular/fehelp.cc @ 3bef0a

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