source: git/Singular/fehelp.cc @ 33b509

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