openblt

a hobby OS from the late 90s
git clone http://frotz.net/git/openblt.git
Log | Files | Refs | LICENSE

ic.c (5685B)


      1 // RPC Interface Compiler (ic)
      2 //
      3 
      4 #include <stdio.h>
      5 #include <stdlib.h>
      6 #include <fcntl.h>
      7 #include <sys/stat.h>
      8 #include <stdarg.h>
      9 #include <string.h>
     10 
     11 typedef struct ic_type ic_type;
     12 typedef struct ic_param ic_param;
     13 typedef struct ic_func ic_func;
     14 typedef struct ic_ifc ic_ifc;
     15 
     16 struct ic_type
     17 {
     18 	ic_type *next;
     19 	
     20 	char *name;
     21 	enum {
     22 		BASIC,
     23 		ARRAY,
     24 		STRING,
     25 		STRUCT
     26 	} type;
     27 	int size;
     28 	ic_type *parts;
     29 };
     30 
     31 struct ic_param
     32 {
     33 	ic_param *next;
     34 	
     35 	char *name;
     36 	ic_type *type;
     37 	enum {
     38 		IN = 1,
     39 		OUT = 2
     40 	} flags;
     41 };
     42 
     43 struct ic_func
     44 {
     45 	ic_func *next;
     46 	
     47 	char *name;
     48 	ic_param *params;	
     49 };
     50 
     51 struct ic_ifc
     52 {
     53 	char *name;
     54 	char *key;
     55 	ic_func *funcs;
     56 };
     57 
     58 ic_type *types = NULL;
     59 
     60 ic_type builtins[] = {
     61 	{ NULL, "int32",   BASIC, 4, NULL },
     62 	{ NULL, "uint32",  BASIC, 4, NULL },
     63 	{ NULL, "int16",   BASIC, 2, NULL },
     64 	{ NULL, "uint16",  BASIC, 2, NULL },
     65 	{ NULL, NULL,      BASIC, 0, NULL }
     66 };
     67 
     68 int line = 1;
     69 char token[256];
     70 char *data;
     71 char *file;
     72 
     73 void die(const char *fmt, ...)
     74 {
     75 	va_list ap;
     76 	va_start(ap,fmt);
     77 	fprintf(stderr,"%s:%d - ",file,line);
     78 	vfprintf(stderr,fmt,ap);
     79 	fprintf(stderr,"\n");
     80 	va_end(ap);
     81 	exit(1);
     82 }
     83 
     84 
     85 void next(void)
     86 {
     87 	char *x = token;
     88 	
     89 	if(*data == 0) {
     90 		token[0] = 0;
     91 		return;
     92 	}
     93 	
     94 eat_space:
     95 	while(*data <= ' ') {
     96 		if(*data == '\n') line++;
     97 		data++;
     98 	}
     99 	
    100 	if(*data == '#') {
    101 		while(*data != '\n') data++;
    102 		goto eat_space;
    103 	}
    104 	
    105 	if(*data == '"') {
    106 		data++;
    107 		while(*data != '"') {
    108 			*x++ = *data++;
    109 		}
    110 		*x = 0;
    111 		data++;
    112 		return;
    113 	}
    114 	
    115 	for(;;){
    116 		switch(*data){
    117 		case '{':
    118 		case '}':
    119 		case '(':
    120 		case ')':
    121 		case ',':
    122 		case '#':
    123 		case '"':
    124 		case ':':
    125 			if(x == token){
    126 				*x++ = *data++;
    127 			}
    128 			*x = 0;
    129 			return;
    130 		default:
    131 			if(*data <= ' '){
    132 				*x = 0;
    133 				return;
    134 			} else {
    135 				*x++ = *data++;
    136 				if((x - token) > 255) die("token too long");
    137 			}
    138 		}
    139 	}	
    140 }
    141 
    142 int match(const char *tok)
    143 {
    144 	if(!strcmp(token,tok)){
    145 		next();
    146 		return 1;
    147 	} else {
    148 		return 0;
    149 	}
    150 }
    151 
    152 void force(const char *tok)
    153 {
    154 	if(strcmp(token,tok)){
    155 		die("expecting '%s', found '%s'",tok,token);
    156 	}
    157 	next();
    158 }
    159 
    160 ic_type *type(void)
    161 {
    162 	ic_type *t;
    163 	
    164 	if(match("string")){
    165 		t = (ic_type *) malloc(sizeof(ic_type));
    166 		if(!t) die("out of memory");
    167 		
    168 		force(":");
    169 		t->size = atoi(token); next();
    170 		t->name = "string";
    171 		t->type = STRING;
    172 		t->next = NULL;
    173 		t->parts = NULL;
    174 		
    175 		return t;
    176 	}
    177 		
    178 	for(t = types; t; t = t->next){
    179 		if(match(t->name)) return t;
    180 	}
    181 	
    182 	die("unknown type '%s'",token);
    183 	return NULL;
    184 }
    185 
    186 ic_param *param(void)
    187 {
    188 	ic_param *p = (ic_param*) malloc(sizeof(ic_param));
    189 	if(!p) die("out of memory");
    190 	
    191 	if(match("in")){
    192 		p->flags = IN;
    193 	} else if(match("out")) {
    194 		p->flags = OUT;
    195 	} else {
    196 		die("expecting 'in' or 'out', found '%s'",token);
    197 	}
    198 	
    199 	p->type = type();
    200 	p->name = strdup(token); next();
    201 	p->next = NULL;
    202 	
    203 	return p;
    204 }
    205 
    206 ic_func *function(void)
    207 {
    208 	ic_param *p,*last = NULL;
    209 	ic_func *func = (ic_func*) malloc(sizeof(ic_func));
    210 	if(!func) die("out of memory");
    211 
    212 	func->name = strdup(token); next();
    213 	func->next = NULL;
    214 	func->params = NULL;
    215 	
    216 	force("(");
    217 	
    218 	for(;;){
    219 		if(match(")")) {	
    220 			match(";"); /* optional semi */
    221 			return func;
    222 		}
    223 		p = param();
    224 		if(last) {
    225 			last->next = p;
    226 		} else {
    227 			func->params = p;
    228 		}
    229 		last = p;
    230 		match(",");
    231 	}
    232 }
    233 
    234 
    235 
    236 ic_ifc *interface(void)
    237 {
    238 	ic_func *func,*last = NULL;
    239 	ic_ifc *ifc = (ic_ifc*) malloc(sizeof(ic_ifc));
    240 	
    241 	if(!ifc) die("out of memory");
    242 
    243 	ifc->name = strdup(token); next();
    244 	ifc->key = strdup(token); next();
    245 	ifc->funcs = NULL;
    246 	
    247 	force("{");
    248 	
    249 	for(;;){
    250 		if(match("}")) {
    251 			match(";"); /* optional semi */
    252 			return ifc;
    253 		}
    254 		func = function();
    255 		if(last){
    256 			last->next = func;
    257 		} else {
    258 			ifc->funcs = func;
    259 		}
    260 		last = func;
    261 	}
    262 }
    263 
    264 void mkheader(FILE *f, ic_ifc *ifc)
    265 {
    266 	ic_func *func;
    267 	ic_param *p;
    268 	char *upname,*x;
    269 	
    270 	x = upname = strdup(ifc->name);
    271 	while(*x) {
    272 		*x = toupper(*x);
    273 		x++;
    274 	}
    275 	fprintf(f,"/* Generated File - DO NOT EDIT */\n\n");
    276 	fprintf(f,"#define IFC_%s \"%s\"\n\n",upname,ifc->key);
    277 	fprintf(f,"typedef struct {\n");
    278 	for(func = ifc->funcs; func; func = func->next){
    279 		fprintf(f,"\tstatus_t (*%s)(\n",func->name);
    280 		fprintf(f,"\t\tconst ifc_handle *handle%s\n",func->params?",":"");
    281 		
    282 		for(p = func->params; p; p = p->next){
    283 			fprintf(f,"\t\t%s %s%s\n",p->type->name,p->name,
    284 					p->next ? "," : "");
    285 		}
    286 		fprintf(f,"\t\t);\n");
    287 	}
    288 	fprintf(f,"} ifc_%s;\n",ifc->name);
    289 }
    290 
    291 void mkstub(FILE *f, ic_ifc *ifc)
    292 {
    293 	ic_func *func;
    294 	ic_param *p;
    295 	
    296 	fprintf(f,"/* Generated File - DO NOT EDIT */\n\n");
    297 	
    298 	/* eject the stubs */
    299 	for(func = ifc->funcs; func; func = func->next){
    300 		fprintf(f,"static status_t\n");
    301 		fprintf(f,"stub_%s(\n",func->name);
    302 		fprintf(f,"\t)\n");
    303 		fprintf(f,"{\n");
    304 		fprintf(f,"\treturn -1;\n"); 
    305 		fprintf(f,"}\n\n");
    306 	}
    307 		
    308 	/* eject the decl */
    309 	fprintf(f,"ifc_%s ifc_%s_impl = {\n",ifc->name,ifc->name);	
    310 	for(func = ifc->funcs; func; func = func->next){
    311 		fprintf(f,"\t&stub_%s%s\n",func->name,func->next?",":"");
    312 	}
    313 	fprintf(f,"};\n");	
    314 }
    315 
    316 void parse(void)
    317 {
    318 	ic_ifc *ifc;
    319 	next();
    320 	
    321 	for(;;){
    322 		if(match("interface")) {
    323 			ifc = interface();
    324 			mkheader(stdout,ifc);
    325 			mkstub(stdout,ifc);
    326 		}
    327 		if(match("")) return;
    328 		die("unexpected token '%s'",token);
    329 	}
    330 }
    331 
    332 int main(int argc, char *argv[])
    333 {
    334 	int i,fd;
    335 	struct stat s;
    336 	
    337 	/* install built-in types */
    338 	for(i=0;builtins[i].name;i++){
    339 		builtins[i].next = types;
    340 		types = builtins + i;
    341 	}
    342 	
    343 	if(argc != 2) {
    344 		fprintf(stderr,"error: no input file\n");
    345 		return 1;
    346 	}
    347 	
    348 	file = argv[1];
    349 	
    350 	if(((fd = open(file,O_RDONLY)) < 0) || fstat(fd,&s)){
    351 		fprintf(stderr,"error: cannot open \"%s\"\n",file);
    352 		return 1;
    353 	}
    354 	
    355 	data = (char*) malloc(s.st_size + 1);
    356 	read(fd, data, s.st_size);
    357 	data[s.st_size] = 0;
    358 	close(fd);
    359 	
    360 	parse();
    361 }
    362 
    363 
    364 
    365 
    366 
    367