source: git/Singular/fehelp.cc @ 2bc4f5

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