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: maktab.c,v 2.7 1994/06/24 10:15:46 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 */
24 struct opform intable[NOTAB] ;
25 struct opform *lastform = intable-1 ;
32 extern char em_mnem[][4] ;
33 char esca[] = "escape" ;
34 #define ename(no) ((no)==ESCAP?esca:em_mnem[(no)])
36 extern char em_flag[] ;
38 main(argc,argv) char **argv ; {
40 if ( freopen(argv[1],"r",stdin)==NULL) {
41 fatal("Cannot open %s",argv[1]) ;
45 if ( freopen(argv[2],"w",stdout)==NULL) {
46 fatal("Cannot create %s",argv[2]) ;
50 fatal("%s [ file [ file ] ]",argv[0]) ;
63 register struct opform *nextform ;
69 for ( nextform=intable ;
70 !feof(stdin) && nextform<&intable[NOTAB] ; ) {
72 if ( *firstid=='\n' || feof(stdin) ) continue ;
74 nextform->i_opcode = getmnem(firstid) ;
75 nextform->i_flag = decflag(ident()) ;
76 switch ( nextform->i_flag&OPTYPE ) {
79 nextform->i_num = atoi(ident()) ;
82 nextform->i_low = atoi(ident()) ;
83 if ( *ident()!='\n' ) {
85 error("End of line expected");
86 while ( (c=readchar())!='\n' && c!=EOF ) ;
88 if ( oplength(nextform)>maxl ) maxl=oplength(nextform) ;
91 if ( !feof(stdin) ) fatal("Internal table too small") ;
96 /* skip spaces and tabs, anything up to space,tab or eof is
98 Anything from # to end-of-line is an end-of-line.
99 End-of-line is an identifier all by itself.
102 static char array[200] ;
108 } while ( c==' ' || c=='\t' ) ;
109 for ( cc=array ; cc<&array[(sizeof array) - 1] ; cc++ ) {
113 } while ( c!='\n' && c!=EOF ) ;
116 if ( c=='\n' && cc==array ) break ;
122 if ( c==' ' || c=='\t' || c==EOF ) break ;
128 int getmnem(str) char *str ; {
131 for ( ptr = em_mnem ; *ptr<= &em_mnem[sp_lmnem-sp_fmnem][0] ; ptr++ ) {
132 if ( strcmp(*ptr,str)==0 ) return (ptr-em_mnem) ;
134 error("Illegal mnemonic") ;
138 error(str,a1,a2,a3,a4,a5,a6) /* VARARGS1 */ char *str ; {
139 if ( !atend ) fprintf(stderr,"line %d: ",line) ;
140 fprintf(stderr,str,a1,a2,a3,a4,a5,a6) ;
141 fprintf(stderr,"\n");
145 mess(str,a1,a2,a3,a4,a5,a6) /* VARARGS1 */ char *str ; {
146 if ( !atend ) fprintf(stderr,"line %d: ",line) ;
147 fprintf(stderr,str,a1,a2,a3,a4,a5,a6) ;
148 fprintf(stderr,"\n");
151 fatal(str,a1,a2,a3,a4,a5,a6) /* VARARGS1 */ char *str ; {
152 error(str,a1,a2,a3,a4,a5,a6) ;
158 check(val) int val ; {
159 if ( val!=ILLGL ) error("Illegal flag combination") ;
162 int decflag(str) char *str ; {
169 type=escape=range=wordm=notzero= ILLGL ;
170 while ( *str ) switch ( *str++ ) {
172 check(type) ; type=OPMINI ; break ;
174 check(type) ; type=OPSHORT ; break ;
176 check(type) ; type=OPNO ; break ;
178 check(type) ; type=OP8 ; break ;
180 check(type) ; type=OP16 ; break ;
182 check(type) ; type=OP32 ; break ;
184 check(type) ; type=OP64 ; break ;
186 check(type) ; type=OP16U ; break ;
188 check(escape) ; escape=0 ; break ;
190 check(range) ; range= 2 ; break ;
192 check(range) ; range= 1 ; break ;
194 check(wordm) ; wordm=0 ; break ;
196 check(notzero) ; notzero=0 ; break ;
198 error("Unknown flag") ;
200 if ( type==ILLGL ) error("Type must be specified") ;
204 if ( escape!=ILLGL ) error("Conflicting escapes") ;
211 if ( notzero!=ILLGL ) mess("Improbable OPNZ") ;
212 if ( type==OPNO && range!=ILLGL ) {
213 mess("No operand in range") ;
216 if ( escape!=ILLGL ) type|=OPESC ;
217 if ( wordm!=ILLGL ) type|=OPWORD ;
219 case ILLGL : type|=OP_BOTH ;
220 if ( type==OPMINI || type==OPSHORT )
221 error("Minies and shorties must have P or N") ;
223 case 1 : type|=OP_POS ; break ;
224 case 2 : type|=OP_NEG ; break ;
226 if ( notzero!=ILLGL ) type|=OPNZ ;
231 register struct opform *next ;
232 int elem[sp_lmnem-sp_fmnem+1+1] ;
233 /* for each op points to first of descr. */
234 register int i,currop ;
238 qsort(intable,(lastform-intable)+1,sizeof intable[0],compare) ;
240 printf("int\tmaxinsl\t= %d ;\n",maxinsl) ;
242 printf("char opchoice[] = {\n") ;
243 for (next=intable ; next<=lastform ; next++ ) {
244 if ( (next->i_opcode&0377)!=currop ) {
246 currop<(next->i_opcode&0377) ; currop++ ) {
248 error("Missing opcode %s",em_mnem[currop]) ;
252 printf("%d, %d,",next->i_flag&0377,next->i_low&0377) ;
254 switch ( next->i_flag&OPTYPE ) {
257 printf("%d,",next->i_num&0377) ; nch++ ;
261 for ( currop++ ; currop<=sp_lmnem-sp_fmnem ; currop++ ) {
263 error("Missing opcode %s",em_mnem[currop]) ;
265 elem[sp_lmnem-sp_fmnem+1]=nch ;
266 printf("0 } ;\n\nchar *opindex[] = {\n");
267 for ( i=0 ; i<=sp_lmnem-sp_fmnem+1 ; i++ ) {
268 printf(" &opchoice[%d],\n",elem[i]) ;
273 int compare(a,b) struct opform *a,*b ; {
274 if ( a->i_opcode!=b->i_opcode ) {
275 return (a->i_opcode&0377)-(b->i_opcode&0377) ;
277 return oplength(a)-oplength(b) ;
280 int oplength(a) struct opform *a ; {
284 if ( a->i_flag&OPESC ) cnt++ ;
285 switch( a->i_flag&OPTYPE ) {
287 case OPMINI : break ;
289 case OPSHORT : cnt++ ; break ;
291 case OP16 : cnt+=2 ; break ;
292 case OP32 : cnt+=5 ; break ;
293 case OP64 : cnt+=9 ; break ;
298 /* ----------- checking --------------*/
300 int ecodes[256],codes[256],lcodes[256] ;
302 #define NMNEM (sp_lmnem-sp_fmnem+1)
307 char negc[NMNEM], zc[NMNEM], posc[NMNEM] ;
311 register struct opform *next ;
314 for ( i=0 ; i<NMNEM ; i++ ) negc[i]=zc[i]=posc[i]=0 ;
315 for ( i=0 ; i<256 ; i++ ) lcodes[i]= codes[i]= ecodes[i]= -1 ;
316 codes[254]=codes[255]=ESCAP;
319 for ( next=intable ; next<=lastform ; next++ ) {
321 flag = next->i_flag&0377 ;
322 opc = next->i_opcode&0377 ;
323 low = next->i_low&0377 ;
325 switch(flag&OPTYPE) {
326 case OPNO : zc[opc]++ ; break ;
329 for ( i=1 ; i<((next->i_num)&0377) ; i++ ) {
330 chkc(flag,low+i,opc) ;
332 if ( !(em_flag[opc]&PAR_G) &&
333 (flag&OPRANGE)==OP_BOTH) {
334 mess("Mini's and shorties should have P or N");
338 error("OP8 is removed") ;
343 else if ( flag&OP_POS )
351 error("Illegal type") ;
356 for ( i=0 ; i<256 ; i++ ) if ( codes[i]== -1 ) {
357 mess("interpreter opcode %d not used",i) ;
359 for ( opc=0 ; opc<NMNEM ; opc++ ) {
360 switch(em_flag[opc]&EM_PAR) {
362 ckop(opc,MUST,FORB,FORB) ;
368 ckop(opc,FORB,MAY,MAY) ;
376 ckop(opc,FORB,MAY,FORB) ;
379 ckop(opc,FORB,MAY,FORB) ;
382 ckop(opc,FORB,MUST,MUST) ;
385 ckop(opc,MUST,MAY,FORB) ;
388 error("Unknown instruction type of %s",ename(opc)) ;
394 chkc(flag,icode,emc) {
396 if ( ecodes[icode]!=-1 ) {
397 mess("Escaped opcode %d used by %s and %s",
398 icode,ename(emc),ename(ecodes[icode])) ;
401 } else switch ( flag&OPTYPE ) {
403 if ( codes[icode]!=-1 ) {
404 mess("Opcode %d used by %s and %s",
405 icode,ename(emc),ename(codes[icode])) ;
411 if ( lcodes[icode]!=-1 ) {
412 mess("Long opcode %d used by %s and %s",
413 icode,ename(emc),ename(codes[icode])) ;
421 if ( zc[emc]>1 ) mess("More then one OPNO for %s",ename(emc)) ;
422 if ( posc[emc]>1 ) mess("More then one OP16(pos) for %s",ename(emc)) ;
423 if ( negc[emc]>1 ) mess("More then one OP16(neg) for %s",ename(emc)) ;
426 if ( zc[emc]==0 ) mess("No OPNO for %s",ename(emc)) ;
429 if ( zc[emc]==1 ) mess("Forbidden OPNO for %s",ename(emc)) ;
434 if ( posc[emc]==0 ) mess("No OP16(pos) for %s",ename(emc)) ;
438 mess("Forbidden OP16(pos) for %s",ename(emc)) ;
443 if ( negc[emc]==0 ) mess("No OP16(neg) for %s",ename(emc)) ;
447 mess("Forbidden OP16(neg) for %s",ename(emc)) ;
452 static int pushchar ;
462 if ( feof(stdin) ) return EOF ;
465 if ( c=='\n' ) line++ ;
471 fatal("Double pushback") ;
475 if ( c=='\n' ) line-- ;