1 /****************************************
2 *  Computer Algebra System SINGULAR     *
3 ****************************************/
4 /*
5 * ABSTRACT: Implementation of option buisness
6 */
7 
8 
9 #include <string.h>
10 
11 #include "kernel/mod2.h"
12 
13 #include "factory/factory.h"
14 
15 #define FE_OPT_STRUCTURE
16 #include "feOpt.h"
17 
18 #if !defined(GENERATE_OPTION_INDEX) && !defined(ESINGULAR) && !defined(TSINGULAR)
19 #include "misc/options.h"
20 #include "misc/sirandom.h"
21 #endif
22 
23 #include "fehelp.h"
24 
25 #ifdef HAVE_FLINT
26 #include <flint/flint.h>
27 #endif
28 
29 const char SHORT_OPTS_STRING[] = "bdhpqstvxec:r:u:";
30 
31 //////////////////////////////////////////////////////////////
32 //
33 // Generation of feOptIndex
34 //
35 #ifdef GENERATE_OPTION_INDEX
36 
37 #include <stdio.h>
38 //#include <unistd.h>
39 //#include <stdlib.h>
main()40 int main()
41 {
42   FILE* fd;
43 #ifdef ESINGULAR
44   fd = fopen("feOptES.xx", "w");
45 #elif defined(TSINGULAR)
46   fd = fopen("feOptTS.xx", "w");
47 #else
48   fd = fopen("feOpt.xx", "w");
49 #endif
50 
51   if (fd == NULL) exit(1);
52 
53   int i = 0;
54 
55   fputs("typedef enum\n{\n", fd);
56 
57   while (feOptSpec[i].name != NULL)
58   {
59     const char* name = feOptSpec[i].name;
60     fputs("FE_OPT_", fd);
61     while (*name != 0)
62     {
63       if (*name == '-')
64       {
65         putc('_', fd);
66       }
67       else if (*name >= 97 && *name <= 122)
68       {
69         putc(*name - 32, fd);
70       }
71       else
72       {
73         putc(*name, fd);
74       }
75       name++;
76     }
77     if (i == 0)
78     {
79       fputs("=0", fd);
80     }
81     i++;
82     fputs(",\n  ", fd);
83   }
84 
85   fprintf(fd, "FE_OPT_UNDEF\n} feOptIndex;\n");
86   fclose(fd);
87 #ifdef ESINGULAR
88   rename("feOptES.xx", "feOptES.inc");
89 #elif defined(TSINGULAR)
90   rename("feOptTS.xx", "feOptTS.inc");
91 #else
92   rename("feOpt.xx", "feOpt.inc");
93 #endif
94   return(0);
95 }
96 
97 #else // ! GENERATE_OPTION_INDEX
98 
99 ///////////////////////////////////////////////////////////////
100 //
101 // Getting Values
102 //
103 
feGetOptIndex(const char * name)104 feOptIndex feGetOptIndex(const char* name)
105 {
106   int opt = 0;
107 
108   while (opt != (int) FE_OPT_UNDEF)
109   {
110     if (strcmp(feOptSpec[opt].name, name) == 0)
111       return (feOptIndex) opt;
112     opt = opt + 1;
113   }
114   return FE_OPT_UNDEF;
115 }
116 
feGetOptIndex(int optc)117 feOptIndex feGetOptIndex(int optc)
118 {
119   int opt = 0;
120 
121   if (optc == LONG_OPTION_RETURN) return FE_OPT_UNDEF;
122 
123   while (opt != (int) FE_OPT_UNDEF)
124   {
125     if (feOptSpec[opt].val == optc)
126       return (feOptIndex) opt;
127     opt = opt + 1;
128   }
129   return FE_OPT_UNDEF;
130 }
131 
132 ///////////////////////////////////////////////////////////////
133 //
134 // Setting Values
135 //
136 //
137 // Return: NULL -- everything ok
138 //         "error-string" on error
139 #if !defined(ESINGULAR) && !defined(TSINGULAR)
140 
141 #include "omalloc/omalloc.h"
142 #include "resources/feResource.h"
143 #include "kernel/oswrapper/feread.h"
144 #include "kernel/oswrapper/timer.h"
145 
146 #include "ipshell.h"
147 #include "tok.h"
148 #include "sdb.h"
149 #include "cntrlc.h"
150 
151 #include <errno.h>
152 
153 static const char* feOptAction(feOptIndex opt);
feSetOptValue(feOptIndex opt,char * optarg)154 const char* feSetOptValue(feOptIndex opt, char* optarg)
155 {
156   if (opt == FE_OPT_UNDEF) return "option undefined";
157 
158   if (feOptSpec[opt].type != feOptUntyped)
159   {
160     if (feOptSpec[opt].type != feOptString)
161     {
162       if (optarg != NULL)
163       {
164         errno = 0;
165         feOptSpec[opt].value = (void*) strtol(optarg, NULL, 10);
166         if (errno) return "invalid integer argument";
167       }
168       else
169       {
170         feOptSpec[opt].value = (void*) 0;
171       }
172     }
173     else
174     {
175       assume(feOptSpec[opt].type == feOptString);
176       if (feOptSpec[opt].set && feOptSpec[opt].value != NULL)
177         omFree(feOptSpec[opt].value);
178       if (optarg != NULL)
179         feOptSpec[opt].value = omStrDup(optarg);
180       else
181         feOptSpec[opt].value = NULL;
182       feOptSpec[opt].set = 1;
183     }
184   }
185   return feOptAction(opt);
186 }
187 
feSetOptValue(feOptIndex opt,int optarg)188 const char* feSetOptValue(feOptIndex opt, int optarg)
189 {
190   if (opt == FE_OPT_UNDEF) return "option undefined";
191 
192   if (feOptSpec[opt].type != feOptUntyped)
193   {
194     if (feOptSpec[opt].type == feOptString)
195       return "option value needs to be an integer";
196 
197     feOptSpec[opt].value = (void*)(long) optarg;
198   }
199   return feOptAction(opt);
200 }
201 
feOptAction(feOptIndex opt)202 static const char* feOptAction(feOptIndex opt)
203 {
204   // do some special actions
205   switch(opt)
206   {
207       case FE_OPT_BATCH:
208         if (feOptSpec[FE_OPT_BATCH].value)
209           fe_fgets_stdin=fe_fgets_dummy;
210         return NULL;
211 
212       case FE_OPT_HELP:
213         feOptHelp(feArgv0);
214         return NULL;
215 
216       case FE_OPT_PROFILE:
217          traceit=1024;
218          return NULL;
219 
220       case FE_OPT_QUIET:
221         if (feOptSpec[FE_OPT_QUIET].value)
222           si_opt_2 &= ~(Sy_bit(0)|Sy_bit(V_LOAD_LIB));
223         else
224           si_opt_2 |= Sy_bit(V_LOAD_LIB)|Sy_bit(0);
225         return NULL;
226 
227       case FE_OPT_NO_TTY:
228         if (feOptSpec[FE_OPT_NO_TTY].value)
229           fe_fgets_stdin=fe_fgets;
230         return NULL;
231 
232       case FE_OPT_SDB:
233       #ifdef HAVE_SDB
234         if (feOptSpec[FE_OPT_SDB].value)
235           sdb_flags = 1;
236         else
237           sdb_flags = 0;
238       #endif
239         return NULL;
240 
241       case FE_OPT_VERSION:
242         {
243         char *s=versionString();
244         printf("%s",s);
245         omFree(s);
246         return NULL;
247         }
248 
249       case FE_OPT_ECHO:
250         si_echo = (int) ((long)(feOptSpec[FE_OPT_ECHO].value));
251         if (si_echo < 0 || si_echo > 9)
252           return "argument of option is not in valid range 0..9";
253         return NULL;
254 
255       case FE_OPT_RANDOM:
256         siRandomStart = (unsigned int) ((unsigned long)
257                                           (feOptSpec[FE_OPT_RANDOM].value));
258         siSeed=siRandomStart;
259         factoryseed(siRandomStart);
260         return NULL;
261 
262       case FE_OPT_EMACS:
263         if (feOptSpec[FE_OPT_EMACS].value)
264         {
265           // print EmacsDir and InfoFile so that Emacs
266           // mode can pcik it up
267           Warn("EmacsDir: %s", (feResource('e' /*"EmacsDir"*/) != NULL ?
268                                 feResource('e' /*"EmacsDir"*/) : ""));
269           Warn("InfoFile: %s", (feResource('i' /*"InfoFile"*/) != NULL ?
270                                 feResource('i' /*"InfoFile"*/) : ""));
271         }
272         return NULL;
273 
274       case FE_OPT_NO_WARN:
275         if (feOptSpec[FE_OPT_NO_WARN].value)
276           feWarn = FALSE;
277         else
278           feWarn = TRUE;
279         return NULL;
280 
281       case FE_OPT_NO_OUT:
282         if (feOptSpec[FE_OPT_NO_OUT].value)
283           feOut = FALSE;
284         else
285           feOut = TRUE;
286         return NULL;
287 
288       case FE_OPT_MIN_TIME:
289       {
290         double mintime = atof((char*) feOptSpec[FE_OPT_MIN_TIME].value);
291         if (mintime <= 0) return "invalid float argument";
292         SetMinDisplayTime(mintime);
293         return NULL;
294       }
295 
296       case FE_OPT_BROWSER:
297         feHelpBrowser((char*) feOptSpec[FE_OPT_BROWSER].value, 1);
298 
299       case FE_OPT_TICKS_PER_SEC:
300       {
301         int ticks = (int) ((long)(feOptSpec[FE_OPT_TICKS_PER_SEC].value));
302         if (ticks <= 0)
303           return "integer argument must be larger than 0";
304         SetTimerResolution(ticks);
305         return NULL;
306       }
307 
308       case FE_OPT_DUMP_VERSIONTUPLE:
309       {
310         feOptDumpVersionTuple();
311         return NULL;
312       }
313 
314       #ifdef HAVE_FLINT
315       #if __FLINT_RELEASE >= 20503
316       case FE_OPT_FLINT_THREADS:
317       {
318         slong nthreads = (slong)feOptSpec[FE_OPT_FLINT_THREADS].value;
319         nthreads = FLINT_MAX(nthreads, WORD(1));
320         flint_set_num_threads(nthreads);
321         int * cpu_affinities = new int[nthreads];
322         for (slong i = 0; i < nthreads; i++)
323           cpu_affinities[i] = (int)i;
324         flint_set_thread_affinity(cpu_affinities, nthreads);
325         delete[] cpu_affinities;
326         return NULL;
327       }
328       #endif
329       #endif
330 
331       default:
332         return NULL;
333   }
334 }
335 
336 // Prints usage message
fePrintOptValues()337 void fePrintOptValues()
338 {
339   int i = 0;
340 
341   while (feOptSpec[i].name != 0)
342   {
343     if (feOptSpec[i].help != NULL && feOptSpec[i].type != feOptUntyped
344 #ifndef SING_NDEBUG
345         && *(feOptSpec[i].help) != '/'
346 #endif
347         )
348     {
349       if (feOptSpec[i].type == feOptString)
350       {
351         if (feOptSpec[i].value == NULL)
352         {
353           Print("// --%-15s\n", feOptSpec[i].name);
354         }
355         else
356         {
357           Print("// --%-15s \"%s\"\n", feOptSpec[i].name, (char*) feOptSpec[i].value);
358         }
359       }
360       else
361       {
362         Print("// --%-15s %d\n", feOptSpec[i].name, (int)(long)feOptSpec[i].value);
363       }
364     }
365     i++;
366   }
367 }
368 
369 #endif // ! ESingular
370 
371 // Prints help message
feOptHelp(const char * name)372 void feOptHelp(const char* name)
373 {
374   int i = 0;
375   char tmp[60];
376 #if defined(ESINGULAR)
377   printf("ESingular starts up Singular within emacs;\n");
378 #elif defined(TSINGULAR)
379   printf("TSingular starts up Singular within a terminal window;\n");
380 #endif
381   printf("Singular is a Computer Algebra System (CAS) for Polynomial Computations.\n");
382   printf("Usage: %s [options] [file1 [file2 ...]]\n", name);
383   printf("Options:\n");
384 
385   while (feOptSpec[i].name != 0)
386   {
387     if (feOptSpec[i].help != NULL
388 #ifdef SING_NDEBUG
389         && *(feOptSpec[i].help) != '/'
390 #endif
391         )
392     {
393       if (feOptSpec[i].has_arg > 0)
394       {
395         if  (feOptSpec[i].has_arg > 1)
396           sprintf(tmp, "%s[=%s]", feOptSpec[i].name, feOptSpec[i].arg_name);
397         else
398           sprintf(tmp, "%s=%s", feOptSpec[i].name, feOptSpec[i].arg_name);
399 
400         printf(" %c%c --%-20s %s\n",
401                (feOptSpec[i].val != LONG_OPTION_RETURN ? '-' : ' '),
402                (feOptSpec[i].val != LONG_OPTION_RETURN ? feOptSpec[i].val : ' '),
403                tmp,
404                feOptSpec[i].help);
405       }
406       else
407       {
408         printf(" %c%c --%-20s %s\n",
409                (feOptSpec[i].val != LONG_OPTION_RETURN ? '-' : ' '),
410                (feOptSpec[i].val != LONG_OPTION_RETURN ? feOptSpec[i].val : ' '),
411                feOptSpec[i].name,
412                feOptSpec[i].help);
413       }
414     }
415     i++;
416   }
417 
418   printf("\nFor more information, type `help;' from within Singular or visit\n");
419   printf("https://www.singular.uni-kl.de or consult the\n");
420   printf("Singular manual (available as on-line info or html manual).\n");
421 }
422 
feOptDumpVersionTuple(void)423 void feOptDumpVersionTuple(void)
424 {
425   printf("%s\n",VERSION);
426 }
427 
428 #endif // GENERATE_OPTION_INDEX
429