source: git/Singular/fehelp.cc @ e6af18

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