1 /****************************************
2 *  Computer Algebra System SINGULAR     *
3 ****************************************/
4 /*
5 * ABSTRACT: Esingular main file
6 */
7 
8 
9 
10 
11 #include "kernel/mod2.h"
12 #include "omalloc/omalloc.h"
13 #include "resources/feResource.h"
14 #include "Singular/feOpt.h"
15 
16 #ifdef __CYGWIN__
17 #define BOOLEAN boolean
18 #endif
19 
20 #include <unistd.h>
21 
22 #ifdef DecAlpha_OSF1
23 #define _BSD
24 #endif
25 
26 #include <stdarg.h>
27 
28 #ifdef __CYGWIN__
29 #include <windows.h>
30 #endif
31 
32 
33 #if !defined(TSINGULAR) && !defined(ESINGULAR)
34 #define ESINGULAR
35 #endif
36 
37 #ifdef system
38 #undef system
39 #endif
40 
41 #ifndef FALSE
42 #define FALSE 0
43 #endif
44 #ifndef TRUE
45 #define TRUE 1
46 #endif
47 #ifndef MAXPATHLEN
48 #define MAXPATHLEN 1024
49 #endif
50 #  define  DIR_SEP '/'
51 #  define  DIR_SEPP "/"
52 #  define  UP_DIR ".."
53 
54 #ifndef __CYGWIN__
error(const char * fmt,...)55 void error(const char *fmt, ...)
56 {
57   va_list ap;
58   va_start(ap, fmt);
59   vfprintf(stderr, fmt, ap);
60 }
61 #else
error(const char * fmt,...)62 void error(const char* fmt, ...)
63 {
64    char buf[4096];
65    int j =0;
66    va_list args;
67    va_start(args, fmt);
68    j =   sprintf(buf,    "");
69    j += vsprintf(buf + j,fmt,args);
70    j +=  sprintf(buf + j,"\n");
71    va_end(args);
72    MessageBox(NULL, buf, "ESingular.exe", MB_ICONSTOP);
73    exit(1);
74 }
75 #endif
76 
77 #define Warn  error
78 #define WarnS error
79 #define StringAppend printf
80 #define Print error
81 
82 #define feReportBug(s) fePrintReportBug(s, __FILE__, __LINE__)
fePrintReportBug(char * msg,char * file,int line)83 void fePrintReportBug(char* msg, char* file, int line)
84 {
85   error("YOU HAVE FOUND A BUG IN SINGULAR.\n"
86 "Please, email the following output to singular@mathematik.uni-kl.de\n"
87 "Bug occurred at %s:%d\n"
88 "Message: %s\n"
89 "Version: " S_UNAME VERSION __DATE__ __TIME__,
90         file, line, msg);
91 
92 }
93 
mainUsage()94 void mainUsage()
95 {
96   error( "Use `%s --help' for a complete list of options\n", feArgv0);
97 }
98 
99 extern char* feResourceDefault(const char id);
100 extern char* feResourceDefault(const char* key);
101 
102 
main(int argc,char ** argv)103 int main(int argc, char** argv)
104 {
105   char* singular = NULL;
106   char* emacs = NULL;
107 #ifndef TSINGULAR
108   char* emacs_dir = NULL;
109   char* emacs_load = NULL;
110   char cwd[MAXPATHLEN];
111 #endif
112   int no_emacs_call = 0;
113 
114   // parse-cmdline options
115 
116   feInitResources(argv[0]);
117   feResource('S');
118   feResource('b');
119   feResource('r');
120 
121   int optc, option_index;
122 
123   while ((optc = fe_getopt_long(argc, argv, SHORT_OPTS_STRING,
124                                 feOptSpec, &option_index))
125         != EOF)
126   {
127     switch(optc)
128     {
129       case 'h':
130           extern void feOptHelp(const char* name);
131 
132           feOptHelp(feArgv0);
133           exit(0);
134           break;
135       case '?':
136       case ':':
137       case '\0':
138           mainUsage();
139           exit(1);
140 
141       case  LONG_OPTION_RETURN:
142         {
143           switch(option_index)
144           {
145 #ifdef TSINGULAR
146               case FE_OPT_XTERM:
147                 emacs = fe_optarg;
148               break;
149 #else
150               case FE_OPT_EMACS:
151                 emacs = fe_optarg;
152                 break;
153 
154               case FE_OPT_EMACS_DIR:
155                 emacs_dir = fe_optarg;
156                 break;
157 
158               case FE_OPT_EMACS_LOAD:
159                 emacs_load = fe_optarg;
160                 break;
161 #endif
162               case FE_OPT_SINGULAR:
163                 singular = fe_optarg;
164                 break;
165 
166               case FE_OPT_NO_CALL:
167                 no_emacs_call = 1;
168                 break;
169 
170               case FE_OPT_DUMP_VERSIONTUPLE:
171                 feOptDumpVersionTuple();
172                 exit(0);
173                 break;
174 
175               default:
176                 goto NEXT;
177           }
178           // delete options from option-list
179           if (fe_optind > 2 && *argv[fe_optind-1] != '-' &&
180               fe_optarg != NULL && feOptSpec[option_index].has_arg)
181           {
182             argv[fe_optind-2] = NULL;
183           }
184           argv[fe_optind-1] = NULL;
185         }
186     }
187     NEXT:{}
188   }
189 
190   int i, length = 0;
191   char* syscall;
192   for (i=1; i<argc; i++)
193   {
194     if (argv[i] != NULL) length += strlen(argv[i]) + 3;
195   }
196 
197 #ifdef TSINGULAR
198   if (emacs == NULL) emacs = feResource('X', 0);
199   if (emacs == NULL)
200   {
201   #ifdef __CYGWIN__
202     error( "Error: Can't find rxvt program. \n Expected it at %s\n Specify alternative with --rxvt=PROGRAM option,\n or set RXVT environment variable to the name of the program to use as rxvt.\n",
203   #else
204     error( "Error: Can't find xterm program. \n Expected it at %s\n Specify alternative with --xterm=PROGRAM option,\n or set XTERM environment variable to the name of the program to use as xterm.\n",
205   #endif
206            feResourceDefault('X'));
207     mainUsage();
208     exit(1);
209   }
210 
211   if (singular == NULL) singular = feResource("SingularXterm", 0);
212   if (singular == NULL)
213   {
214     error( "Error: Can't find singular executable.\n Expected it at %s\n Specify with --singular option,\n or set TSINGULAR_SINGULAR environment variable.\n",
215             feResourceDefault("SingularXterm"));
216     mainUsage();
217     exit(1);
218   }
219 
220 #ifdef __CYGWIN__
221 #define EXTRA_XTERM_ARGS "+vb -sl 2000 -fb Courier-bold-12 -tn xterm -cr Red3"
222 #else
223 #define EXTRA_XTERM_ARGS ""
224 #endif
225 
226   syscall = (char*) omAlloc(strlen(emacs) +
227                                  strlen(singular) +
228                                  length + 300);
229   sprintf(syscall, "%s %s -e %s ", emacs, EXTRA_XTERM_ARGS, singular);
230 
231   for (i=1; i<argc; i++)
232   {
233     if (argv[i] != NULL)
234     {
235       strcat(syscall, " ");
236       strcat(syscall, argv[i]);
237     }
238   }
239 #else
240   // make sure  emacs, singular, emacs_dir, emacs_load are set
241   if (emacs == NULL) emacs = feResource("xemacs", 0);
242   if (emacs == NULL) emacs = feResource("emacs", 0);
243   if (emacs == NULL)
244   {
245     error( "Error: Can't find emacs or xemacs executable. \n Expected it at %s or %s\n Specify alternative with --emacs option,\n or set ESINGULAR_EMACS environment variable.\n",
246             feResourceDefault("emacs"), feResourceDefault("xemacs"));
247     mainUsage();
248     exit(1);
249   }
250 
251   if (singular == NULL) singular = feResource("SingularEmacs", 0);
252   if (singular == NULL)
253   {
254     error( "Error: Can't find singular executable.\n Expected it at %s\n Specify with --singular option,\n or set ESINGULAR_SINGULAR environment variable.\n",
255             feResourceDefault("SingularEmacs"));
256     mainUsage();
257     exit(1);
258   }
259 
260   if (emacs_dir == NULL) emacs_dir = feResource("EmacsDir", 0);
261   if (emacs_dir == NULL)
262   {
263     error( "Error: Can't find emacs directory for Singular lisp files. \n Expected it at %s\n Specify with --emacs_dir option,\n or set ESINGULAR_EMACS_DIR environment variable.\n",
264             feResourceDefault("EmacsDir"));
265     mainUsage();
266     exit(1);
267   }
268 
269   if (emacs_load == NULL)
270   {
271     // look into env variable
272     emacs_load = getenv("ESINGULAR_EMACS_LOAD");
273     if (access(emacs_load, R_OK))
274     {
275       // look in home-dir
276       emacs_load = getenv("HOME");
277 #ifdef __CYGWIN__
278       if ((emacs_load==NULL)||(!access(emacs_load,X_OK)))
279         emacs_load = getenv("SINGHOME");
280 #endif
281       sprintf(cwd, "%s/.emacs-singular", emacs_load);
282       if (! access(cwd, R_OK))
283       {
284         emacs_load = omStrDup(cwd);
285       }
286       else
287       {
288         // try with resources
289         emacs_load = feResource("EmacsLoad", 0);
290         if (emacs_load == NULL)
291         {
292           error( "Error: Can't find emacs load file for Singular mode. \n Expected it at %s\n Specify with --emacs_load option,\n or set ESINGULAR_EMACS_LOAD environment variable,\n or put file '.emacs-singular' in your home directory.\n",
293                   feResourceDefault("EmacsLoad"));
294           mainUsage();
295           exit(1);
296         }
297       }
298     }
299   }
300 
301   syscall = (char*) omAlloc(strlen(emacs) +
302                            strlen(singular) +
303                            strlen(emacs_dir) +
304                            strlen(emacs_load) +
305                            length + 300);
306   const char* prefix = "--";
307   if (strstr(emacs, "xemacs") || strstr(emacs, "Xemacs") || strstr(emacs, "XEMACS"))
308     prefix = "-";
309   getcwd(cwd, MAXPATHLEN);
310   // append / at the end of cwd
311   if (cwd[strlen(cwd)-1] != '/') strcat(cwd, "/");
312 
313   // Note: option -no-init-file should be equivalent to -q. Anyhow,
314   // xemacs-20.4 sometimes crashed on startup when using -q. Don�t know why.
315   sprintf(syscall, "%s %sno-init-file %seval '(progn (setq singular-emacs-home-directory \"%s\") (load-file \"%s\") (singular-other \"%s\" \"%s\" (list ",
316           emacs, prefix, prefix, emacs_dir, emacs_load,
317           singular, cwd);
318 
319 
320   for (i=1; i<argc; i++)
321   {
322     if (argv[i] != NULL)
323     {
324       strcat(syscall, "\"");
325       strcat(syscall, argv[i]);
326       strcat(syscall, "\" ");
327     }
328   }
329   strcat(syscall, ") \"singular\"))'");
330 #endif
331 
332   if (no_emacs_call)
333   {
334     printf("%s\n", syscall);
335   }
336   else
337   {
338     if (system(syscall) != 0)
339     {
340       error( "Error: Execution of\n%s\n", syscall);
341       mainUsage();
342       exit(1);
343     }
344   }
345 }
346 
347 
348