Update the changelog
[opencv] / apps / Hawk / CVEiCL / EiC / src / starteic.c
1 /* starteic.c
2  *
3  *      (C) Copyright Dec 31 1995, Edmond J. Breen.
4  *                 ALL RIGHTS RESERVED.
5  * This code may be copied for personal, non-profit use only.
6  *
7  */
8
9 /* In accordance with the practice of fair use, I hereby acknowledge
10  * that:
11  */
12 static char *PlaugerStr_=
13 "Portions of this work are derived from the Standard C library, (C), 1992 by P.J. Plauger, published by Prentice-Hall and are used with permission.";
14
15
16 /* Modified by Intel OpenCV team. The runEiC function has been changed 
17    in order to catch exceptions thrown by parser and interpreter. */
18
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <ctype.h>
24 #include <signal.h>
25 #include <setjmp.h>
26 #include <stdarg.h>
27
28 #include "MachSet.h"
29 #include "global.h"
30 #include "lexer.h"
31 #include "typemod.h"
32 #include "func.h"
33 #include "xalloc.h"
34 #include "preproc.h"
35 #include "emitter.h"
36 #include "parser.h"
37 #include "symbol.h"
38 #include "error.h"
39 #include "reset.h"
40
41 #if __GLIBC__ >=  2
42 #define signal sysv_signal
43 void (*sysv_signal(int sig, void (*func)(int a))) (int a);
44 #endif
45
46
47 extern void EiC_interpret(environ_t * env);
48 extern  char *EiC_prolineString(char *str);
49
50
51 #define HERE printf("%s %d\n",__FILE__,__LINE__)
52
53 char *Version =
54 "*************************************************************************\n"
55 "EiC V4.3.1 - Copyright (c) 1995 to 2000,"
56 " by Edmond J. Breen\n"
57 "EiC comes `as is' and with ABSOLUTELY NO WARRANTY OF MERCHANTIBILITY AND\n"
58 " FITNESS OF PURPOSE\n"
59 "*************************************************************************\n"
60 ;
61     
62
63 environ_t *EiC_ENV;
64
65 size_t EiC_ENV_NextEntryNum()
66 {
67     return EiC_stab_NextEntryNum(&EiC_ENV->stab);
68 }
69
70 void EiC_ENV_CleanUp(size_t bot)
71 {
72     EiC_stab_CleanUp(&EiC_ENV->stab,bot);
73 }
74
75 /*END STRING TABLE ROUTINES*/
76
77
78 void EiC_reset_env_pointers(token_t * e1, int bp)
79 {
80     EiC_ENV->lsp = bp;
81 }
82
83
84 void EiC_markENV(char mark)
85 {
86     EiC_stab_Mark(&EiC_ENV->stab,mark);
87 }       
88
89 void free_env_code(void)
90 {
91     unsigned int i;
92     InsT_t *inst;
93
94     code_t *c = &EiC_ENV->CODE;
95
96     while(c->prev) /* find start point */
97         c = (code_t*)c->prev;
98         
99      inst = c->inst;
100      /* rem free up other info also */
101     for (i = 0; i < c->nextinst; i++, inst++)
102         if (inst->opcode == jmptab) {
103             eicstack_t *s;
104             s = inst->val.p.p;
105             xfree(s->val);
106             xfree(s);
107         } else if (inst->opcode == assigntype) {
108             EiC_freetype(inst->val.p.p);
109
110         } else if(inst->opcode == halt) {
111                 EiC_freetype(inst->val.p.p);
112         }
113
114     EiC_freecode(c);
115     EiC_ENV->CODE = *c;
116 }
117
118 void EiC_SaveGlobalString(ptr_t *s)
119 {
120     int len = (char*)s->ep - (char*)s->sp;
121     s->sp = s->p = EiC_stab_SaveString(&EiC_ENV->stab,s->p);
122     s->ep = (char*)s->p + len;
123 }
124
125 /* signal handling  routines 
126  *
127  * If a new signal hangling rountines gets added
128  * make sure it gets also added in module/stdClib/src/signal.c
129  *
130  */
131
132 jmp_buf env;
133 static int jmpOn = 0;
134 #define Err_   1
135 #define Exit_  2
136
137 char * EiC_CurrentFile =NULL;
138 unsigned int  EiC_CurrentLine = -1;
139
140 #define errStr(x)   if(EiC_CurrentFile) EiC_error("\n" x ", file %s, line %d\n",EiC_CurrentFile,EiC_CurrentLine)
141 #define eic_disaster() EiC_error("exit EiC\n");exit(1)
142
143
144
145 size_t fopen_NextEntryNum(void);
146 void _ffexit(size_t);
147
148 void EiC_exit_call(int i)
149 {
150 #ifndef _SEIC_
151     size_t fopen_entry = fopen_NextEntryNum(); 
152 #if defined(WIN32) || defined(_DJGPP)
153     signal(SIGTERM, EiC_exit_call);
154 #else
155     signal(SIGUSR1, EiC_exit_call);
156 #endif
157     _ffexit(fopen_entry);
158     if(jmpOn && jmpOn++ <= 1)
159       longjmp(env,Exit_);
160     else
161         eic_disaster();
162 #else
163     eic_disaster();
164 #endif
165 }
166
167 void  EiC_bus_err(int i)
168 {
169
170 #if defined(WIN32) || defined(_DJGPP)
171     signal(SIGABRT,EiC_bus_err);
172 #else
173     signal(SIGBUS, EiC_bus_err);
174 #endif
175     errStr("EiC bus error trapped");
176     if(jmpOn && jmpOn++ <= 1)
177       longjmp(env,Err_);
178     else
179       eic_disaster();
180 }
181 void  EiC_ill_oper(int i)
182 {
183     signal(SIGILL, EiC_ill_oper);
184     errStr("EiC illegal operation attempted\n");
185     if(jmpOn && jmpOn++ <= 1)
186       longjmp(env,Err_);
187     else
188       eic_disaster();
189 }
190 void EiC_stor_access(int i)
191 {
192     signal(SIGSEGV, EiC_stor_access);
193     errStr("EiC illegal storage access");
194     if(jmpOn && jmpOn++ <= 1)  {
195         longjmp(env,Err_);
196     } else
197         eic_disaster();
198 }
199
200 void EiC_float_err(int i)
201 {
202     signal(SIGFPE, EiC_float_err);
203     errStr("EiC maths  exception");
204     if(jmpOn && jmpOn++ <= 1)
205       longjmp(env,Err_);
206     else
207       eic_disaster();
208 }
209
210 void EiC_term_int(int i)
211 {
212     signal(SIGINT, EiC_term_int);
213     errStr("EiC interrupted");
214     if(jmpOn && jmpOn++ <= 1)
215       longjmp(env,Err_);
216     else
217       eic_disaster();
218 }
219
220 FILE *EiChist = NULL;
221 extern int EiC_verboseON, EiC_SHOWLINE, EiC_traceON, EiC_TIMER,
222     EiC_interActive, EiC_showIncludes;
223 int silent = 0, HistoryFile = 1;
224 int StartUpH = 1;
225 int reStart = 0, prompt = 0;
226 int EiC_Interact = 1;
227 int ScriptMode = 0;
228 static int FREE_G_STRING = 1;
229
230
231 void usage(void)
232 {
233     puts("\n\t\tEiC\n"
234          " An Extensible Interactive C interpreter\n"
235          " To start eic, type eic.\n"
236          " To exit eic, type :exit.\n"
237          "\n Usage:\n"
238          "\teic  [-Ipath] [-Dname[=var]] -[hHvVcCrR]  [[file] [fileargs]]\n"
239          " Options:\n"
240          "   C preprocessor directives:\n"
241          "\t-Ipath      search for include files in path\n"
242          "\t-Dname      define a symbolic name to the value 1\n"
243          "\t-Dname=var  define a symbolic name to the value var\n"
244          "\t            Note, there is no spaces allowed\n"
245          "   EiC directives:\n"
246          "\t-h -H       causes this usage to be displayed\n"
247          "\t-v -V       print EiC's Log information\n"
248          "\t-p          showline\n"
249          "\t-P          show path of include files\n"
250          "\t-t -T       turns trace on\n"
251          "\t-c -C       turns timer on\n"
252          "\t-e          echo HTML mode\n" 
253          "\t-r          restart EiC. Causes EiC to be re initiated\n"
254          "\t               from the contents of EiChist.lst file\n"
255          "\t-R          same as `r', but prompts the user to accept\n"
256          "\t               or reject each input line first\n" 
257          "\t-s -S       run silently\n"
258          "\t-f          run in script mode\n"
259          "\t-n          no history file\n"
260          "\t-N          don't use any startup.h files\n"
261          "\t-A          Non-interactive-mode\n"
262          "\tfile        EiC will execute `file' and then stop; for example:\n"
263          "\t              % eic foo.c \n"
264          "\tfileargs    command line arguments, which get passed onto file\n"
265          );
266     exit(1);
267 }
268
269 int do_sw_commands(char *cp)
270 {
271     while(*cp) {
272         switch(*cp++) {
273         case 'D': dodefine(cp);  return 1;
274         case 'I': EiC_insertpath(cp); return 1;
275         case '\?':
276         case 'h':
277         case 'H': usage();
278         case 'c':
279         case 'C': EiC_TIMER = 1; break;
280         #ifndef NO_HTML
281         case 'e':
282             /* connect stderr to stdout */
283             dup2(1,2); 
284             /* setup stdout to behave like stderr */
285             if(setvbuf(stdout,NULL,_IONBF,0) != 0)
286                 EiC_error("failed to setup stdout\n");
287             /* inform the browser */
288             puts("Content-type: text/plain\n\n");
289             break;
290         #endif
291         case 'v':
292         case 'V': puts(Version); exit(1);
293
294         case 'R': prompt = 1;
295         case 'r': reStart = 1;  break;
296
297         case 's': 
298         case 'S': silent = 1; break; 
299
300         case 'f': ScriptMode = 1; break;
301         case 'p': EiC_SHOWLINE = 1; break;
302         case 'P': EiC_showIncludes = 1; break;
303         case 't':
304         case 'T': EiC_traceON = 1; break;
305         case 'n': HistoryFile = 0; break;
306         case 'N': StartUpH = 0; break;
307         case 'A': EiC_Interact = 0; break;
308         default:
309             while(isspace(*cp)) cp++;
310             if(*cp == '-')  /* assume script mode */
311                 while(isspace(*++cp));
312             else if(*cp)  /* catch for lines ending with whitespace */
313                 return 0;
314         }
315     }
316     return 1;
317 }
318
319
320
321 void EiC_save_history(FILE *fp, int from);
322
323 extern int EiC_verboseON;
324
325 int EiC_Include_file(char *, int);
326 void EiC_marksyms(char);
327     
328 char *inbuf;
329 extern char *EiC_nextproline();
330 extern int EiC_listcodeON, EiC_interpON,EiC_memdumpON;
331 extern unsigned long EiC_tot_memory;
332 extern size_t EiC_tot_alloc;
333
334 void do_displays()
335 {
336     if(EiC_verboseON)
337         printf("\ninstr = %d sARsize = %d  lsp = %d aARsize  = %d\n"
338                "EiC_tot_alloc = %lu EiC_tot_memory = %lu\n",
339                EiC_ENV->CODE.nextinst,
340                EiC_ENV->ARsize,
341                EiC_ENV->lsp,
342                EiC_ENV->LARsize,
343                (unsigned long)EiC_tot_alloc,
344                EiC_tot_memory);
345     EiC_listcode(&EiC_ENV->CODE);
346 }
347
348 void runEiC()
349 {
350     void EiC_remTempories(void);
351     void EiC_peephole(code_t *c);
352     int EiC_getHistLineNo(), hfrom = 0;
353
354     /* Hawk start change */
355         EiC_ParseError = 0;
356     /* Hawk change */
357
358     /* Hawk start change */
359     __try {
360     /* Hawk change */
361     switch(setjmp(env)) {
362         case 0:
363             jmpOn = 1;
364
365             EiCp_initiateReset();
366
367 #ifndef NO_HISTORY
368             hfrom = EiC_getHistLineNo();
369 #endif
370             inbuf = EiC_nextproline();
371
372             EiC_initlex(inbuf);
373             EiC_initparser();
374             EiC_parse(EiC_ENV);
375             EiC_peephole(&getenvcode(EiC_ENV));
376         
377             if(EiC_listcodeON)
378                 do_displays();
379             if (EiC_ENV->CODE.nextinst && EiC_interpON && !EiC_ParseError)
380                 EiC_interpret(EiC_ENV);
381             break;
382         
383         default:
384             EiC_messageDisplay("EiC reports an unRecognised jmp condition in starteic.c"); 
385         case Err_:
386             EiC_ParseError = 1;
387             break;
388         case Exit_:
389             EiC_messageDisplay("Exit called: force clean up!\n");
390             EiC_ParseError = 1;
391             break;
392
393             
394     }
395     /* Hawk start change */
396     } __finally {
397     /* Hawk change */
398
399     if (EiC_errs) 
400         EiC_clear_err_msgs();
401     
402     if(FREE_G_STRING)
403         EiC_xfreemark(eicgstring);
404     free_env_code();
405     EiC_remTempories();
406     
407     if(EiC_ParseError) {
408
409         if(EiC_ENV->lsp != 0) {
410             EiC_messageDisplay("EiC::Reset Local Stack Pointer\n");
411             EiC_ENV->lsp = 0;
412         }
413         /*
414         if(EiC_ENV->ARgar.n)
415         xmark(EiC_ENV->ARgar.val,eicstay);
416         */
417         
418         EiCp_Reset(1);
419
420     /* Hawk start change */
421 //      EiC_ParseError = 0;
422     /* Hawk change */
423     } else { 
424
425 #ifndef NO_HISTORY
426         if(EiChist)
427             EiC_save_history(EiChist,hfrom);
428 #endif
429     }
430
431     if(EiC_memdumpON) {
432         EiC_marksyms(NON_LEAK);
433         if(EiC_verboseON)
434             printf("--- XMEM DUMP\n");
435         xdumpnonmark("eicxdump", NON_LEAK);
436     }
437     }
438 }
439 #define FORMAT1 "\n#ifdef _STDLIBH\nexit(main());\n"\
440                  "#else\nmain();\n#endif\n"
441
442 #define FORMAT2   "\n"\
443           "#ifdef _STDLIBH\n"\
444           "exit(main(_Argc,_Argv));\n"\
445           "#else\n"\
446           "main(_Argc,_Argv);\n"\
447           "#endif\n"
448
449 /*
450 #define FORMAT3   "\n"\
451           "#ifdef _STDLIBH\n"\
452           "exit(main(_Argc,_Argv,_Envp));\n"\
453           "#else\n"\
454           "main(_Argc,_Argv,_Envp);\n"\
455           "#endif\n"
456 */
457
458 int doEntry()
459 {
460     func_t *F;
461     symentry_t *sym;
462     sym = EiC_lookup(stand_tab,"main");
463
464     if(!sym) {
465         if(!ScriptMode) 
466             EiC_messageDisplay("Error: Missing `main'\n");
467         return 0;
468     }
469     if(sym) {
470         if(EiC_gettype(sym->type) != t_func) {
471             EiC_messageDisplay("Error: `main' NOT DECLARED as a function\n");
472             return 0;
473         }
474         /* check return type of main */
475         if(EiC_gettype(nextType(sym->type)) != t_int) {
476             EiC_messageDisplay("Error: function `main' MUST return an `int' type\n");
477             return 0;
478         }
479     
480         /* get number of arguments */
481         F = EiC_getInf(sym->type);
482         if(getFNp(F) <= 1)  /* allow for void argument */
483             EiC_prolineString(FORMAT1);
484         else if(getFNp(F) <= 2)
485             EiC_prolineString(FORMAT2);
486         else
487             EiC_messageDisplay("Error: too many arguments being "
488                                "passed  to `main'\n");
489            /*EiC_prolineString(FORMAT3);*/
490     }
491     return 1;
492 }
493
494 char * doargs(int argc, char **argv)
495 {
496     int i,sz;
497     char buf[51];
498     char *p;
499     
500     sprintf(buf,"int _Argc = %d;char *_Argv[] = {",argc);
501
502     /* get size of string needed */
503     sz = strlen(buf);
504     for(i=0;i<argc;++i)
505         sz += strlen(argv[i]) + 3; /* 3  comma + quotes */
506     /* needs to be NULL terminated */
507     sz += strlen("(void*)0};") + 2; /* 2 for NULL */
508
509     p = xmalloc(sz);
510
511     *p ='\0';
512     strcat(p,buf);
513     for(i=0;i<argc;++i) {
514         strcat(p,"\"");
515         strcat(p,argv[i]);
516         strcat(p,"\",");
517     }
518     strcat(p,"(void*)0};");
519     return p;
520
521 }
522
523 void EiC_parseString(char * fmt,...)
524 {
525
526   code_t code;
527   char *str;
528   int h = EiC_interActive;
529   int gs = FREE_G_STRING;
530   int len;
531
532   /*  unsigned sp;*/
533
534   va_list args;
535   va_start(args,fmt);
536
537   FREE_G_STRING = 0;
538
539   len = 2 * strlen(fmt);
540   str = malloc(len > 256 ? len : 256);
541   vsprintf(str,fmt,args);
542
543   EiC_interActive = 0;  /* turn off interactive mode */
544   EiC_prolineString(str);
545
546
547   code = EiC_ENV->CODE;
548   EiC_ENV->CODE.nextinst = EiC_ENV->CODE.binst = 0;
549   EiC_ENV->CODE.inst = NULL;
550   EiC_ENV->CODE.prev = &code;
551   /*  sp = EiC_ENV->sp;*/
552
553   runEiC();
554
555   /* rem: runEiC will call free_env_code */
556   EiC_ENV->CODE = code;
557
558   EiC_interActive = h;
559   free(str);
560   va_end(args);
561   FREE_G_STRING = gs;
562 }    
563
564 void EiC_callBack(void *c)
565 {
566     code_t code;
567     int gs = FREE_G_STRING;
568
569     FREE_G_STRING = 0;
570
571     if(!c)
572         return;
573
574     code = EiC_ENV->CODE;
575     EiC_ENV->CODE = *(code_t*)c;
576     EiC_ENV->CODE.prev = &code; /* link */
577
578     EiC_interpret(EiC_ENV);
579
580     EiC_ENV->CODE.prev = NULL;  /* unlink */
581     EiC_ENV->CODE = code;
582     FREE_G_STRING = gs;
583 }    
584
585
586 void EiC_switches(char *switches)
587 {
588     if(switches) {
589         char *p,*c = malloc(strlen(switches)+2);
590         strcpy(c,switches);
591         p = strtok(c," \t\n");
592         while(p) {
593             if(*p == '-')
594                 do_sw_commands(p+1);
595             p = strtok(NULL," \t\n");
596         }
597         free(c);
598     }
599 }
600
601 int EiC_run(int argc, char **argv)
602 {
603     char * n2 = doargs(argc,argv);
604     int h = EiC_interActive;
605     code_t code;
606     
607     EiC_interActive = 0;  /* turn off interactive mode */
608
609     code = EiC_ENV->CODE;
610     EiC_ENV->CODE.nextinst = EiC_ENV->CODE.binst = 0;
611     EiC_ENV->CODE.inst = NULL;
612     EiC_ENV->CODE.prev = &code;
613     /*sp = EiC_ENV->sp;*/
614
615
616     EiC_prolineString(n2);
617     runEiC();
618
619
620     if(!EiC_Include_file(argv[0],1))
621         return 0;
622     else 
623         runEiC();
624
625     if(doEntry()) 
626         runEiC();
627
628     /* rem: runEiC will call free_env_code */
629     EiC_ENV->CODE.prev = NULL;
630     EiC_ENV->CODE = code;
631     /*EiC_ENV->sp = sp;*/
632
633     xfree(n2);
634
635     EiC_interActive = h;
636     return 1;
637 }    
638
639 void EiC_getSwitchCommands(int *Argc, char ***Argv)
640 {
641
642 #ifndef NO_ARGV
643
644     int argc = *Argc;
645     char **argv = *Argv;
646  
647     static int gotSwitches = 0;
648
649     if(gotSwitches)
650         return;
651
652     gotSwitches = 1;
653     
654     if(argc-- > 0)
655         while(argv[1]) {
656             if(argv[1][0] == '-') {
657                 if(!do_sw_commands(&argv[1][1])) {
658                     EiC_error("Unknown switch command [%s]\n",
659                             argv[1]);
660                     usage();
661                 } 
662             } else 
663                 break;
664             argv++;
665             argc--;
666         }
667
668     if(argc-- >0) {
669         if(!EiC_run(argc+1,argv+1))
670             EiC_error("Failed to run %s\n",argv[1]);
671         exit(0);
672     }
673
674     *Argc = argc;
675     *Argv = argv;
676
677 #endif
678
679 }   
680
681 void EiC_startEiC(int argc, char **argv)
682 {
683     extern int EiC_load_history(char *fname,int prompt);
684
685 #if defined(WIN32) || defined(_DJGPP)
686     signal(SIGABRT, EiC_bus_err);
687 #else
688     signal(SIGBUS, EiC_bus_err);
689 #endif
690     signal(SIGILL, EiC_ill_oper);
691     signal(SIGSEGV, EiC_stor_access);
692     signal(SIGFPE, EiC_float_err);
693     signal(SIGINT, EiC_term_int);
694 #if defined(WIN32) || defined(_DJGPP)
695     signal(SIGTERM, EiC_exit_call);
696 #else
697     signal(SIGUSR1, EiC_exit_call);
698 #endif
699
700
701     EiC_getSwitchCommands(&argc,&argv);
702
703 #ifndef NO_ARGV
704
705     if(argc-- >0) {
706         if(!EiC_run(argc+1,argv+1))
707             EiC_error("Error: Failed to run %s\n",argv[1]);
708         exit(0);
709     }
710 #endif
711
712     if(!silent) {
713       fputs(Version,stdout);
714     }
715    
716     #ifndef NO_HISTORY 
717     if(StartUpH)
718         EiC_setinfile("starteic.h");
719
720     if(HistoryFile) {
721         char * name = "EiChist.lst";
722         if(reStart) {
723           puts("Re Initiating EiC -- please wait.");
724           if(EiC_load_history(name,prompt)) {
725             runEiC();  /* ensure that startup files have
726                           been loaded and compiled */
727             EiChist = fopen(name,"w");
728             EiC_save_history(EiChist,0);
729             fclose(EiChist);
730             EiChist=NULL;
731             EiC_Include_file(name,1);
732             runEiC();
733             EiChist = fopen(name,"a");
734           }else {
735             EiC_error("Error: unable to load history file\n");
736             HistoryFile = 0;
737             EiChist = NULL;
738           }
739           puts("Done.");
740         } else {
741           EiChist = fopen(name,"w");
742           if(!EiChist) {
743             EiC_messageDisplay("Failed to create EiChist.lst\n"
744                     "Start No history file mode switch\n");
745             HistoryFile = 0;
746           }
747         }
748         if(HistoryFile)     
749           setvbuf(EiChist,NULL,_IOLBF,0);
750       }
751      #endif
752
753      #ifdef PPCLIB
754         setvbuf(stdout,NULL,_IONBF,0);
755         setvbuf(stderr,NULL,_IONBF,0);
756      #endif
757     /* Hawk start change */
758 //      while(1) 
759 //      runEiC();
760     /* Hawk change */
761 }
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798