source: git/Singular/fehelp.cc @ cb8103a

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