Update the changelog
[opencv] / apps / Hawk / CVEiCL / EiC / src / eicmod.c
1 /* eicmod.c
2  *
3  *      (C) Copyright Apr 15 1995, Edmond J. Breen.
4  *                 ALL RIGHTS RESERVED.
5  * This code may be copied for personal, non-profit use only.
6  *
7  */
8
9
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <ctype.h>
15
16 #include "typemod.h"
17 #include "global.h"
18 #include "lexer.h"
19
20 #include "func.h"
21 #include "xalloc.h"
22 #include "typesets.h"
23 #include "preproc.h"
24 #include "cdecl.h"
25 #include "error.h"
26 #include "emitter.h"
27 #include "symbol.h"
28
29 extern char EiC_LEXEM[];
30 extern token_t *token;
31
32 int EiC_listcodeON = 0;
33 int EiC_lineNums = 0;
34 int EiC_interpON = 1;
35 int EiC_TIMER = 0;
36 int EiC_SHOWLINE = 0;
37 int EiC_memdumpON = 0;
38 int EiC_memtraceON = 0;
39 int EiC_traceON = 0;
40 int EiC_traceFunc = 0;
41 int EiC_verboseON = 0;
42 int interfaceON=0;
43 int EiC_interActive=1;
44 int EiC_showIncludes = 0;
45 int adjustNum = 0;
46
47
48 static void outputval(int obj, void *v)
49 {
50     switch (obj) {
51       case t_char:    fprintf(stdout,"%d",*(char *) v);break;
52       case t_uchar:   fprintf(stdout,"%d",*(unsigned char *) v); break;
53       case t_short:   fprintf(stdout,"%d",*(short *) v); break;
54       case t_ushort:  fprintf(stdout,"%d",*(unsigned short*) v); break;
55       case t_int:     fprintf(stdout,"%d",*(int *) v); break;
56       case t_uint:    fprintf(stdout,"%u",*(unsigned *) v); break;
57       case t_long:    fprintf(stdout,"%ld",*(long *) v); break;
58       case t_ulong:   fprintf(stdout,"%lu",*(long *) v); break;
59
60 #ifndef NO_LONG_LONG
61
62       case t_llong:   fprintf(stdout,"%Ld",*(eic_llong *) v); break;
63 #else
64       case t_llong:   fprintf(stdout,"%ld",*(eic_llong *) v); break;
65 #endif 
66
67       case t_float:   fprintf(stdout,"%.9g",*(float *) v); break;
68       case t_double:  fprintf(stdout,"%.9g",*(double *) v); break;
69       case t_lval:   
70       case t_pointer: fprintf(stdout,"%p",(void*)*(long *) v); break;
71       case t_void:    fprintf(stdout,"(void)"); break;
72       case t_enum:    fprintf(stdout,"(enumeration)"); break; 
73       case STR:       fprintf(stdout,"%.100s",*(char **) v); break;
74       default:        fprintf(stdout,"Unknown type"); break;
75     }
76 }
77
78
79 static void showstruct(AR_t * arg)
80 {
81     int i, t;
82     struct_t *S;
83     char *D;
84     S = (struct_t *) EiC_getInf(arg->type);
85     D = arg->v.p.p;
86     fputc('{', stdout);
87     if (!D)
88         fputs("(null struct) ", stdout);
89     else
90         for (i = 0; i < S->n; i++) {
91             switch ((t = EiC_gettype(S->type[i]))) {
92               case t_array:
93                 fputs("Array", stdout);
94                 break;
95               case t_union:
96                 fputs("Union",stdout);
97                 break;
98               case t_struct:
99                 fputs("Struct", stdout);
100                 break;
101               default:
102                 outputval(t, &D[S->offset[i]]);
103                 break;
104             }
105             fputc(',', stdout);
106         }
107     fputs("\b}", stdout);
108 }
109
110 void EiC_showvalue(AR_t * arg)
111 {
112     int t;
113
114     if(!EiC_interActive || !arg->type)
115         return ;
116
117     fputc('\t', stdout);
118
119     t = EiC_gettype(arg->type);
120
121     if(isconst(arg->type) && t != t_pointer) {
122         outputval(t, &arg->v);
123         fputc('\n', stdout);
124         return;
125     }
126         
127     switch ((t = EiC_gettype(arg->type))) {
128       case t_union:  fputs("(Union)",stdout); break;
129       case t_struct: showstruct(arg); break;
130       case t_char:   case t_uchar:  case t_short:  
131       case t_ushort: outputval(t_int, &arg->v.ival); break;
132       case t_float:  outputval(t_double, &arg->v.ival); break;
133       case t_array:
134       case t_pointer:
135         if (EiC_gettype(nextType(arg->type)) == t_char)
136             t = STR;
137         else
138             t = t_pointer;
139       default:
140         outputval(t, &arg->v);
141         break;
142     }
143     fputc('\n', stdout);
144
145 }
146
147 static void EiC_showdectype(type_expr *, int, FILE *);
148
149 static void showFunc(type_expr **t, FILE *fp)
150 {
151     static int level = 0;
152     func_t *F;
153     int i,k;
154     fputs("Func (", fp);
155     F = (func_t *) EiC_getInf(*t);
156     level++;
157
158     if (F && getFNp(F)) {
159         for (i = 0; i < getFNp(F); i++) {
160             fputc('\n',fp);
161             for(k=0;k<level;k++)
162                 fputc('\t',fp);
163             if(getFPname(F,i))
164                 printf("%s: ",getFPname(F,i));
165             EiC_showdectype(getFPty(F,i), 0,fp);
166             if(i < getFNp(F)-1)
167                 fputs(",", fp);
168         }
169
170     }
171     fputc('\n',fp);
172     for(k=0;k<level;k++)
173         fputc('\t',fp);
174     fputs(") returning ", fp);
175     if(nextType(*t)) {
176         *t = nextType(*t);
177         EiC_showdectype(*t,0,fp);
178         if(*t)
179             while(nextType(*t))
180                 *t = nextType(*t);
181     }
182     
183     if(F && getFComm(F)) 
184         fprintf(fp,"\n\n    /* %s/\n", getFComm(F));  /**/
185     level--;
186     
187 }    
188
189 static void EiC_showdectype(type_expr * t, int expand, FILE *fp)
190 {
191
192     struct_t *S;
193     int i;
194     static int level = 0;
195
196     while (t) {
197         if(isconst(t) || isconstp(t))
198             fputs("const ",fp);
199         
200         switch (EiC_gettype(t)) {
201           case t_var:   fputs("...", fp); break;
202           case t_enum:  fputs("enum ", fp); break;
203           case t_char:  fputs("char ", fp); break;
204           case t_uchar: fputs("unsigned char ", fp); break;
205           case t_short: fputs("short ", fp); break;
206           case t_ushort:fputs("unsigned short ", fp); break;
207           case t_int:   fputs("int ", fp); break;
208           case t_uint:  fputs("unsigned ", fp); break;
209           case t_long:  fputs("long int ", fp); break;
210           case t_ulong: fputs("unsigned long int ", fp); break;
211           case t_llong: fputs("long long ",fp); break;
212           case t_float: fputs("float ", fp); break;
213           case t_double:fputs("double ", fp); break;
214           case t_pointer: 
215
216             if(isunsafe(t)) 
217               fputs("unsafe ", fp);
218             /*else if(issafe(t)) 
219               fputs("safe ", fp);*/
220
221             fputs("* ", fp); 
222             break;
223
224           case t_void:  fputs("void ", fp); break;
225           case t_hidden: fputs("hidden ",fp); break;
226             
227           case t_funcdec: fputs("dec_", fp); showFunc(&t,fp); break;
228           case t_func:   showFunc(&t,fp); break;
229           case t_builtin: fputs("Builtin ",fp); showFunc(&t,fp); break; 
230
231           case t_array:
232             fprintf(fp,"ARY[%d]",(int) EiC_getInf(t));
233             break;
234           case t_union:
235           case t_struct:
236             S = EiC_getInf(t);
237             if(!S) {
238                 fputs("Incomplete", fp);
239                 break;
240             }
241             if (EiC_gettype(t) == t_struct)
242                 fprintf(fp,"struct: size  %u bytes",S->tsize);
243             else
244                 fprintf(fp,"union: size  %u bytes",S->tsize);
245             if (expand) {
246                 level++;
247                 fputc('\n', fp);
248                 if (level <= 2) {
249                     int j;
250                     for (i = 0; i < S->n; i++) {
251                         for (j = 0; j < level; j++)
252                             fputc('\t', fp);
253                         fputs(S->id[i], fp);
254                         fputs(" -> ", fp);
255                         EiC_showdectype(S->type[i], expand,fp);
256                         fputc('\n', fp);
257                     }
258                 }
259                 level--;
260             }
261             break;
262           case t_ref: fputs("Reference ",fp);break;
263           case ID: fputs("Identifier ", fp); break;
264           default: fputs("Uknown identifier", fp); return;
265         }
266         t = nextType(t);
267     }
268 }
269
270 static int IsObject(int t)
271 {
272     if(t != t_func && t !=t_funcdec && t != t_builtin)
273         return 1;
274     return 0;
275 }
276
277
278 int EiC_IsFunc(int t)
279 {
280     return !IsObject(t);
281 }
282
283 static void displaySclass(symentry_t *sym)
284 {
285     /* display storage class */
286     if (sym->sclass == c_typedef)
287         fputs("typedef ", stdout);
288     else if(sym->sclass & c_private)
289         fprintf(stdout,"private to %s: ", sym->fname);
290     else if (sym->sclass & c_static)
291         fputs("static ", stdout);
292     if (sym->typequal == q_const)
293         fputs("const ", stdout);
294     else if (sym->typequal == q_volatile)
295         fputs("volatile ", stdout);
296 }    
297
298 static void showtab(int tab, int expand, token_t * e1, char *fname, int allowed())
299 {
300     int i, t;
301     symentry_t *sym;
302     
303     for (i = 0; i < HSIZE; i++)
304         for (sym = EiC_HTAB[i]; sym; sym = sym->next) {
305
306             if ((t = EiC_gettype(sym->type)) == t_eic || sym->nspace != tab)
307                 continue;
308
309             if(e1 && e1->Type && ! EiC_sametypes(e1->Type,sym->type))
310                 continue;
311
312             /*printf("looking at [%s]\n",sym->fname);*/
313             if(fname && strcmp(fname,sym->fname) != 0)
314                 continue;
315             
316             if(allowed && !allowed(t))
317                 continue;
318             displaySclass(sym);
319             fputs(sym->id, stdout);
320             fputs(" -> ", stdout);
321             EiC_showdectype(sym->type, expand,stdout);
322             fputc('\n', stdout);
323         }
324 }
325
326
327 static int show(void)
328 {
329     int t;
330     int h = EiC_work_tab;
331     AR_t arg;
332
333     EiC_work_tab = stand_tab;
334
335     if ((t = EiC_lexan()) == ID || t == TYPENAME) {
336         if(!EiC_showMacro(token->Val.sym->id)) { /* test macros first */
337             t = EiC_gettype(token->Val.sym->type);
338             if (t == ID) {
339                 EiC_remsym(token->Val.sym);
340                 /*
341                  * check for struct/union tag name.
342                  */
343                 if ((token->Val.sym = EiC_lookup(tag_tab, EiC_LEXEM)) == NULL) {
344                     EiC_error("Unknown identifier %s",EiC_LEXEM);
345                     return 0;
346                 }
347                 fputs("Tag::",stdout);
348             }
349
350             displaySclass(token->Val.sym);
351             fputs(token->Val.sym->id, stdout);
352             fputs(" -> ", stdout);
353             EiC_showdectype(token->Val.sym->type, 1,stdout);
354             fputc('\n',stdout);
355             
356 /* -----------------------------------------------------*/
357            
358             t = EiC_gettype(token->Val.sym->type);
359             if (! (token->Val.sym->sclass == c_typedef ||
360                    (t==t_builtin) || (t==t_func) || (t==t_funcdec))) 
361             {
362               fputs("value= ", stdout);
363               
364               arg.v=EiC_ENV->AR[token->Val.sym->val.ival].v;
365               arg.type = token->Val.sym->type;
366     
367               EiC_showvalue(&arg);
368               
369              } 
370              
371
372 /* -------------------------------------------------*/
373             if (t == t_func && EiC_listcodeON) {
374                 if (EiC_ENV->AR[token->Val.sym->val.ival].v.p.p)
375                     EiC_listcode(EiC_ENV->AR[token->Val.sym->val.ival].v.p.p);         
376             }
377         } else
378             EiC_remsym(token->Val.sym);
379     } else
380         EiC_error("Expected identifier");
381     EiC_work_tab = h;
382     return 1;
383 }
384
385 static char *getNextInput()
386 {
387     
388     char c, *p;
389     static char buf[256];
390     
391     while(isspace(c = EiC_nextchar()));
392     p = buf;
393     while( c && c != DONE && !isspace(c)) {
394         *p++ = c;
395         c = EiC_nextchar();
396     }
397     *p = '\0';
398
399     return buf;
400 }
401
402
403 static int ResetEiC()
404 {
405     char *buf;
406     void EiCp_ResetStart(void);
407     void EiCp_setResetStart(void);
408
409     buf = getNextInput();
410     if(buf[0]) {
411         if(strcmp(buf,"here") == 0)
412            EiCp_setResetStart();
413         else
414             EiC_error("Unrecgonised command `%s' for reset",buf);
415     } else
416         EiCp_ResetStart();
417
418     return 0;
419 }
420
421 static int filesCommand(void)
422 {
423     void EiC_showIncludedFiles(void);
424     void EiC_showFileMacros(char *fname);
425     char EiC_nextchar(void);
426
427     int EiC_IsIncluded(char *fname);
428     char *buf;
429     
430     buf = getNextInput();
431
432     if(buf[0]) {
433         if(!EiC_IsIncluded(buf))
434              EiC_warningerror("Failed to find %s",buf); 
435         else {
436             EiC_showFileMacros(buf);
437             showtab(stand_tab,0,NULL,buf,IsObject);
438             showtab(stand_tab,0,NULL,buf,EiC_IsFunc);
439         }
440     } else 
441         EiC_showIncludedFiles();
442     
443     return 1;
444 }
445
446 static int clearCommand(void)
447 {
448     /*
449      * syntax :clear file1[,file]*
450      */
451
452     int EiC_lutClearFileEntries(char *FileName);
453     void EiC_ClearFileMacros(char *fname);
454     void EiC_rmIncludeFileName(char *fname);
455     
456     char EiC_nextchar(void);
457
458     int EiC_IsIncluded(char *fname);
459     char *buf;
460
461     buf = getNextInput();
462
463     if(buf[0]) {
464         char *p;
465         do {
466             p = strchr(buf,',');
467             if(p) 
468                 *p = 0;
469
470             if(!EiC_IsIncluded(buf))
471                 EiC_warningerror("Failed to find %s",buf); 
472             else {
473                 int r = EiC_lutClearFileEntries(buf);
474                 EiC_ClearFileMacros(buf);
475                 if(r)
476                     EiC_rmIncludeFileName(buf);
477             }
478             if(p) 
479                 buf = p + 1;
480         }while(p);
481                 
482
483     } else 
484         EiC_error("Expected file name");
485     
486
487
488     return 1;
489 }
490
491 static int setnextinf(void *info)
492 {
493     int i, t;
494     symentry_t *sym;
495     type_expr *type;
496     for (i = 0; i < HSIZE; i++)
497         for (sym = EiC_HTAB[i]; sym; sym = sym->next)
498             if ((t = EiC_gettype(sym->type)) == t_union || t == t_struct)
499                 for (type = sym->type; type; type = nextType(type))
500                     if (type->alias && EiC_getInf(type) == info) {
501                         type->alias = 0;
502                         return 1;
503                     }
504     return 0;
505 }
506
507 static void checktype(type_expr * type)
508 {
509     int t;
510     while (type) {
511         if ((t = EiC_gettype(type)) == t_struct || t == t_union)
512             if (!type->alias)
513                 if (setnextinf(EiC_getInf(type)))
514                     type->alias = 1;
515         type = nextType(type);
516     }
517 }
518
519
520 static long getmitem(val_t *v, int t)
521 {
522     switch(t) {
523       case INT: return v->ival;
524       case UINT: return v->uival;       
525       case LONG: return v->lval;
526       case ULONG: return v->ulval;
527     }
528     return -1;      
529 }
530
531 static int rm(void)
532 {
533     unsigned long mitem;
534     
535     int t, h = EiC_work_tab;
536     EiC_work_tab = stand_tab;
537     do {
538         switch(EiC_lexan()) {
539           case ID:
540           case TYPENAME:
541             t = EiC_gettype(token->Val.sym->type);
542             if (t == ID) {
543                 EiC_remsym(token->Val.sym);
544                 /*
545                  * check for a tag name.
546                  */
547                 if((token->Val.sym = EiC_lookup(tag_tab,EiC_LEXEM)) == NULL) {
548                     EiC_error("Unknown identifier %s",EiC_LEXEM);
549                 }else {
550                     checktype(token->Val.sym->type);
551                     EiC_remsym(token->Val.sym);
552                 }
553             } else if (t == t_builtin) {
554                 EiC_error("Cannot remove builtin functions");
555             } else {
556                 checktype(token->Val.sym->type);
557                 EiC_remsym(token->Val.sym);
558             }
559             break;
560           case INT: 
561           case UINT:
562           case LONG:
563           case ULONG:       
564             mitem = getmitem(&token->Val,token->Tok);
565             if(EiC_getMemMark(mitem) == MEM_LEAK)
566                 EiC_freeMemItem(mitem);
567             else
568                 EiC_error("Memory item %ld is not a leak\n", mitem);
569             break;
570           default:
571             EiC_error("UnExpected input to rm");
572             break;
573             
574         }
575     } while (EiC_lexan() == ',');
576     retractlexan();
577     EiC_work_tab = h;
578     return 1;
579 }
580
581
582 static int showhashtab(void)
583 {
584     int tab;
585     token_t e1;
586
587     EiC_work_tab = tab  = stand_tab;   /* standard name space */
588     EiC_inittoken(&e1);
589
590     switch(EiC_lexan()) {
591       TYPESPEC:
592       TYPEQUAL:
593         retractlexan();
594         EiC_type_name(&e1);
595         break;
596       case ID:
597         if(strcmp(EiC_LEXEM,"tags") == 0) 
598             tab = tag_tab;
599         else if(strcmp(EiC_LEXEM,"builtin") == 0)
600                 e1.Type = EiC_addtype(t_builtin,0);
601         else
602             retractlexan();
603         break;          
604       default:
605         retractlexan();
606     }
607     if(e1.Type) {
608         showtab(tab, 0,&e1,NULL,NULL);
609         EiC_freetype(e1.Type);
610     } else {
611         showtab(tab,0,NULL,NULL,IsObject);
612         showtab(tab,0,NULL,NULL,EiC_IsFunc);
613     }
614     return 1;
615 }
616
617 static int extra_option(char * option)
618 {
619     EiC_work_tab = stand_tab;   /* standard name space */
620     if (EiC_lexan() == ID) {
621         if(strcmp(EiC_LEXEM,option) == 0)
622             return 1;
623         else
624             retractlexan();
625     } else
626         retractlexan();
627     return 0;
628 }
629
630 int EiC_exit_EiC()
631 {
632     extern FILE *EiChist;
633     fflush(NULL);
634     if(EiC_verboseON)
635         fputs("EiC Bye\n", stdout);
636     if(EiChist)
637         fclose(EiChist);
638     exit(1);
639     return 1;
640 }
641
642 static int toggle_verbose()
643 {
644     EiC_verboseON = !EiC_verboseON;
645     return EiC_verboseON;
646 }
647
648 static int toggle_interface()
649 {
650     interfaceON = !interfaceON;
651     return interfaceON;
652 }
653
654
655 static int toggle_memdump()
656 {
657     EiC_memdumpON = !EiC_memdumpON;
658     return EiC_memdumpON;
659 }
660
661 static int toggle_memtrace()
662 {
663     EiC_memtraceON = !EiC_memtraceON;
664     return EiC_memtraceON;
665 }
666
667 static int toggle_showline()
668 {
669     EiC_SHOWLINE = !EiC_SHOWLINE;
670     return EiC_SHOWLINE;
671 }
672
673
674 static int toggle_timer()
675 {
676     EiC_TIMER = !EiC_TIMER;
677     return EiC_TIMER;
678 }
679
680 static int toggle_interp()
681 {
682     EiC_interpON = !EiC_interpON;
683     return EiC_interpON;
684 }
685
686 static int toggle_includes()
687 {
688     EiC_showIncludes= !EiC_showIncludes;
689     return EiC_showIncludes;
690 }
691
692 static int toggle_trace()
693 {
694     if(extra_option("funcs"))
695         EiC_traceFunc = !EiC_traceFunc;
696     else
697         EiC_traceFunc = 0;
698
699     if(EiC_traceFunc)
700         EiC_traceON = 1;
701     else
702         EiC_traceON = !EiC_traceON;
703
704     return EiC_traceON;
705 }
706
707 static int toggle_listcode()
708 {
709     if(extra_option("linenums"))
710         EiC_lineNums = !EiC_lineNums;
711     else
712         EiC_lineNums = 0;
713
714     if(EiC_lineNums)
715         EiC_listcodeON = 1;
716     else
717         EiC_listcodeON = !EiC_listcodeON;
718
719     return EiC_listcodeON;
720 }
721
722
723 static int showhistory()
724 {
725   #ifndef NO_HISTORY
726     void EiC_show_history(FILE *fp);
727     EiC_show_history(stdout);
728   #endif
729     return 1;
730 }
731
732 static int showHelp()
733 {
734 puts("-----------------------------------------------------------------------------\n"
735      "EiC-COMMAND          SUMMARY DESCRIPTION\n"
736      "-----------------------------------------------------------------------------\n"
737      ":-I path       Append path to the include-file search list.\n"
738      ":-L            List search paths.\n"
739      ":-R path       Remove path from the include-file search list.\n"
740      ":clear fname   Removes the contents of file fname from EiC.\n"
741      ":exit          Terminates an EiC session.\n"
742      ":files         Display the names of all included files.\n"
743      ":files fname   Summarize the contents of the included file `fname'.\n" 
744      ":gen fname     Generates EiC interface of the included file `fname'.\n"
745      ":gen fname [<\"outfile\">] Places the interface in outfile\n"
746      ":gen fname 4   Generates EiC interface with 4 levels of multiplexing.\n"
747      ":help          Display summary of EiC commands.\n"
748      ":history       List the history of all input commands.\n"
749      ":includes      Display path of include files when loaded.\n"
750      ":interpreter   Execute input commands. By default it is on.\n"
751      ":listcode      List stack code.\n"
752      ":listcode linenums     List stack code with associated line numbers.\n"
753      ":memdump       Show potential memory leaks.\n"
754      ":reset         Reset EiC back to its start state.\n"
755      ":reset here    Set the `reset' state to EiC's current state.\n"
756      ":rm  dddd      Remove memory item dddd, which is a constant integer value.\n"
757      ":rm   f        Removes f's definition from the symbol tables.\n"
758      ":show f        Shows type or  macro definition of `f'.\n"
759      ":showline      Show input line after macro expansion.\n"
760      ":status        Display the status of the toggle switches.\n"
761      ":timer         Time in seconds of execution.\n"
762      ":trace         Trace function calls and line numbers during code execution.\n"
763      ":trace funcs   Trace function calls only during code execution.\n"
764      ":variables     Display declared variables and interpreter-ed function names.\n"
765      ":variables tags       Display the tag identifiers.\n"
766      ":variables type-name  Display variables of type `type-name'.\n"
767      ":verbose       Suppresses EiC's copyright and warning messages on start up.\n"
768      "------------------------------------------------------------------------------\n"
769      );
770     return 0;
771 }
772
773 static int EiCstatus()
774 {
775     struct toggle {
776         char * name;
777         int *val; }
778     toggles[] =  {
779         {"includes",&EiC_showIncludes},
780         {"interpreter", &EiC_interpON},
781         {"listcode",&EiC_listcodeON},
782         {"memdump", &EiC_memdumpON},
783         {"showline",&EiC_SHOWLINE},
784         {"timer",&EiC_TIMER},
785         {"trace",&EiC_traceON},
786         {"verbose",&EiC_verboseON},
787     };
788     int n = sizeof(toggles)/sizeof(struct toggle);
789
790     while(n--)
791         printf("\t%-15s %d\n",toggles[n].name, *toggles[n].val);
792
793     return 0;
794 }
795
796
797 static symentry_t *add_eicfunc(char *name, int (*func) ())
798 {
799     symentry_t *sym;
800     sym = EiC_insertLUT(eic_tab, name, t_eic);
801     sym->level = 1;
802     sym->val.func = func;
803     return sym;
804 }
805
806 symentry_t *EiC_add_builtinfunc(char *name, val_t(*vfunc) ())
807 {
808     symentry_t *sym;
809     sym = EiC_insertLUT(stand_tab, name, ID);
810     EiC_freetype(sym->type);
811     sym->level = 1;
812     sym->val.vfunc = vfunc;
813     sym->type = EiC_addtype(t_builtin,NULL);
814     return sym;
815 }
816
817
818 void EiC_comm_switch(void)
819 {
820     int EiC_insertpath(char *);
821     int EiC_removepath(char *);
822     void EiC_listpath(void);
823     char EiC_nextchar(void);
824     
825     char *buf;
826     if (EiC_lexan() == ID) {
827         if(EiC_gettype(token->Val.sym->type) == ID) {
828             EiC_remsym(token->Val.sym);
829         }
830
831         buf = getNextInput();
832             
833         switch(EiC_LEXEM[0]) {
834           case 'I':
835             if(!*buf || !EiC_insertpath(buf))
836              EiC_warningerror("Failed to add path"); 
837             break;
838           case 'R':
839             if(!*buf || !EiC_removepath(buf))
840              EiC_warningerror("Failed to remove path"); 
841             break;
842           case 'L':
843             EiC_listpath();break;
844           default:          
845             EiC_error("Unknown command switch");
846         }                   
847             
848     } else 
849         EiC_error("Expected command switch");
850
851 }
852
853
854
855 /*                                                                      */
856 /* Jean-Bruno Richard personal Modification inside eicmod.c             */
857 /*                                                                      */
858 /* Semi-automatic module code generation                                */
859 /* functions. Thanks to the function prototype, it's possible to        */
860 /* generate it's interfacing function to EiC.                           */
861 /* Few manual modification of the generated code are sometimes needed,  */
862 /* but it helps a lot....                                               */
863 /* How to use it :                                                      */
864 /* Launch EiC, #include the desired header file                         */
865 /* (Example #include "gl.h")                                            */
866 /* and use the new EiC command :gen with the name of the header file    */
867 /* (In the example :gen gl.h) EiC will output the interface to stdout   */
868 /* Hope it helps.....   :                                               */
869 /* jean-bruno.richard@mg2.com                                           */
870
871
872
873 #ifndef NO_AUTOGEN
874
875
876 static int callBack=0;
877 static  int * callNo =NULL;
878 static  int *callpos = NULL;
879 static int Ncalls = 0;
880 static char *callName="EiC_Cfunc_";
881 static char *middleName="MiddleOne_";
882 static int  MULTIPLEX = 1;
883
884 static void EiC__generateType(type_expr *t, char *id,FILE *fp, int level)
885 {
886
887     struct_t *S;
888
889     char tmp[100];
890     char out[100];
891
892     strcpy(out,id);
893
894     do {
895         switch(EiC_gettype(t)) {
896             case t_pointer: /* pointer */
897                 sprintf(tmp,"*%s",out);
898                 strcpy(out,tmp);
899                 break;
900
901             case t_char:    sprintf(tmp,"%s %s", "char", out); strcpy(out,tmp); break;
902             case t_uchar:   sprintf(tmp,"%s %s", "unsigned char",out);strcpy(out,tmp); break;
903             case t_short:   sprintf(tmp,"%s %s",  "short",out);strcpy(out,tmp);break;
904             case t_ushort:  sprintf(tmp,"%s %s",  "unsigned short",out);strcpy(out,tmp);break;
905             case t_int:     sprintf(tmp,"%s %s",  "int",out);strcpy(out,tmp);break;
906             case t_uint:    sprintf(tmp,"%s %s",  "unsigned",out);strcpy(out,tmp);break;
907             case t_long:    sprintf(tmp,"%s %s",  "long",out);strcpy(out,tmp);break;
908             case t_ulong:   sprintf(tmp,"%s %s",  "unsigned long",out);strcpy(out,tmp);break;
909             case t_float:   sprintf(tmp,"%s %s",  "float",out);strcpy(out,tmp);break;
910             case t_double:  sprintf(tmp,"%s %s",  "double",out);strcpy(out,tmp);break;
911             case t_void:  sprintf(tmp,"%s %s",  "void",out);strcpy(out,tmp);break;
912
913             case t_struct:
914             case t_union:
915                 if(EiC_gettype(t) == t_union) 
916                     fputs("union {",fp);
917                 else
918                     fputs("struct {",fp);
919
920                 S = EiC_getInf(t);
921                 if(!S) {
922                     fputs("Incomplete", fp);
923                     break;
924                 }
925                 level++;
926                 if (level <= 2) {
927                     int i;
928                     for (i = 0; i < S->n; i++) {
929                         EiC__generateType(S->type[i], S->id[i], fp,level);
930                         fputs(";",fp);
931                     }
932                 }
933                 sprintf(tmp,"} %s ",out);
934                 strcpy(out,tmp);
935                 level--;
936                 break;
937
938             case t_array: /* array */ 
939                 if(out[0] ==  '*') {
940                     sprintf(tmp,"(%s)%s",out,"[]");
941                     strcpy(out,tmp);
942                 } else {
943                     sprintf(tmp,"[%d]",(int)EiC_getInf(t));
944                     strcat(out, tmp);
945                 }
946                 break;
947
948                 
949         }
950
951     } while ( (t=nextType(t)));
952
953     fprintf(fp,"%s",out);
954 }
955
956 static int DoCallBackNames(func_t *F, FILE *fp)
957 {
958     int x = 0;
959     if (F) {
960         int i;
961         callpos = realloc(callpos,sizeof(int)*getFNp(F));
962         for (i = 0; i < getFNp(F); i++) {
963             type_expr *t = getFPty(F,i);
964             if(EiC_gettype(t) == t_pointer && 
965                EiC_IsFunc(EiC_gettype(nextType(t)))) {
966                 callNo = realloc(callNo, sizeof(*callNo) * (x+1));
967                 callpos[x] = i;
968                 callNo[x] = callBack++;
969                 fprintf(fp,"static void * %s%d = NULL;\n",callName,callNo[x]);
970                 x++;
971             }
972         }
973     }
974     return (Ncalls = x);
975 }
976
977
978 static void genCallBackFunc(type_expr *ty, 
979                             int p, 
980                             FILE *fp)
981 {
982     char buff[10];
983     func_t *F, *F2;
984     int i,v, var=0;
985     type_expr *t;
986
987     F = EiC_getInf(ty);
988     t = getFPty(F,callpos[p]);
989     t = nextType(t);
990     F2 = EiC_getInf(t);
991
992     fprintf(fp,"static ");
993     EiC_showdectype(nextType(t),0,fp);
994
995     fprintf(fp," %s%d(",middleName,callNo[p]);
996
997     /* check 4 varadic function calls */
998     for(i=0;i<getFNp(F2);i++) 
999         if(EiC_gettype(getFPty(F2,i)) == t_var) {
1000             var = 1;
1001             break;
1002         }
1003
1004     if(!var) {
1005         for(i=0;i<getFNp(F2)-1;i++) {
1006             if((v=EiC_gettype(getFPty(F2,i))) == t_void)
1007                 continue;
1008             sprintf(buff,"x%d, ",i);
1009             EiC__generateType(getFPty(F2,i),buff,fp,1);
1010
1011         }
1012         if((v=EiC_gettype(getFPty(F2,i))) != t_void)  {
1013             sprintf(buff,"x%d ",i);
1014             EiC__generateType(getFPty(F2,i),buff,fp,1);
1015         }
1016         fprintf(fp,")\n{\n");
1017
1018         for (i = 0; i < getFNp(F2); i++) {
1019             if(EiC_gettype(getFPty(F2,i)) == t_void)
1020                 continue;
1021             fprintf(fp,"    setArg(%d, %s%d, ",i,callName,callNo[p]);
1022
1023             EiC__generateType(getFPty(F2,i),"",fp,1);
1024
1025             fprintf(fp,",x%d);\n",i);
1026         }
1027
1028     } else {
1029         fprintf(fp," va_alist )  va_dcl\n{\n");
1030         fprintf(fp,"    void Auto_EiC_CallBack(code_t *callback, va_list ap);\n");
1031         fprintf(fp,"    va_list ap; va_start(ap);\n");
1032         fprintf(fp,"    Auto_EiC_CallBack(%s%d,ap);\n",callName,callNo[p]);
1033     } 
1034         
1035     fprintf(fp,"\n    EiC_callBack(%s%d);\n",callName,callNo[p]);
1036
1037     if(EiC_gettype(nextType(t)) != t_void) {
1038         fputs("    return EiC_ReturnValue( ",fp);
1039         /*EiC_showdectype(nextType(t),0,fp);*/
1040         EiC__generateType(nextType(t),"",fp,1);
1041         fputs(");\n",fp);
1042     }
1043     if(var)
1044         fputs("    va_end(ap);\n",fp);
1045     
1046     fputs("}\n\n",fp);
1047
1048 }
1049
1050
1051
1052 static void genArg(type_expr * t, int idx, FILE *fp)
1053 {
1054     int ob;
1055    if ((ob = EiC_gettype(t)) == t_void) {
1056       return;
1057    }
1058
1059    if(ob == t_pointer) {
1060        int k = EiC_gettype((nextType(t)));
1061        if(EiC_IsFunc(k)) {
1062            k = 0;
1063            while(k<Ncalls && callpos[k] != idx) k++;
1064            fprintf(fp,"%s%d",middleName,callNo[k]+adjustNum);
1065            return ;
1066        }
1067    }
1068        
1069     fputs("arg(",fp);
1070     fprintf(fp,"%d",idx);
1071     fputs(",getargs(),",fp);
1072
1073         switch (ob) {
1074           case t_char:  fputs("char)", fp); break;
1075           case t_uchar: fputs("char)", fp); break;
1076           case t_short: fputs("short)", fp); break;
1077           case t_ushort:fputs("short)", fp); break;
1078           case t_int:   fputs("int)", fp); break;
1079           case t_uint:  fputs("unsigned)", fp); break;
1080           case t_long:  fputs("long) ", fp); break;
1081           case t_ulong: fputs("unsigned long)", fp); break;
1082           case t_float: fputs("float)", fp); break;
1083           case t_double:fputs("double)", fp); break;
1084           case t_pointer:
1085               fputs("ptr_t).p",fp);
1086               break; 
1087           default: fputs("Uknown identifier", fp); return;
1088         }
1089 }
1090
1091 static void genAffect(type_expr * t, int expand, FILE *fp)
1092 {
1093  
1094         fputs("\t", fp);
1095         switch (EiC_gettype(t)) {
1096           case t_char: 
1097           case t_short:
1098           case t_int:   fputs("v.ival = ", fp); break;
1099           case t_uchar:
1100           case t_ushort:
1101           case t_uint:  fputs("v.uival = ", fp); break;
1102           case t_long:  fputs("v.lval = ", fp); break;
1103           case t_ulong: fputs("v.ulval = ", fp); break;
1104           case t_float: 
1105           case t_double:fputs("v.dval = ", fp); break;
1106
1107           case t_pointer: 
1108             if(isunsafe(t)) 
1109               fputs("v.p.ep = (void*)ULONG_MAX;\n"
1110                     "\tv.p.sp = v.p.p = ",fp);
1111             else if(issafe(t)) 
1112               fputs("v.p.ep = v.p.sp = v.p.p = ", fp);
1113             break;
1114           case t_void:  break;
1115           case t_hidden: break;
1116             
1117 /*        case t_array:
1118             fprintf(fp,"ARY[%d]",(int) EiC_getInf(t));
1119             break;
1120           case t_union:
1121           case t_struct:
1122             S = EiC_getInf(t);
1123             if(!S) {
1124                 fputs("Incomplete", fp);
1125                 break;
1126             }
1127             if (EiC_gettype(t) == t_struct)
1128                 fprintf(fp,"struct: size  %u bytes",S->tsize);
1129             else
1130                 fprintf(fp,"union: size  %u bytes",S->tsize);
1131             if (expand) {
1132                 level++;
1133                 fputc('\n', fp);
1134                 if (level <= 2) {
1135                     int j;
1136                     for (i = 0; i < S->n; i++) {
1137                         for (j = 0; j < level; j++)
1138                             fputc('\t', fp);
1139                         fputs(S->id[i], fp);
1140                         fputs(" -> ", fp);
1141                         EiC_showdectype(S->type[i], expand,fp);
1142                         fputc('\n', fp);
1143                     }
1144                 }
1145                 level--;
1146             }
1147             break;
1148           case t_ref: fputs("Reference ",fp);break;
1149           case ID: fputs("Identifier ", fp); break;
1150 */
1151           default: fputs("Uknown identifier", fp); return;
1152         }
1153 }
1154
1155 static void genCall(type_expr *t, char *fname, FILE *fp)
1156 {
1157     static int level = 0;
1158     func_t *F;
1159     int i;
1160
1161     F = (func_t *) EiC_getInf(t);
1162     level++;
1163
1164     fputs("\n", fp);
1165
1166     if(Ncalls) {
1167         int k;
1168         for(k=0;k<Ncalls;++k) 
1169             fprintf(fp,"\t%s%d = arg(%d,getargs(),ptr_t).p;\n",
1170                     callName,callNo[k],callpos[k]);
1171     }
1172
1173     if(nextType(t)) {
1174         t = nextType(t);
1175         genAffect(t,0,fp);
1176         if(t)
1177             while(nextType(t))
1178                 t = nextType(t);
1179     }
1180     
1181     fputs(fname,fp);
1182     fputs("(", fp);
1183     if (F && getFNp(F)) {
1184         for (i = 0; i < getFNp(F); i++) {
1185             genArg(getFPty(F,i), i, fp);
1186             if(i < getFNp(F)-1) {
1187                 fputs(",\n", fp);
1188                 fputs("\t\t", fp);
1189             }
1190         }
1191         fputs(");\n", fp);
1192     }
1193     else
1194         fputs(");\n", fp);
1195
1196     level--;
1197 }
1198
1199 static void genMultiCall(type_expr *t, char *fname, FILE *fp)
1200 {
1201     static int level = 0;
1202     func_t *F;
1203     int i,n;
1204     type_expr *T;
1205
1206     F = (func_t *) EiC_getInf(t);
1207     level++;
1208
1209     fputs("\tstatic int nb = 0;\n\n",fp);
1210
1211     fprintf(fp,"\tswitch(nb)\n");
1212     fprintf(fp,"\t{\n");
1213     for (n = 0;n < MULTIPLEX;++n)
1214     {
1215         adjustNum = n+1-MULTIPLEX;
1216         fprintf(fp,"\tcase %d :\n",n);
1217
1218         if(Ncalls) {
1219             int k;
1220             for(k=0;k<Ncalls;++k) 
1221                 fprintf(fp,"\t%s%d = arg(%d,getargs(),ptr_t).p;\n",
1222                         callName,callNo[k]+adjustNum,callpos[k]);
1223         }
1224
1225         if (n == 0)
1226         {
1227             T = t;
1228         }
1229         else
1230         {
1231             t = T;
1232         }
1233
1234         if(nextType(t)) {
1235             t = nextType(t);
1236             genAffect(t,0,fp);
1237             if(t)
1238                 while(nextType(t))
1239                     t = nextType(t);
1240         }
1241
1242         fputs(fname,fp);
1243         fputs("(", fp);
1244         if (F && getFNp(F)) {
1245             for (i = 0; i < getFNp(F); i++) {
1246                 genArg(getFPty(F,i), i, fp);
1247                 if(i < getFNp(F)-1) {
1248                     fputs(",\n", fp);
1249                     fputs("\t\t", fp);
1250                 }
1251             }
1252             fputs(");\n", fp);
1253         }
1254         else
1255             fputs(");\n", fp);
1256
1257         level--;
1258         fprintf(fp,"\tbreak;\n");
1259     }
1260     fprintf(fp,"\t}\n");
1261     fprintf(fp,"\t++nb;\n");
1262     fprintf(fp,"\tnb %%= %d;\n",MULTIPLEX);
1263     adjustNum = 0;
1264 }
1265
1266
1267 static void genFunctions(int tab, int expand, 
1268                   token_t * e1, 
1269                   char *mname, 
1270                   int allowed(), FILE *fp)
1271 {
1272     int i, n, t;
1273     int multiplexed;
1274     symentry_t *sym;
1275     
1276     for (i = 0; i < HSIZE; i++)
1277         for (sym = EiC_HTAB[i]; sym; sym = sym->next) {
1278             if ((t = EiC_gettype(sym->type)) == t_eic || sym->nspace != tab)
1279                 continue;
1280
1281             if(e1 && e1->Type && ! EiC_sametypes(e1->Type,sym->type))
1282                 continue;
1283
1284             if(mname && strcmp(mname,sym->fname) != 0)
1285                 continue;
1286             
1287             if(allowed && !allowed(t))
1288                 continue;
1289
1290             n = 1;
1291             multiplexed = 0;
1292             while (n)
1293             {
1294                 if(DoCallBackNames(EiC_getInf(sym->type),fp)) {
1295                     int k = 0;
1296                     if (!multiplexed)
1297                     {
1298                         multiplexed = 1;
1299                         n = MULTIPLEX;
1300                     }
1301                     while(k<Ncalls) {
1302                         genCallBackFunc(sym->type,k++,fp);
1303                     }
1304                 }
1305                 --n;
1306             }
1307
1308             fputs("static val_t eic_",fp);
1309             fputs(sym->id, fp);
1310             fputs("(void)\n",fp);
1311             fputs("{\n",fp);
1312             
1313             fputs("\tval_t v;\n",fp);
1314             /*fputs("\tstatic int nb = 0;\n",fp);*/
1315
1316             if (multiplexed)
1317             {
1318                 genMultiCall(sym->type, sym->id, fp);
1319             }
1320             else
1321             {
1322                 genCall(sym->type, sym->id, fp);
1323             }
1324             
1325             fputs("\n",fp);
1326             fputs("\treturn v;\n",fp);
1327             fputs("}\n\n",fp);
1328
1329         }
1330 }
1331
1332
1333
1334
1335
1336
1337 static void genInterface(int tab, 
1338                   int expand, 
1339                   token_t * e1, 
1340                   char *mname, 
1341                   FILE *fp)
1342 {
1343     char *pt;
1344     int i, t;
1345     symentry_t *sym;
1346     char iname[255]; 
1347   
1348     strcpy(iname,mname);
1349     pt = strrchr(iname,'.');
1350     if (pt)
1351     {
1352         *pt = '\0';
1353     }
1354     pt = strrchr(iname,'/');
1355     if (pt)
1356     {
1357         ++pt;
1358     }
1359     else
1360     {
1361         pt = iname;
1362     }
1363
1364     fputs("/**********************************/\n\n",fp);
1365
1366     fprintf(fp,"void module_%s()\n",pt);
1367     fputs("{\n",fp);
1368
1369
1370     for (i = 0; i < HSIZE; i++)
1371         for (sym = EiC_HTAB[i]; sym; sym = sym->next) {
1372
1373             if ((t = EiC_gettype(sym->type)) == t_eic || sym->nspace != tab)
1374                 continue;
1375
1376             if(e1 && e1->Type && ! EiC_sametypes(e1->Type,sym->type))
1377                 continue;
1378
1379             if(mname && strcmp(mname,sym->fname) != 0)
1380                 continue;
1381             
1382             if(EiC_IsFunc(t) || sym->sclass == c_typedef || sym->sclass == c_enum)
1383                 continue;
1384
1385             fprintf(fp,"\tEiC_parseString(\"");
1386             EiC__generateType(sym->type,sym->id,fp,1);
1387             fprintf(fp," @ %%ld;\", (long)&%s);\n",sym->id);
1388         }
1389
1390
1391
1392     for (i = 0; i < HSIZE; i++)
1393         for (sym = EiC_HTAB[i]; sym; sym = sym->next) {
1394
1395             if ((t = EiC_gettype(sym->type)) == t_eic || sym->nspace != tab)
1396                 continue;
1397
1398             if(e1 && e1->Type && ! EiC_sametypes(e1->Type,sym->type))
1399                 continue;
1400
1401             if(mname && strcmp(mname,sym->fname) != 0)
1402                 continue;
1403             
1404             if(!EiC_IsFunc(t))
1405                 continue;
1406
1407             fprintf(fp,"\tEiC_add_builtinfunc(\"%s\",eic_%s);\n",sym->id,sym->id);
1408         }
1409
1410     fputs("}\n\n",fp);
1411     fputs("/**********************************/\n\n",fp);
1412 }
1413
1414 static void genHeader(char *mname, FILE *fp)
1415 {
1416     fputs("#include <stdlib.h>\n"
1417           "#include <varargs.h>\n"
1418           "#include <limits.h>\n"
1419           "#include \"eic.h\"\n",fp);
1420     fprintf(fp,"#include \"%s\"\n",mname);
1421     fputs("\n\n",fp);
1422 }
1423
1424 static void genModule(int tab, int expand, token_t * e1, char *mname)
1425 {
1426   FILE *fp = stdout;
1427
1428   if(EiC_lexan() == INT)
1429       MULTIPLEX = token->Val.ival;
1430   else
1431       retractlexan();
1432
1433   if(EiC_lexan() == STR) {
1434     fp = fopen(token->Val.p.p,"w");
1435     EiC_formatMessage("redirecting to [%s]\n",(char*)token->Val.p.p);
1436     if(!fp) {
1437       EiC_warningerror("Failed to open file %s\n", token->Val.p.p);
1438       fp = stdout;
1439     }
1440   } else
1441     retractlexan();
1442
1443   genHeader(mname,fp);
1444   genFunctions(tab, expand, e1, mname, EiC_IsFunc,fp);
1445   genInterface(tab, expand, e1, mname,fp);
1446
1447
1448   if(fp != stdout)
1449     fclose(fp);
1450 }
1451
1452 /*
1453  *
1454  *      NEW EiC COMMAND !
1455  *      By Jean-Bruno Richard
1456  *
1457  */
1458 static int genCommand(void)
1459 {
1460     char EiC_nextchar(void);
1461     int EiC_IsIncluded(char *fname);
1462     char *buf;
1463     
1464     callBack=0;
1465     buf = getNextInput();
1466     if(buf[0]) {
1467         if(!EiC_IsIncluded(buf))
1468              EiC_warningerror("Failed to find %s",buf); 
1469         else {
1470             genModule(stand_tab,0,NULL,buf);
1471         }
1472     } else 
1473              EiC_warningerror("Need a included file name for generating module"); 
1474     return 1;
1475 }
1476 #endif
1477
1478
1479
1480 static void establish_ARs(void)
1481 {
1482     EiC_ENV->LARsize = 4000;
1483     EiC_ENV->ARsize =  3000;
1484     EiC_ENV->LAR =(AR_t*)xmalloc(sizeof(AR_t)*EiC_ENV->LARsize);
1485     EiC_ENV->AR = (AR_t*)xmalloc(sizeof(AR_t)*EiC_ENV->ARsize);
1486 }
1487
1488 void EiC_init_EiC(void)
1489 {
1490     EiC_ENV = (environ_t *) xcalloc(1, sizeof(environ_t));
1491     EiC_ENV->CODE.Filename = "::EiC::";
1492
1493     establish_ARs();
1494     EiC_initpp();
1495     EiC_work_tab = stand_tab;
1496     /*init_hashtab(31);*/
1497     /* add EiC command line functions */
1498     add_eicfunc("listcode", toggle_listcode);
1499     add_eicfunc("interpreter", toggle_interp);
1500     add_eicfunc("variables", showhashtab);
1501     add_eicfunc("exit", EiC_exit_EiC);
1502     add_eicfunc("quit", EiC_exit_EiC);
1503     add_eicfunc("timer", toggle_timer);
1504     add_eicfunc("showline", toggle_showline);
1505     add_eicfunc("show", show);
1506     add_eicfunc("memdump", toggle_memdump);
1507     add_eicfunc("memtrace", toggle_memtrace);
1508     add_eicfunc("rm", rm);
1509     add_eicfunc("trace",toggle_trace);
1510     add_eicfunc("verbose",toggle_verbose);
1511     add_eicfunc("interface",toggle_interface);
1512
1513 #ifndef NO_HISTORY
1514     add_eicfunc("history",showhistory);
1515 #endif
1516     add_eicfunc("help", showHelp);
1517     add_eicfunc("status",EiCstatus);
1518     add_eicfunc("includes",toggle_includes);
1519     add_eicfunc("files",filesCommand);
1520     add_eicfunc("clear",clearCommand);
1521 #ifndef NO_AUTOGEN
1522     add_eicfunc("gen",genCommand);
1523     add_eicfunc("reset",ResetEiC);
1524     /* Remenber to modify help message too... */
1525 #endif
1526 }
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536