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