source: git/Singular/fehelp.cc @ af223b0

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