2 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3 * See the copyright notice in the ACK home directory, in the file "Copyright".
13 static char rcs_id[] = "$Id: mkdispatch.c,v 1.6 1994/06/24 10:03:13 ceriel Exp $" ;
16 /* This program reads the human readable interpreter specification
17 and produces a efficient machine representation that can be
18 translated by a C-compiler.
21 #define NOTAB 600 /* The max no of interpreter specs */
25 struct opform intable[NOTAB] ;
26 struct opform *lastform = intable-1 ;
32 extern char em_mnem[][4] ;
33 char esca1[] = "escape1" ;
34 char esca2[] = "escape2" ;
35 #define ename(no) ((no)==ESCAP1?esca1:(no)==ESCAP2?esca2:em_mnem[(no)])
37 extern char em_flag[] ;
39 main(argc,argv) char **argv ; {
41 if ( freopen(argv[1],"r",stdin)==NULL) {
42 fatal("Cannot open %s",argv[1]) ;
46 if ( freopen(argv[2],"w",stdout)==NULL) {
47 fatal("Cannot create %s",argv[2]) ;
51 fatal("%s [ file [ file ] ]",argv[0]) ;
64 register struct opform *nextform ;
68 for ( nextform=intable ;
69 !feof(stdin) && nextform<&intable[NOTAB] ; ) {
71 if ( *firstid=='\n' || feof(stdin) ) continue ;
73 nextform->i_opcode = getmnem(firstid) ;
74 nextform->i_flag = decflag(ident()) ;
75 switch ( nextform->i_flag&OPTYPE ) {
78 nextform->i_num = atoi(ident()) ;
81 nextform->i_low = atoi(ident()) ;
82 if ( *ident()!='\n' ) {
84 error("End of line expected");
85 while ( (c=readchar())!='\n' && c!=EOF ) ;
89 if ( !feof(stdin) ) fatal("Internal table too small") ;
93 /* skip spaces and tabs, anything up to space,tab or eof is
95 Anything from # to end-of-line is an end-of-line.
96 End-of-line is an identifier all by itself.
99 static char array[200] ;
105 } while ( c==' ' || c=='\t' ) ;
106 for ( cc=array ; cc<&array[(sizeof array) - 1] ; cc++ ) {
110 } while ( c!='\n' && c!=EOF ) ;
113 if ( c=='\n' && cc==array ) break ;
119 if ( c==' ' || c=='\t' || c==EOF ) break ;
125 int getmnem(str) char *str ; {
128 for ( ptr = em_mnem ; *ptr<= &em_mnem[sp_lmnem-sp_fmnem][0] ; ptr++ ) {
129 if ( strcmp(*ptr,str)==0 ) return (ptr-em_mnem) ;
131 error("Illegal mnemonic") ;
135 error(str,a1,a2,a3,a4,a5,a6) /* VARARGS1 */ char *str ; {
136 if ( !atend ) fprintf(stderr,"line %d: ",line) ;
137 fprintf(stderr,str,a1,a2,a3,a4,a5,a6) ;
138 fprintf(stderr,"\n");
142 mess(str,a1,a2,a3,a4,a5,a6) /* VARARGS1 */ char *str ; {
143 if ( !atend ) fprintf(stderr,"line %d: ",line) ;
144 fprintf(stderr,str,a1,a2,a3,a4,a5,a6) ;
145 fprintf(stderr,"\n");
148 fatal(str,a1,a2,a3,a4,a5,a6) /* VARARGS1 */ char *str ; {
149 error(str,a1,a2,a3,a4,a5,a6) ;
155 check(val) int val ; {
156 if ( val!=ILLGL ) error("Illegal flag combination") ;
159 int decflag(str) char *str ; {
166 type=escape=range=wordm=notzero= ILLGL ;
167 while ( *str ) switch ( *str++ ) {
169 check(type) ; type=OPMINI ; break ;
171 check(type) ; type=OPSHORT ; break ;
173 check(type) ; type=OPNO ; break ;
175 check(type) ; type=OP8 ; break ;
177 check(type) ; type=OP16 ; break ;
179 check(type) ; type=OP32 ; break ;
181 check(type) ; type=OP64 ; break ;
183 check(type) ; type=OP16U ; break ;
185 check(escape) ; escape=0 ; break ;
187 check(range) ; range= 2 ; break ;
189 check(range) ; range= 1 ; break ;
191 check(wordm) ; wordm=0 ; break ;
193 check(notzero) ; notzero=0 ; break ;
195 error("Unknown flag") ;
197 if ( type==ILLGL ) error("Type must be specified") ;
201 if ( escape!=ILLGL ) error("Conflicting escapes") ;
208 if ( notzero!=ILLGL ) mess("Improbable OPNZ") ;
209 if ( type==OPNO && range!=ILLGL ) {
210 mess("No operand in range") ;
213 if ( escape!=ILLGL ) type|=OPESC ;
214 if ( wordm!=ILLGL ) type|=OPWORD ;
216 case ILLGL : type|=OP_BOTH ;
217 if ( type==OPMINI || type==OPSHORT )
218 error("Minies and shorties must have P or N") ;
220 case 1 : type|=OP_POS ; break ;
221 case 2 : type|=OP_NEG ; break ;
223 if ( notzero!=ILLGL ) type|=OPNZ ;
227 /* ----------- checking --------------*/
229 int ecodes[256],codes[256],lcodes[256] ;
230 char eflags[256], flags[256], lflags[256] ;
231 int elows[256], lows[256], llows[256];
233 #define NMNEM (sp_lmnem-sp_fmnem+1)
238 char negc[NMNEM], zc[NMNEM], posc[NMNEM], lnegc[NMNEM], lposc[NMNEM] ;
242 register struct opform *next ;
245 for ( i=0 ; i<NMNEM ; i++ ) negc[i]=zc[i]=posc[i]=0 ;
246 for ( i=0 ; i<256 ; i++ ) lcodes[i]= codes[i]= ecodes[i]= -1 ;
247 codes[254]=ESCAP1; codes[255]=ESCAP2;
250 for ( next=intable ; next<=lastform ; next++ ) {
252 flag = next->i_flag&0377 ;
253 opc = next->i_opcode&0377 ;
254 low = next->i_low&0377 ;
255 chkc(flag,low,opc,low) ;
256 switch(flag&OPTYPE) {
257 case OPNO : zc[opc]++ ; break ;
260 for ( i=1 ; i<((next->i_num)&0377) ; i++ ) {
261 chkc(flag,low+i,opc,low) ;
263 if ( !(em_flag[opc]&PAR_G) &&
264 (flag&OPRANGE)==OP_BOTH) {
265 mess("Mini's and shorties should have P or N");
269 error("OP8 is removed") ;
274 else if ( flag&OP_POS )
280 else if ( flag&OP_POS )
286 error("Illegal type") ;
291 for ( i=0 ; i<256 ; i++ ) if ( codes[i]== -1 ) {
292 mess("interpreter opcode %d not used",i) ;
294 for ( opc=0 ; opc<NMNEM ; opc++ ) {
295 switch(em_flag[opc]&EM_PAR) {
297 ckop(opc,MUST,FORB,FORB) ;
303 ckop(opc,FORB,MAY,MAY) ;
311 ckop(opc,FORB,MAY,FORB) ;
314 ckop(opc,FORB,MAY,FORB) ;
317 ckop(opc,FORB,MUST,MUST) ;
320 ckop(opc,MUST,MAY,FORB) ;
323 error("Unknown instruction type of %s",ename(opc)) ;
329 chkc(flag,icode,emc,low) {
331 if ( ecodes[icode]!=-1 ) {
332 mess("Escaped opcode %d used by %s and %s",
333 icode,ename(emc),ename(ecodes[icode])) ;
338 } else switch ( flag&OPTYPE ) {
340 if ( codes[icode]!=-1 ) {
341 mess("Opcode %d used by %s and %s",
342 icode,ename(emc),ename(codes[icode])) ;
350 if ( lcodes[icode]!=-1 ) {
351 mess("Long opcode %d used by %s and %s",
352 icode,ename(emc),ename(lcodes[icode])) ;
362 if ( zc[emc]>1 ) mess("More then one OPNO for %s",ename(emc)) ;
363 if ( posc[emc]>1 ) mess("More then one OP16(pos) for %s",ename(emc)) ;
364 if ( negc[emc]>1 ) mess("More then one OP16(neg) for %s",ename(emc)) ;
365 if ( lposc[emc]>1 ) mess("More then one OP32(pos) for %s",ename(emc)) ;
366 if ( lnegc[emc]>1 ) mess("More then one OP32(neg) for %s",ename(emc)) ;
369 if ( zc[emc]==0 ) mess("No OPNO for %s",ename(emc)) ;
372 if ( zc[emc]==1 ) mess("Forbidden OPNO for %s",ename(emc)) ;
377 if ( posc[emc]==0 ) mess("No OP16(pos) for %s",ename(emc)) ;
381 mess("Forbidden OP16(pos) for %s",ename(emc)) ;
386 if ( negc[emc]==0 ) mess("No OP16(neg) for %s",ename(emc)) ;
390 mess("Forbidden OP16(neg) for %s",ename(emc)) ;
395 static int pushchar ;
405 if ( feof(stdin) ) return EOF ;
408 if ( c=='\n' ) line++ ;
414 fatal("Double pushback") ;
418 if ( c=='\n' ) line-- ;
425 for (i = 0; i < 256;) {
426 if (!(i % 8)) printf("\n%d", i);
427 printf("\t%s", ename(codes[i]));
429 prx(flags[i],lows[i],i);
434 printf("\nDISPATCH2");
435 for (i = 0; i < 256;) {
436 if (ecodes[i] != -1) {
437 if (!(i % 8)) printf("\n%d", i);
438 printf("\t%s", ename(ecodes[i]));
439 prx(eflags[i],elows[i],i);
445 printf("\nDISPATCH3");
447 while (lcodes[i] != -1) {
448 if (!(i % 8)) printf("\n%d", i);
449 printf("\t%s", ename(lcodes[i]));
450 prx(lflags[i],llows[i],i);
453 while (i++ % 8) putchar('\t');
471 if (flg&OP_POS) putchar('p');
472 else if (flg&OP_NEG) putchar('n');
474 if (flg&OPWORD) putchar('w');
477 if (flg&OP_POS) putchar('P');
478 else if (flg&OP_NEG) putchar('N');
480 if (flg&OPWORD) putchar('w');
483 if (flg & OPWORD) putchar('w');
487 if (flg & OPNZ) arg++;
488 if (flg & OP_NEG) arg = -arg - 1;
490 if((flg&OPTYPE) == OPMINI && (flg & OPWORD)) putchar('W');