source: git/libpolys/resources/feResource.cc @ 630ca9

spielwiese
Last change on this file since 630ca9 was 630ca9, checked in by Oleksandr Motsak <motsak@…>, 13 years ago
FIX: separate debug/optimized flags for resources and coeffs FIX: longrat.cc: missing "coeff" arguments!
  • Property mode set to 100644
File size: 18.9 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id$ */
5/*
6* ABSTRACT: management of resources
7*/
8
9#include <stdlib.h>
10#include <unistd.h>
11#include <string.h>
12
13#include "config.h"
14#include <misc/auxiliary.h>
15
16#include <resources/feResource.h>
17
18
19
20#ifdef AIX_4
21#define HAVE_PUTENV 1
22#endif
23
24#if defined(HPUX_10) || defined(HPUX_9)
25extern "C" int setenv(const char *name, const char *value, int overwrite);
26#endif
27
28
29#include <reporter/reporter.h>
30#if !defined(ESINGULAR) && !defined(TSINGULAR)
31#include <omalloc/omalloc.h>
32#else
33char* feResource(const char id, int warn = -1);
34char* feResource(const char* key, int warn = -1);
35#endif
36
37// define RESOURCE_DEBUG for chattering about resource management
38// #define RESOURCE_DEBUG
39
40#if defined(MAKE_DISTRIBUTION)
41#if defined(ix86_Win) && ! defined(__CYGWIN__)
42#define SINGULAR_DEFAULT_DIR "/Singular/"S_VERSION1
43#else // unix
44#define SINGULAR_DEFAULT_DIR "/usr/local/Singular/"S_VERSION1
45#endif
46#else // ! defined(MAKE_DISTRIBUTION)
47#define SINGULAR_DEFAULT_DIR S_ROOT_DIR
48#endif // defined(MAKE_DISTRIBUTION)
49
50/*****************************************************************
51 *
52 * Declarations: Data  structures
53 *
54 *****************************************************************/
55typedef enum {feResUndef = 0, feResBinary, feResDir, feResFile, feResUrl, feResPath} feResourceType;
56
57typedef struct feResourceConfig_s
58{
59  const char*           key;   // key to identify resource
60  const char            id;    // char id to identify resource
61  feResourceType  type;  // type of Resource
62  const char*           env;   // env variable to look for
63  const char*           fmt;   // format string -- see below for epxlaination
64  char*                 value; // what it was set to: may be changed
65} feResourceConfig_s;
66typedef feResourceConfig_s * feResourceConfig;
67
68// feSprintf transforms format strings as follows:
69// 1.) substrings of the form %c (c being a letter) are replaced by respective resource value
70// 2.) substrings of the form $string are replaced by value of resp. env variable
71
72// feCleanResource makes furthermore  the following transformations (except for URL resources)
73// 1.) '/' characters are replaced by respective directory - separators
74// 2.) ';' characters are replaced by respective path separators
75static feResourceConfig_s feResourceConfigs[] =
76{
77  {"SearchPath",    's', feResPath,  NULL,
78   "$SINGULARPATH;"
79   "%b/LIB;"
80   "%b/MOD;"
81   "%r/LIB;"
82   "%r/../LIB;"
83   "%d/LIB;"
84   "%d/../LIB"
85   ""},
86  {"Singular",  'S',    feResBinary,"SINGULAR_EXECUTABLE",  "%d/"S_UNAME"/Singular",(char *)""},
87  {"BinDir",    'b',    feResDir,   "SINGULAR_BIN_DIR",     "%d/"S_UNAME,           (char *)""},
88  {"RootDir",   'r',    feResDir,   "SINGULAR_ROOT_DIR",    "%b/..",                (char *)""},
89  {"DefaultDir",'d',    feResDir,   "SINGULAR_DEFAULT_DIR",  SINGULAR_DEFAULT_DIR,  (char *)""},
90  {"InfoFile",  'i',    feResFile,  "SINGULAR_INFO_FILE",   "%r/info/singular.hlp", (char *)""},
91  {"IdxFile",   'x',    feResFile,  "SINGULAR_IDX_FILE",    "%r/doc/singular.idx",  (char *)""},
92  {"HtmlDir",   'h',    feResDir,   "SINGULAR_HTML_DIR",    "%r/html",              (char *)""},
93#ifdef ix86_Win
94  {"HtmlHelpFile",'C',  feResFile,  "SINGULAR_CHM_FILE",    "%r/doc/Manual.chm",    (char *)""},
95#endif
96  {"ManualUrl", 'u',    feResUrl,   "SINGULAR_URL",         "http://www.singular.uni-kl.de/Manual/"S_VERSION1,    (char *)""},
97  {"ExDir",     'm',    feResDir,   "SINGULAR_EXAMPLES_DIR","%r/examples",          (char *)""},
98  {"Path",      'p',    feResPath,  NULL,                   "%b;$PATH",             (char *)""},
99
100#ifdef ESINGULAR
101  {"emacs",     'E',    feResBinary,"ESINGULAR_EMACS",      "%b/emacs",             (char *)""},
102  {"xemacs",    'A',    feResBinary,"ESINGULAR_EMACS",      "%b/xemacs",            (char *)""},
103  {"SingularEmacs",'M', feResBinary,"ESINGULAR_SINGULAR",   "%b/Singular",          (char *)""},
104  {"EmacsLoad", 'l',    feResFile,  "ESINGULAR_EMACS_LOAD", "%e/.emacs-singular",   (char *)""},
105  {"EmacsDir",  'e',    feResDir,   "ESINGULAR_EMACS_DIR",  "%r/emacs",             (char *)""},
106#elif defined(TSINGULAR)
107  {"SingularXterm",'M', feResBinary,"TSINGULAR_SINGULAR",   "%b/Singular",          (char *)""},
108#ifdef ix86_Win
109  {"rxvt",      'X',    feResBinary,"RXVT",                 "%b/rxvt",              (char *)""},
110#else
111  {"xterm",     'X',    feResBinary,"XTERM",                "%b/xterm",             (char *)""},
112#endif
113#else
114  {"EmacsDir",  'e',    feResDir,   "SINGULAR_EMACS_DIR",   "%r/emacs",             (char *)""},
115#endif
116  {NULL, 0, feResUndef, NULL, NULL, NULL}, // must be the last record
117};
118
119
120/*****************************************************************
121 *
122 * Declarations: Local variables / functions
123 *
124 *****************************************************************/
125char* feArgv0=NULL;
126#define MAXRESOURCELEN 5*MAXPATHLEN
127
128static feResourceConfig feGetResourceConfig(const char id);
129static feResourceConfig feGetResourceConfig(const char* key);
130static char* feResource(feResourceConfig config, int warn);
131static char* feResourceDefault(feResourceConfig config);
132static char* feInitResource(feResourceConfig config, int warn);
133static char* feGetExpandedExecutable();
134static BOOLEAN feVerifyResourceValue(feResourceType type, char* value);
135static char* feCleanResourceValue(feResourceType type, char* value);
136static char* feCleanUpFile(char* fname);
137static char* feCleanUpPath(char* path);
138static void mystrcpy(char* d, char* s);
139static char* feSprintf(char* s, const char* fmt, int warn = -1);
140#if defined(ix86_Win) && defined(__GNUC__)
141// utility function of Cygwin32:
142extern "C" int cygwin32_posix_path_list_p (const char *path);
143#endif
144
145/*****************************************************************
146 *
147 * Public functions
148 *
149 *****************************************************************/
150char* feResource(const char* key, int warn)
151{
152  return feResource(feGetResourceConfig(key), warn);
153}
154
155char* feGetResource(const char id)
156{
157  return feResource(feGetResourceConfig(id), -1);
158}
159
160char* feResource(const char id, int warn)
161{
162  return feResource(feGetResourceConfig(id), warn);
163}
164
165char* feResourceDefault(const char id)
166{
167  return feResourceDefault(feGetResourceConfig(id));
168}
169
170char* feResourceDefault(const char* key)
171{
172  return feResourceDefault(feGetResourceConfig(key));
173}
174
175void feInitResources(char* argv0)
176{
177#if defined(ix86_Win) && defined(__GNUC__)
178  if (cygwin32_posix_path_list_p (getenv("PATH")))
179    fePathSep = ':';
180#endif
181  feArgv0 = omStrDup(argv0);
182#ifdef RESOURCE_DEBUG
183  printf("feInitResources: entering with argv0=%s=\n", argv0);
184#endif
185  // init some Resources
186  feResource('b');
187  feResource('r');
188  // don't complain about stuff when initializing SingularPath
189  feResource('s',0);
190
191#if defined(HAVE_SETENV) || defined(HAVE_PUTENV)
192  char* path = feResource('p');
193#ifdef RESOURCE_DEBUG
194  printf("feInitResources: setting path with argv0=%s=\n", path);
195#endif
196#ifdef HAVE_PUTENV
197  if (path != NULL) { char *s=(char *)omAlloc0(strlen(path)+6);
198                      sprintf(s,"PATH=%s",path);
199                      putenv(s);
200                    }
201#else
202  if (path != NULL) setenv("PATH", path, 1);
203#endif
204#endif
205}
206
207void feReInitResources()
208{
209  int i = 0;
210  while (feResourceConfigs[i].key != NULL)
211  {
212    if (feResourceConfigs[i].value[0] != '\0')
213    {
214      if (feResourceConfigs[i].value != NULL)
215        omFree(feResourceConfigs[i].value);
216      feResourceConfigs[i].value = (char *)"";
217    }
218    i++;
219  }
220#ifdef RESOURCE_DEBUG
221  printf("feInitResources: entering with argv0=%s=\n", feArgv0);
222#endif
223  // init some Resources
224  feResource('b');
225  feResource('r');
226  // don't complain about stuff when initializing SingularPath
227  feResource('s',0);
228}
229
230/*****************************************************************
231 *
232 * Local functions
233 *
234 *****************************************************************/
235static feResourceConfig feGetResourceConfig(const char id)
236{
237  int i = 0;
238  while (feResourceConfigs[i].key != NULL)
239  {
240    if (feResourceConfigs[i].id == id) return &(feResourceConfigs[i]);
241    i++;
242  }
243  return NULL;
244}
245
246static feResourceConfig feGetResourceConfig(const char* key)
247{
248  int i = 0;
249  while (feResourceConfigs[i].key != NULL)
250  {
251    if (strcmp(feResourceConfigs[i].key, key) == 0)
252      return &(feResourceConfigs[i]);
253    i++;
254  }
255  return NULL;
256}
257
258static char* feResource(feResourceConfig config, int warn)
259{
260  if (config == NULL) return NULL;
261  if (config->value != NULL && *(config->value) != '\0') return config->value;
262  return feInitResource(config, warn);
263}
264
265static char* feResourceDefault(feResourceConfig config)
266{
267  if (config == NULL) return NULL;
268  char* value = (char*) omAlloc(MAXRESOURCELEN);
269  feSprintf(value, config->fmt, -1);
270  return value;
271}
272
273static char* feInitResource(feResourceConfig config, int warn)
274{
275  assume(config != NULL);
276#ifdef RESOURCE_DEBUG
277  printf("feInitResource: entering for %s\n", config->key);
278#endif
279
280  char value[MAXRESOURCELEN];
281  // now we have to work
282  // First, check Environment variable
283  if (config->env != NULL)
284  {
285    char* evalue = getenv(config->env);
286    if (evalue != NULL)
287    {
288#ifdef RESOURCE_DEBUG
289      printf("feInitResource: Found value from env:%s\n", evalue);
290#endif
291      strcpy(value, evalue);
292      if (config->type == feResBinary  // do not verify binaries
293          ||
294          feVerifyResourceValue(config->type,
295                                feCleanResourceValue(config->type, value)))
296      {
297#ifdef RESOURCE_DEBUG
298        printf("feInitResource: Set value of %s to =%s=\n", config->key, value);
299#endif
300        config->value = omStrDup(value);
301        return config->value;
302      }
303    }
304  }
305
306  *value = '\0';
307  // Special treatment of executable
308  if (config->id == 'S')
309  {
310    char* executable = feGetExpandedExecutable();
311    if (executable != NULL)
312    {
313#ifdef RESOURCE_DEBUG
314      printf("exec:%s\n", executable);
315#endif
316      strcpy(value, executable);
317#ifdef RESOURCE_DEBUG
318      printf("value:%s\n", value);
319#endif
320      omFree(executable);
321    }
322  }
323  // and bindir
324  else if (config->id == 'b')
325  {
326    char* executable = feResource('S');
327#ifdef RESOURCE_DEBUG
328      printf("feInitResource: Get %s from %s\n", config->key, executable);
329#endif
330    if (executable != NULL)
331    {
332      strcpy(value, executable);
333      executable = strrchr(value, DIR_SEP);
334      if (executable != NULL) *executable = '\0';
335    }
336  }
337
338#ifdef RESOURCE_DEBUG
339  printf("value:%s\n", value);
340#endif
341
342  if (*value == '\0' && config->fmt != NULL )
343  {
344    feSprintf(value, config->fmt, warn);
345  }
346  else if (config->fmt == NULL)
347  {
348    sprintf(value, "Wrong Resource Specification of %s", config->key);
349    dReportBug(value);
350    return NULL;
351  }
352
353  // Clean and verify
354  if (feVerifyResourceValue(config->type,
355                            feCleanResourceValue(config->type, value)))
356  {
357#ifdef RESOURCE_DEBUG
358    printf("feInitResource: Set value of %s to =%s=\n", config->key, value);
359#endif
360    config->value = omStrDup(value);
361    return config->value;
362  }
363  else if (config->type == feResBinary)
364  {
365    // for binaries, search through PATH once more
366    char* executable = omFindExec(config->key, value);
367    if (executable != NULL)
368    {
369      if (feVerifyResourceValue(config->type,
370                                feCleanResourceValue(config->type, value)))
371      {
372        config->value = omStrDup(value);
373#ifdef RESOURCE_DEBUG
374        printf("feInitResource: Set value of %s to =%s=\n", config->key, config->value);
375#endif
376        return config->value;
377      }
378    }
379  }
380
381  // issue warning if explicitely requested, or if
382  // this value is gotten for the first time
383  if (warn > 0 || (warn < 0 && config->value != NULL))
384  {
385    Warn("Could not get %s. ", config->key);
386    Warn("Either set environment variable %s to %s,",
387         config->env, config->key);
388    feSprintf(value, config->fmt, warn);
389    Warn("or make sure that %s is at %s", config->key, value);
390  }
391#ifdef RESOURCE_DEBUG
392      printf("feInitResource: Set value of %s to NULL", config->key);
393#endif
394  config->value = NULL;
395  return NULL;
396}
397
398static char* feGetExpandedExecutable()
399{
400  if (feArgv0 == NULL || *feArgv0 == '\0')
401  {
402    if (feArgv0 == NULL) dReportBug("feArgv0 == NULL");
403    else dReportBug("feArgv0 == ''");
404    return NULL;
405  }
406#ifdef ix86_Win // stupid WINNT sometimes gives you argv[0] within ""
407  if (*feArgv0 == '"')
408  {
409    int l = strlen(feArgv0);
410    if (feArgv0[l-1] == '"')
411    {
412      feArgv0[l-1] = '\0';
413      feArgv0++;
414    }
415  }
416#endif
417#ifdef RESOURCE_DEBUG
418  printf("feGetExpandedExecutable: calling find_exec with =%s=\n", feArgv0);
419#endif
420  char executable[MAXRESOURCELEN];
421  char* value = omFindExec(feArgv0, executable);
422#ifdef RESOURCE_DEBUG
423  printf("feGetExpandedExecutable: find_exec exited with =%s=%d\n", executable, access(executable, X_OK));
424#endif
425  if (value == NULL)
426  {
427    char message[MAXRESOURCELEN];
428    sprintf(message, "Could not get expanded executable from %s", feArgv0);
429    dReportBug(message);
430    return NULL;
431  }
432  return omStrDup(value);
433}
434
435
436static BOOLEAN feVerifyResourceValue(feResourceType type, char* value)
437{
438#ifdef RESOURCE_DEBUG
439  printf("feVerifyResourceValue: entering with =%s=\n", value);
440  printf("%d:%d\n", access(value, R_OK), access(value, X_OK));
441#endif
442  switch(type)
443  {
444      case feResUrl:
445      case feResPath:
446        return TRUE;
447
448      case feResFile:
449        return ! access(value, R_OK);
450
451      case feResBinary:
452      case feResDir:
453        return ! access(value, X_OK);
454
455      default:
456        return FALSE;
457  }
458}
459
460/*****************************************************************
461 *
462 * Cleaning/Transformations of resource values
463 *
464 *****************************************************************/
465
466static char* feCleanResourceValue(feResourceType type, char* value)
467{
468  if (value == NULL || *value == '\0') return value;
469#ifdef RESOURCE_DEBUG
470      printf("Clean value:%s\n", value);
471#endif
472#ifdef ix86_Win
473#ifdef RESOURCE_DEBUG
474      printf("Clean WINNT value:%s\n", value);
475#endif
476  if (type == feResBinary)
477  {
478    int l = strlen(value);
479    if (l < 4 || (strcmp(&value[l-4], ".exe") != 0 &&
480                  strcmp(&value[l-4], ".EXE") != 0))
481      strcat(value, ".exe");
482  }
483#endif
484  if (type == feResFile || type == feResBinary || type == feResDir)
485    return feCleanUpFile(value);
486  if (type == feResPath)
487    return feCleanUpPath(value);
488  return value;
489}
490
491static char* feCleanUpFile(char* fname)
492{
493  char* fn, *s;
494
495#ifdef RESOURCE_DEBUG
496  printf("feCleanUpFile: entering with =%s=\n", fname);
497#endif
498  // Remove unnecessary .. and //
499  for (fn = fname; *fn != '\0'; fn++)
500  {
501    if (*fn == '/')
502    {
503      if (*(fn+1) == '\0')
504      {
505        if (fname != fn) *fn = '\0';
506        break;
507      }
508      if (*(fn + 1) == '/' && (fname != fn))
509      {
510        mystrcpy(fn, fn+1);
511        fn--;
512      }
513      else if (*(fn+1) == '.')
514      {
515        if (*(fn+2) == '.' && (*(fn + 3) == '/' || *(fn + 3) == '\0'))
516        {
517          *fn = '\0';
518          s = strrchr(fname, '/');
519          if (s != NULL)
520          {
521            mystrcpy(s+1, fn + (*(fn + 3) != '\0' ? 4 : 3));
522            fn = s-1;
523          }
524          else
525          {
526            *fn = '/';
527          }
528        }
529        else if (*(fn+2) == '/' || *(fn+2) == '\0')
530        {
531          mystrcpy(fn+1, fn+3);
532          fn--;
533        }
534      }
535    }
536  }
537
538#ifdef RESOURCE_DEBUG
539  printf("feCleanUpFile: leaving with =%s=\n", fname);
540#endif
541  return fname;
542}
543
544// remove duplicates dir resp. those which do not exist
545static char* feCleanUpPath(char* path)
546{
547#ifdef RESOURCE_DEBUG
548  printf("feCleanUpPath: entering with: =%s=\n", path);
549#endif
550  if (path == NULL) return path;
551
552  int n_comps = 1, i, j;
553  char* opath = path;
554  char** path_comps;
555
556  for (; *path != '\0'; path++)
557  {
558    if (*path == fePathSep) n_comps++;
559    else if (*path == ';')
560    {
561      *path = fePathSep;
562      n_comps++;
563    }
564  }
565
566  path_comps = (char**) omAlloc(n_comps*sizeof(char*));
567  path_comps[0]=opath;
568  path=opath;
569  i = 1;
570
571  if (i < n_comps)
572  {
573    while (1)
574    {
575      if (*path == fePathSep)
576      {
577        *path = '\0';
578        path_comps[i] = path+1;
579        i++;
580        if (i == n_comps) break;
581      }
582      path++;
583    }
584  }
585
586  for (i=0; i<n_comps; i++)
587    path_comps[i] = feCleanUpFile(path_comps[i]);
588#ifdef RESOURCE_DEBUG
589  PrintS("feCleanUpPath: after CleanUpName: ");
590  for (i=0; i<n_comps; i++)
591    Print("%s:", path_comps[i]);
592  Print("\n");
593#endif
594
595  for (i=0; i<n_comps;)
596  {
597#ifdef RESOURCE_DEBUG
598    if (access(path_comps[i], X_OK | R_OK))
599      Print("feCleanUpPath: remove %d:%s -- can not access\n", i, path_comps[i]);
600#endif
601    if ( ! access(path_comps[i], X_OK | R_OK))
602    {
603      // x- permission is granted -- we assume that it is a dir
604      for (j=0; j<i; j++)
605      {
606        if (strcmp(path_comps[j], path_comps[i]) == 0)
607        {
608          // found a duplicate
609#ifdef RESOURCE_DEBUG
610          Print("feCleanUpPath: remove %d:%s -- equal to %d:%s\n", j, path_comps[j], i, path_comps[i]);
611#endif
612          j = i+1;
613          break;
614        }
615      }
616      if (j == i)
617      {
618        i++;
619        continue;
620      }
621    }
622    // now we can either not access or found a duplicate
623    path_comps[i] = NULL;
624    for (j=i+1; j<n_comps; j++)
625        path_comps[j-1] = path_comps[j];
626    n_comps--;
627  }
628
629
630  // assemble everything again
631  for (path=opath, i=0;i<n_comps-1;i++)
632  {
633    mystrcpy(path, path_comps[i]);
634    path += strlen(path);
635    *path = fePathSep;
636    path++;
637  }
638  if (n_comps)
639  {
640    mystrcpy(path, path_comps[i]);
641  }
642  else
643  {
644    *opath = '\0';
645  }
646  omFree(path_comps);
647#ifdef RESOURCE_DEBUG
648  Print("feCleanUpPath: leaving with path=%s=\n", opath);
649#endif
650  return opath;
651}
652
653// strcpy where source and destination may overlap
654static void mystrcpy(char* d, char* s)
655{
656  assume(d != NULL && s != NULL);
657  while (*s != '\0')
658  {
659    *d = *s;
660    d++;
661    s++;
662  }
663  *d = '\0';
664}
665
666/*****************************************************************
667 *
668 * feSprintf
669 *
670 *****************************************************************/
671static char* feSprintf(char* s, const char* fmt, int warn)
672{
673  char* s_in = s;
674  if (fmt == NULL) return NULL;
675
676  while (*fmt != '\0')
677  {
678    *s = *fmt;
679
680    if (*fmt == '%' && *(fmt + 1) != '\0')
681    {
682      fmt++;
683      char* r = feResource(*fmt, warn);
684      if (r != NULL)
685      {
686        strcpy(s, r);
687        s += strlen(r) - 1;
688      }
689      else
690      {
691        s++;
692        *s = *fmt;
693      }
694    }
695    else if (*fmt == '$' && *(fmt + 1) != '\0')
696    {
697      fmt++;
698      char* v = s + 1;
699      while (*fmt == '_' ||
700             (*fmt >= 'A' && *fmt <= 'Z') ||
701             (*fmt >= 'a' && *fmt <= 'z'))
702      {
703        *v = *fmt;
704        v++;
705        fmt++;
706      }
707      fmt--;
708      *v = '\0';
709      v = getenv(s + 1);
710      if (v != NULL) strcpy(s, v);
711      s += strlen(s) - 1;
712    }
713    s++;
714    fmt++;
715  }
716  *s = '\0';
717  return s_in;
718}
719
720void feStringAppendResources(int warn)
721{
722  int i = 0;
723  char* r;
724  StringAppend("%-10s:\t%s\n", "argv[0]", feArgv0);
725  while (feResourceConfigs[i].key != NULL)
726  {
727    r = feResource(feResourceConfigs[i].key, warn);
728    StringAppend("%-10s:\t%s\n", feResourceConfigs[i].key,
729                 (r != NULL ? r : ""));
730    i++;
731  }
732}
Note: See TracBrowser for help on using the repository browser.