Pristine Ack-5.5
[Ack-5.5.git] / doc / em / int / mktables.c
1 /* $Id: mktables.c,v 1.5 1994/06/24 10:03:34 ceriel Exp $ */
2 /*
3  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
4  * See the copyright notice in the ACK home directory, in the file "Copyright".
5  *
6  */
7
8 /* Author: E.G. Keizer */
9
10 #include <stdio.h>
11 #include <ip_spec.h>
12 #include <em_spec.h>
13 #include <em_flag.h>
14
15 /* This program reads the human readable interpreter specification
16    and produces a efficient machine representation that can be
17    translated by a C-compiler.
18 */
19
20 #define ESCAP   256
21
22 int nerror = 0 ;
23 int atend  = 0 ;
24 int line   = 1 ;
25 int maxinsl= 0 ;
26
27 extern char em_mnem[][4] ;
28 char esca[] = "escape" ;
29 #define ename(no)       ((no)==ESCAP?esca:em_mnem[(no)])
30
31 extern char em_flag[] ;
32
33 main(argc,argv) char **argv ; {
34         if ( argc>1 ) {
35                 if ( freopen(argv[1],"r",stdin)==NULL) {
36                         fatal("Cannot open %s",argv[1]) ;
37                 }
38         }
39         if ( argc>2 ) {
40                 if ( freopen(argv[2],"w",stdout)==NULL) {
41                         fatal("Cannot create %s",argv[2]) ;
42                 }
43         }
44         if ( argc>3 ) {
45                 fatal("%s [ file [ file ] ]",argv[0]) ;
46         }
47         atend=0 ;
48         readin();
49         atend=1 ;
50         exit(nerror) ;
51 }
52
53 readin() {
54         char *ident();
55         char *firstid ;
56         int opcode,flags;
57         int c;
58
59         while ( !feof(stdin) ) {
60                 firstid=ident() ;
61                 if ( *firstid=='\n' || feof(stdin) ) continue ;
62                 opcode = getmnem(firstid) ;
63                 printf("%d ",opcode+1) ;
64                 flags  = decflag(ident(),opcode) ;
65                 switch(em_flag[opcode]&EM_PAR) {
66                 case PAR_D: case PAR_F: case PAR_B: case PAR_L: case PAR_C:
67                         putchar('S') ;
68                 }
69                 putchar(' ');
70                 while ( (c=readchar())!='\n' && c!=EOF ) putchar(c) ;
71                 putchar('\n') ;
72         }
73 }
74
75 char *ident() {
76         /* skip spaces and tabs, anything up to space,tab or eof is
77            a identifier.
78            Anything from # to end-of-line is an end-of-line.
79            End-of-line is an identifier all by itself.
80         */
81
82         static char array[200] ;
83         register int c ;
84         register char *cc ;
85
86         do {
87                 c=readchar() ;
88         } while ( c==' ' || c=='\t' ) ;
89         for ( cc=array ; cc<&array[(sizeof array) - 1] ; cc++ ) {
90                 if ( c=='#' ) {
91                         do {
92                                 c=readchar();
93                         } while ( c!='\n' && c!=EOF ) ;
94                 }
95                 *cc = c ;
96                 if ( c=='\n' && cc==array ) break ;
97                 c=readchar() ;
98                 if ( c=='\n' ) {
99                         pushback(c) ;
100                         break ;
101                 }
102                 if ( c==' ' || c=='\t' || c==EOF ) break ;
103         }
104         *++cc=0 ;
105         return array ;
106 }
107
108 int getmnem(str) char *str ; {
109         char (*ptr)[4] ;
110
111         for ( ptr = em_mnem ; *ptr<= &em_mnem[sp_lmnem][0] ; ptr++ ) {
112                 if ( strcmp(*ptr,str)==0 ) return (ptr-em_mnem) ;
113         }
114         error("Illegal mnemonic") ;
115         return 0 ;
116 }
117
118 error(str,a1,a2,a3,a4,a5,a6) /* VARARGS1 */ char *str ; {
119         if ( !atend ) fprintf(stderr,"line %d: ",line) ;
120         fprintf(stderr,str,a1,a2,a3,a4,a5,a6) ;
121         fprintf(stderr,"\n");
122         nerror++ ;
123 }
124
125 mess(str,a1,a2,a3,a4,a5,a6) /* VARARGS1 */ char *str ; {
126         if ( !atend ) fprintf(stderr,"line %d: ",line) ;
127         fprintf(stderr,str,a1,a2,a3,a4,a5,a6) ;
128         fprintf(stderr,"\n");
129 }
130
131 fatal(str,a1,a2,a3,a4,a5,a6) /* VARARGS1 */ char *str ; {
132         error(str,a1,a2,a3,a4,a5,a6) ;
133         exit(1) ;
134 }
135
136 #define ILLGL   -1
137
138 check(val) int val ; {
139         if ( val!=ILLGL ) error("Illegal flag combination") ;
140 }
141
142 int decflag(str,opc) char *str ; {
143         int type ;
144         int escape ;
145         int range ;
146         int wordm ;
147         int notzero ;
148         char c;
149
150         type=escape=range=wordm=notzero= ILLGL ;
151         while ( c= *str++ ) {
152                 switch ( c ) {
153                 case 'm' :
154                         check(type) ; type=OPMINI ; break ;
155                 case 's' :
156                         check(type) ; type=OPSHORT ; break ;
157                 case '-' :
158                         check(type) ; type=OPNO ;
159                         if ( (em_flag[opc]&EM_PAR)==PAR_W ) c='i' ;
160                         break ;
161                 case '1' :
162                         check(type) ; type=OP8 ; break ;
163                 case '2' :
164                         check(type) ; type=OP16 ; break ;
165                 case '4' :
166                         check(type) ; type=OP32 ; break ;
167                 case '8' :
168                         check(type) ; type=OP64 ; break ;
169                 case 'u' :
170                         check(type) ; type=OP16U ; break ;
171                 case 'e' :
172                         check(escape) ; escape=0 ; break ;
173                 case 'N' :
174                         check(range) ; range= 2 ; break ;
175                 case 'P' :
176                         check(range) ; range= 1 ; break ;
177                 case 'w' :
178                         check(wordm) ; wordm=0 ; break ;
179                 case 'o' :
180                         check(notzero) ; notzero=0 ; break ;
181                 default :
182                         error("Unknown flag") ;
183                 }
184                 putchar(c);
185         }
186         if ( type==ILLGL ) error("Type must be specified") ;
187         switch ( type ) {
188         case OP64 :
189         case OP32 :
190                 if ( escape!=ILLGL ) error("Conflicting escapes") ;
191                 escape=ILLGL ;
192         case OP16 :
193         case OP16U :
194         case OP8 :
195         case OPSHORT :
196         case OPNO :
197                 if ( notzero!=ILLGL ) mess("Improbable OPNZ") ;
198                 if ( type==OPNO && range!=ILLGL ) {
199                         mess("No operand in range") ;
200                 }
201         }
202         if ( escape!=ILLGL ) type|=OPESC ;
203         if ( wordm!=ILLGL ) type|=OPWORD ;
204         switch ( range) {
205         case ILLGL : type|=OP_BOTH ; break ;
206         case 1     : type|=OP_POS  ; break ;
207         case 2     : type|=OP_NEG  ; break ;
208         }
209         if ( notzero!=ILLGL ) type|=OPNZ ;
210         return type ;
211 }
212
213 static int pushchar ;
214 static int pushf ;
215
216 int readchar() {
217         int c ;
218
219         if ( pushf ) {
220                 pushf=0 ;
221                 c = pushchar ;
222         } else {
223                 if ( feof(stdin) ) return EOF ;
224                 c=getc(stdin) ;
225         }
226         if ( c=='\n' ) line++ ;
227         return c ;
228 }
229
230 pushback(c) {
231         if ( pushf ) {
232                 fatal("Double pushback") ;
233         }
234         pushf++ ;
235         pushchar=c ;
236         if ( c=='\n' ) line-- ;
237 }