Update the changelog
[opencv] / apps / cvenv / EiC / 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 = EiC_lookup(1, name);
809     if(!sym)
810     {
811         sym = EiC_insertLUT(stand_tab, name, ID);
812         EiC_freetype(sym->type);
813         sym->level = 1;
814         sym->val.vfunc = vfunc;
815         sym->type = EiC_addtype(t_builtin,NULL);
816     }
817     else
818     {
819         sym->level = 1;
820         sym->val.vfunc = vfunc;
821         sym->type->obj = t_builtin;
822 /*        EiC_freetype(sym->type->nxt);
823         sym->type->nxt = 0;
824 */
825     }
826     return sym;
827 }
828
829
830 void EiC_comm_switch(void)
831 {
832     int EiC_insertpath(char *);
833     int EiC_removepath(char *);
834     void EiC_listpath(void);
835     char EiC_nextchar(void);
836     
837     char *buf;
838     if (EiC_lexan() == ID) {
839         if(EiC_gettype(token->Val.sym->type) == ID) {
840             EiC_remsym(token->Val.sym);
841         }
842
843         buf = getNextInput();
844             
845         switch(EiC_LEXEM[0]) {
846           case 'I':
847             if(!*buf || !EiC_insertpath(buf))
848              EiC_warningerror("Failed to add path"); 
849             break;
850           case 'R':
851             if(!*buf || !EiC_removepath(buf))
852              EiC_warningerror("Failed to remove path"); 
853             break;
854           case 'L':
855             EiC_listpath();break;
856           default:          
857             EiC_error("Unknown command switch");
858         }                   
859             
860     } else 
861         EiC_error("Expected command switch");
862
863 }
864
865
866
867 /*                                                                      */
868 /* Jean-Bruno Richard personal Modification inside eicmod.c             */
869 /*                                                                      */
870 /* Semi-automatic module code generation                                */
871 /* functions. Thanks to the function prototype, it's possible to        */
872 /* generate it's interfacing function to EiC.                           */
873 /* Few manual modification of the generated code are sometimes needed,  */
874 /* but it helps a lot....                                               */
875 /* How to use it :                                                      */
876 /* Launch EiC, #include the desired header file                         */
877 /* (Example #include "gl.h")                                            */
878 /* and use the new EiC command :gen with the name of the header file    */
879 /* (In the example :gen gl.h) EiC will output the interface to stdout   */
880 /* Hope it helps.....   :                                               */
881 /* jean-bruno.richard@mg2.com                                           */
882
883
884
885 #ifndef NO_AUTOGEN
886
887
888 static int callBack=0;
889 static  int * callNo =NULL;
890 static  int *callpos = NULL;
891 static int Ncalls = 0;
892 static char *callName="EiC_Cfunc_";
893 static char *middleName="MiddleOne_";
894 static int  MULTIPLEX = 1;
895
896 static void EiC__generateType(type_expr *t, char *id,FILE *fp, int level)
897 {
898
899     struct_t *S;
900
901     char tmp[100];
902     char out[100];
903
904     strcpy(out,id);
905
906     do {
907         switch(EiC_gettype(t)) {
908             case t_pointer: /* pointer */
909                 sprintf(tmp,"*%s",out);
910                 strcpy(out,tmp);
911                 break;
912
913             case t_char:    sprintf(tmp,"%s %s", "char", out); strcpy(out,tmp); break;
914             case t_uchar:   sprintf(tmp,"%s %s", "unsigned char",out);strcpy(out,tmp); break;
915             case t_short:   sprintf(tmp,"%s %s",  "short",out);strcpy(out,tmp);break;
916             case t_ushort:  sprintf(tmp,"%s %s",  "unsigned short",out);strcpy(out,tmp);break;
917             case t_int:     sprintf(tmp,"%s %s",  "int",out);strcpy(out,tmp);break;
918             case t_uint:    sprintf(tmp,"%s %s",  "unsigned",out);strcpy(out,tmp);break;
919             case t_long:    sprintf(tmp,"%s %s",  "long",out);strcpy(out,tmp);break;
920             case t_ulong:   sprintf(tmp,"%s %s",  "unsigned long",out);strcpy(out,tmp);break;
921             case t_float:   sprintf(tmp,"%s %s",  "float",out);strcpy(out,tmp);break;
922             case t_double:  sprintf(tmp,"%s %s",  "double",out);strcpy(out,tmp);break;
923             case t_void:  sprintf(tmp,"%s %s",  "void",out);strcpy(out,tmp);break;
924
925             case t_struct:
926             case t_union:
927                 if(EiC_gettype(t) == t_union) 
928                     fputs("union {",fp);
929                 else
930                     fputs("struct {",fp);
931
932                 S = EiC_getInf(t);
933                 if(!S) {
934                     fputs("Incomplete", fp);
935                     break;
936                 }
937                 level++;
938                 if (level <= 2) {
939                     int i;
940                     for (i = 0; i < S->n; i++) {
941                         EiC__generateType(S->type[i], S->id[i], fp,level);
942                         fputs(";",fp);
943                     }
944                 }
945                 sprintf(tmp,"} %s ",out);
946                 strcpy(out,tmp);
947                 level--;
948                 break;
949
950             case t_array: /* array */ 
951                 if(out[0] ==  '*') {
952                     sprintf(tmp,"(%s)%s",out,"[]");
953                     strcpy(out,tmp);
954                 } else {
955                     sprintf(tmp,"[%d]",(int)EiC_getInf(t));
956                     strcat(out, tmp);
957                 }
958                 break;
959
960                 
961         }
962
963     } while ( (t=nextType(t)));
964
965     fprintf(fp,"%s",out);
966 }
967
968 static int DoCallBackNames(func_t *F, FILE *fp)
969 {
970     int x = 0;
971     if (F) {
972         int i;
973         callpos = realloc(callpos,sizeof(int)*getFNp(F));
974         for (i = 0; i < getFNp(F); i++) {
975             type_expr *t = getFPty(F,i);
976             if(EiC_gettype(t) == t_pointer && 
977                EiC_IsFunc(EiC_gettype(nextType(t)))) {
978                 callNo = realloc(callNo, sizeof(*callNo) * (x+1));
979                 callpos[x] = i;
980                 callNo[x] = callBack++;
981                 fprintf(fp,"static void * %s%d = NULL;\n",callName,callNo[x]);
982                 x++;
983             }
984         }
985     }
986     return (Ncalls = x);
987 }
988
989
990 static void genCallBackFunc(type_expr *ty, 
991                             int p, 
992                             FILE *fp)
993 {
994     char buff[10];
995     func_t *F, *F2;
996     int i,v, var=0;
997     type_expr *t;
998
999     F = EiC_getInf(ty);
1000     t = getFPty(F,callpos[p]);
1001     t = nextType(t);
1002     F2 = EiC_getInf(t);
1003
1004     fprintf(fp,"static ");
1005     EiC_showdectype(nextType(t),0,fp);
1006
1007     fprintf(fp," %s%d(",middleName,callNo[p]);
1008
1009     /* check 4 varadic function calls */
1010     for(i=0;i<getFNp(F2);i++) 
1011         if(EiC_gettype(getFPty(F2,i)) == t_var) {
1012             var = 1;
1013             break;
1014         }
1015
1016     if(!var) {
1017         for(i=0;i<getFNp(F2)-1;i++) {
1018             if((v=EiC_gettype(getFPty(F2,i))) == t_void)
1019                 continue;
1020             sprintf(buff,"x%d, ",i);
1021             EiC__generateType(getFPty(F2,i),buff,fp,1);
1022
1023         }
1024         if((v=EiC_gettype(getFPty(F2,i))) != t_void)  {
1025             sprintf(buff,"x%d ",i);
1026             EiC__generateType(getFPty(F2,i),buff,fp,1);
1027         }
1028         fprintf(fp,")\n{\n");
1029
1030         for (i = 0; i < getFNp(F2); i++) {
1031             if(EiC_gettype(getFPty(F2,i)) == t_void)
1032                 continue;
1033             fprintf(fp,"    setArg(%d, %s%d, ",i,callName,callNo[p]);
1034
1035             EiC__generateType(getFPty(F2,i),"",fp,1);
1036
1037             fprintf(fp,",x%d);\n",i);
1038         }
1039
1040     } else {
1041         fprintf(fp," va_alist )  va_dcl\n{\n");
1042         fprintf(fp,"    void Auto_EiC_CallBack(code_t *callback, va_list ap);\n");
1043         fprintf(fp,"    va_list ap; va_start(ap);\n");
1044         fprintf(fp,"    Auto_EiC_CallBack(%s%d,ap);\n",callName,callNo[p]);
1045     } 
1046         
1047     fprintf(fp,"\n    EiC_callBack(%s%d);\n",callName,callNo[p]);
1048
1049     if(EiC_gettype(nextType(t)) != t_void) {
1050         fputs("    return EiC_ReturnValue( ",fp);
1051         /*EiC_showdectype(nextType(t),0,fp);*/
1052         EiC__generateType(nextType(t),"",fp,1);
1053         fputs(");\n",fp);
1054     }
1055     if(var)
1056         fputs("    va_end(ap);\n",fp);
1057     
1058     fputs("}\n\n",fp);
1059
1060 }
1061
1062
1063
1064 static void genArg(type_expr * t, int idx, FILE *fp)
1065 {
1066     int ob;
1067    if ((ob = EiC_gettype(t)) == t_void) {
1068       return;
1069    }
1070
1071    if(ob == t_pointer) {
1072        int k = EiC_gettype((nextType(t)));
1073        if(EiC_IsFunc(k)) {
1074            k = 0;
1075            while(k<Ncalls && callpos[k] != idx) k++;
1076            fprintf(fp,"%s%d",middleName,callNo[k]+adjustNum);
1077            return ;
1078        }
1079    }
1080        
1081     fputs("arg(",fp);
1082     fprintf(fp,"%d",idx);
1083     fputs(",getargs(),",fp);
1084
1085         switch (ob) {
1086           case t_char:  fputs("char)", fp); break;
1087           case t_uchar: fputs("char)", fp); break;
1088           case t_short: fputs("short)", fp); break;
1089           case t_ushort:fputs("short)", fp); break;
1090           case t_int:   fputs("int)", fp); break;
1091           case t_uint:  fputs("unsigned)", fp); break;
1092           case t_long:  fputs("long) ", fp); break;
1093           case t_ulong: fputs("unsigned long)", fp); break;
1094           case t_float: fputs("float)", fp); break;
1095           case t_double:fputs("double)", fp); break;
1096           case t_pointer:
1097               fputs("ptr_t).p",fp);
1098               break; 
1099           default: fputs("Uknown identifier", fp); return;
1100         }
1101 }
1102
1103 static void genAffect(type_expr * t, int expand, FILE *fp)
1104 {
1105  
1106         fputs("\t", fp);
1107         switch (EiC_gettype(t)) {
1108           case t_char: 
1109           case t_short:
1110           case t_int:   fputs("v.ival = ", fp); break;
1111           case t_uchar:
1112           case t_ushort:
1113           case t_uint:  fputs("v.uival = ", fp); break;
1114           case t_long:  fputs("v.lval = ", fp); break;
1115           case t_ulong: fputs("v.ulval = ", fp); break;
1116           case t_float: 
1117           case t_double:fputs("v.dval = ", fp); break;
1118
1119           case t_pointer: 
1120             if(isunsafe(t)) 
1121               fputs("v.p.ep = (void*)ULONG_MAX;\n"
1122                     "\tv.p.sp = v.p.p = ",fp);
1123             else if(issafe(t)) 
1124               fputs("v.p.ep = v.p.sp = v.p.p = ", fp);
1125             break;
1126           case t_void:  break;
1127           case t_hidden: break;
1128             
1129 /*        case t_array:
1130             fprintf(fp,"ARY[%d]",(int) EiC_getInf(t));
1131             break;
1132           case t_union:
1133           case t_struct:
1134             S = EiC_getInf(t);
1135             if(!S) {
1136                 fputs("Incomplete", fp);
1137                 break;
1138             }
1139             if (EiC_gettype(t) == t_struct)
1140                 fprintf(fp,"struct: size  %u bytes",S->tsize);
1141             else
1142                 fprintf(fp,"union: size  %u bytes",S->tsize);
1143             if (expand) {
1144                 level++;
1145                 fputc('\n', fp);
1146                 if (level <= 2) {
1147                     int j;
1148                     for (i = 0; i < S->n; i++) {
1149                         for (j = 0; j < level; j++)
1150                             fputc('\t', fp);
1151                         fputs(S->id[i], fp);
1152                         fputs(" -> ", fp);
1153                         EiC_showdectype(S->type[i], expand,fp);
1154                         fputc('\n', fp);
1155                     }
1156                 }
1157                 level--;
1158             }
1159             break;
1160           case t_ref: fputs("Reference ",fp);break;
1161           case ID: fputs("Identifier ", fp); break;
1162 */
1163           default: fputs("Uknown identifier", fp); return;
1164         }
1165 }
1166
1167 static void genCall(type_expr *t, char *fname, FILE *fp)
1168 {
1169     static int level = 0;
1170     func_t *F;
1171     int i;
1172
1173     F = (func_t *) EiC_getInf(t);
1174     level++;
1175
1176     fputs("\n", fp);
1177
1178     if(Ncalls) {
1179         int k;
1180         for(k=0;k<Ncalls;++k) 
1181             fprintf(fp,"\t%s%d = arg(%d,getargs(),ptr_t).p;\n",
1182                     callName,callNo[k],callpos[k]);
1183     }
1184
1185     if(nextType(t)) {
1186         t = nextType(t);
1187         genAffect(t,0,fp);
1188         if(t)
1189             while(nextType(t))
1190                 t = nextType(t);
1191     }
1192     
1193     fputs(fname,fp);
1194     fputs("(", fp);
1195     if (F && getFNp(F)) {
1196         for (i = 0; i < getFNp(F); i++) {
1197             genArg(getFPty(F,i), i, fp);
1198             if(i < getFNp(F)-1) {
1199                 fputs(",\n", fp);
1200                 fputs("\t\t", fp);
1201             }
1202         }
1203         fputs(");\n", fp);
1204     }
1205     else
1206         fputs(");\n", fp);
1207
1208     level--;
1209 }
1210
1211 static void genMultiCall(type_expr *t, char *fname, FILE *fp)
1212 {
1213     static int level = 0;
1214     func_t *F;
1215     int i,n;
1216     type_expr *T;
1217
1218     F = (func_t *) EiC_getInf(t);
1219     level++;
1220
1221     fputs("\tstatic int nb = 0;\n\n",fp);
1222
1223     fprintf(fp,"\tswitch(nb)\n");
1224     fprintf(fp,"\t{\n");
1225     for (n = 0;n < MULTIPLEX;++n)
1226     {
1227         adjustNum = n+1-MULTIPLEX;
1228         fprintf(fp,"\tcase %d :\n",n);
1229
1230         if(Ncalls) {
1231             int k;
1232             for(k=0;k<Ncalls;++k) 
1233                 fprintf(fp,"\t%s%d = arg(%d,getargs(),ptr_t).p;\n",
1234                         callName,callNo[k]+adjustNum,callpos[k]);
1235         }
1236
1237         if (n == 0)
1238         {
1239             T = t;
1240         }
1241         else
1242         {
1243             t = T;
1244         }
1245
1246         if(nextType(t)) {
1247             t = nextType(t);
1248             genAffect(t,0,fp);
1249             if(t)
1250                 while(nextType(t))
1251                     t = nextType(t);
1252         }
1253
1254         fputs(fname,fp);
1255         fputs("(", fp);
1256         if (F && getFNp(F)) {
1257             for (i = 0; i < getFNp(F); i++) {
1258                 genArg(getFPty(F,i), i, fp);
1259                 if(i < getFNp(F)-1) {
1260                     fputs(",\n", fp);
1261                     fputs("\t\t", fp);
1262                 }
1263             }
1264             fputs(");\n", fp);
1265         }
1266         else
1267             fputs(");\n", fp);
1268
1269         level--;
1270         fprintf(fp,"\tbreak;\n");
1271     }
1272     fprintf(fp,"\t}\n");
1273     fprintf(fp,"\t++nb;\n");
1274     fprintf(fp,"\tnb %%= %d;\n",MULTIPLEX);
1275     adjustNum = 0;
1276 }
1277
1278
1279 static void genFunctions(int tab, int expand, 
1280                   token_t * e1, 
1281                   char *mname, 
1282                   int allowed(), FILE *fp)
1283 {
1284     int i, n, t;
1285     int multiplexed;
1286     symentry_t *sym;
1287     
1288     for (i = 0; i < HSIZE; i++)
1289         for (sym = EiC_HTAB[i]; sym; sym = sym->next) {
1290             if ((t = EiC_gettype(sym->type)) == t_eic || sym->nspace != tab)
1291                 continue;
1292
1293             if(e1 && e1->Type && ! EiC_sametypes(e1->Type,sym->type))
1294                 continue;
1295
1296             if(mname && strcmp(mname,sym->fname) != 0)
1297                 continue;
1298             
1299             if(allowed && !allowed(t))
1300                 continue;
1301
1302             n = 1;
1303             multiplexed = 0;
1304             while (n)
1305             {
1306                 if(DoCallBackNames(EiC_getInf(sym->type),fp)) {
1307                     int k = 0;
1308                     if (!multiplexed)
1309                     {
1310                         multiplexed = 1;
1311                         n = MULTIPLEX;
1312                     }
1313                     while(k<Ncalls) {
1314                         genCallBackFunc(sym->type,k++,fp);
1315                     }
1316                 }
1317                 --n;
1318             }
1319
1320             fputs("static val_t eic_",fp);
1321             fputs(sym->id, fp);
1322             fputs("(void)\n",fp);
1323             fputs("{\n",fp);
1324             
1325             fputs("\tval_t v;\n",fp);
1326             /*fputs("\tstatic int nb = 0;\n",fp);*/
1327
1328             if (multiplexed)
1329             {
1330                 genMultiCall(sym->type, sym->id, fp);
1331             }
1332             else
1333             {
1334                 genCall(sym->type, sym->id, fp);
1335             }
1336             
1337             fputs("\n",fp);
1338             fputs("\treturn v;\n",fp);
1339             fputs("}\n\n",fp);
1340
1341         }
1342 }
1343
1344
1345
1346
1347
1348
1349 static void genInterface(int tab, 
1350                   int expand, 
1351                   token_t * e1, 
1352                   char *mname, 
1353                   FILE *fp)
1354 {
1355     char *pt;
1356     int i, t;
1357     symentry_t *sym;
1358     char iname[255]; 
1359   
1360     strcpy(iname,mname);
1361     pt = strrchr(iname,'.');
1362     if (pt)
1363     {
1364         *pt = '\0';
1365     }
1366     pt = strrchr(iname,'/');
1367     if (pt)
1368     {
1369         ++pt;
1370     }
1371     else
1372     {
1373         pt = iname;
1374     }
1375
1376     fputs("/**********************************/\n\n",fp);
1377
1378     fprintf(fp,"void module_%s()\n",pt);
1379     fputs("{\n",fp);
1380
1381
1382     for (i = 0; i < HSIZE; i++)
1383         for (sym = EiC_HTAB[i]; sym; sym = sym->next) {
1384
1385             if ((t = EiC_gettype(sym->type)) == t_eic || sym->nspace != tab)
1386                 continue;
1387
1388             if(e1 && e1->Type && ! EiC_sametypes(e1->Type,sym->type))
1389                 continue;
1390
1391             if(mname && strcmp(mname,sym->fname) != 0)
1392                 continue;
1393             
1394             if(EiC_IsFunc(t) || sym->sclass == c_typedef || sym->sclass == c_enum)
1395                 continue;
1396
1397             fprintf(fp,"\tEiC_parseString(\"");
1398             EiC__generateType(sym->type,sym->id,fp,1);
1399             fprintf(fp," @ %%ld;\", (long)&%s);\n",sym->id);
1400         }
1401
1402
1403
1404     for (i = 0; i < HSIZE; i++)
1405         for (sym = EiC_HTAB[i]; sym; sym = sym->next) {
1406
1407             if ((t = EiC_gettype(sym->type)) == t_eic || sym->nspace != tab)
1408                 continue;
1409
1410             if(e1 && e1->Type && ! EiC_sametypes(e1->Type,sym->type))
1411                 continue;
1412
1413             if(mname && strcmp(mname,sym->fname) != 0)
1414                 continue;
1415             
1416             if(!EiC_IsFunc(t))
1417                 continue;
1418
1419             fprintf(fp,"\tEiC_add_builtinfunc(\"%s\",eic_%s);\n",sym->id,sym->id);
1420         }
1421
1422     fputs("}\n\n",fp);
1423     fputs("/**********************************/\n\n",fp);
1424 }
1425
1426 static void genHeader(char *mname, FILE *fp)
1427 {
1428     fputs("#include <stdlib.h>\n"
1429           "#include <varargs.h>\n"
1430           "#include <limits.h>\n"
1431           "#include \"eic.h\"\n",fp);
1432     fprintf(fp,"#include \"%s\"\n",mname);
1433     fputs("\n\n",fp);
1434 }
1435
1436 static void genModule(int tab, int expand, token_t * e1, char *mname)
1437 {
1438   FILE *fp = stdout;
1439
1440   if(EiC_lexan() == INT)
1441       MULTIPLEX = token->Val.ival;
1442   else
1443       retractlexan();
1444
1445   if(EiC_lexan() == STR) {
1446     fp = fopen(token->Val.p.p,"w");
1447     EiC_formatMessage("redirecting to [%s]\n",(char*)token->Val.p.p);
1448     if(!fp) {
1449       EiC_warningerror("Failed to open file %s\n", token->Val.p.p);
1450       fp = stdout;
1451     }
1452   } else
1453     retractlexan();
1454
1455   genHeader(mname,fp);
1456   genFunctions(tab, expand, e1, mname, EiC_IsFunc,fp);
1457   genInterface(tab, expand, e1, mname,fp);
1458
1459
1460   if(fp != stdout)
1461     fclose(fp);
1462 }
1463
1464 /*
1465  *
1466  *      NEW EiC COMMAND !
1467  *      By Jean-Bruno Richard
1468  *
1469  */
1470 static int genCommand(void)
1471 {
1472     char EiC_nextchar(void);
1473     int EiC_IsIncluded(char *fname);
1474     char *buf;
1475     
1476     callBack=0;
1477     buf = getNextInput();
1478     if(buf[0]) {
1479         if(!EiC_IsIncluded(buf))
1480              EiC_warningerror("Failed to find %s",buf); 
1481         else {
1482             genModule(stand_tab,0,NULL,buf);
1483         }
1484     } else 
1485              EiC_warningerror("Need a included file name for generating module"); 
1486     return 1;
1487 }
1488 #endif
1489
1490
1491
1492 static void establish_ARs(void)
1493 {
1494     EiC_ENV->LARsize = 4000;
1495     EiC_ENV->ARsize =  3000;
1496     EiC_ENV->LAR =(AR_t*)xmalloc(sizeof(AR_t)*EiC_ENV->LARsize);
1497     EiC_ENV->AR = (AR_t*)xmalloc(sizeof(AR_t)*EiC_ENV->ARsize);
1498 }
1499
1500 void EiC_init_EiC(void)
1501 {
1502     EiC_ENV = (environ_t *) xcalloc(1, sizeof(environ_t));
1503     EiC_ENV->CODE.Filename = "::EiC::";
1504
1505     establish_ARs();
1506     EiC_initpp();
1507     EiC_work_tab = stand_tab;
1508     /*init_hashtab(31);*/
1509     /* add EiC command line functions */
1510     add_eicfunc("listcode", toggle_listcode);
1511     add_eicfunc("interpreter", toggle_interp);
1512     add_eicfunc("variables", showhashtab);
1513     add_eicfunc("exit", EiC_exit_EiC);
1514     add_eicfunc("quit", EiC_exit_EiC);
1515     add_eicfunc("timer", toggle_timer);
1516     add_eicfunc("showline", toggle_showline);
1517     add_eicfunc("show", show);
1518     add_eicfunc("memdump", toggle_memdump);
1519     add_eicfunc("memtrace", toggle_memtrace);
1520     add_eicfunc("rm", rm);
1521     add_eicfunc("trace",toggle_trace);
1522     add_eicfunc("verbose",toggle_verbose);
1523     add_eicfunc("interface",toggle_interface);
1524
1525 #ifndef NO_HISTORY
1526     add_eicfunc("history",showhistory);
1527 #endif
1528     add_eicfunc("help", showHelp);
1529     add_eicfunc("status",EiCstatus);
1530     add_eicfunc("includes",toggle_includes);
1531     add_eicfunc("files",filesCommand);
1532     add_eicfunc("clear",clearCommand);
1533 #ifndef NO_AUTOGEN
1534     add_eicfunc("gen",genCommand);
1535     add_eicfunc("reset",ResetEiC);
1536     /* Remenber to modify help message too... */
1537 #endif
1538 }
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548