PulkoMandy | 17fc759 | 2022-07-28 18:27:54 +0200 | [diff] [blame^] | 1 | #include <stdio.h> |
| 2 | #include <string.h> |
| 3 | #include <stdlib.h> |
| 4 | #include <ctype.h> |
| 5 | #include <limits.h> |
| 6 | |
| 7 | #ifndef __STDC_VERSION__ |
| 8 | #ifdef __GNUC__ |
| 9 | #define __STDC_VERSION__ 199901L |
| 10 | #endif |
| 11 | #endif |
| 12 | |
| 13 | struct dtlist {char *spec,*descr;} dts[]={ |
| 14 | #include "datatypes.h" |
| 15 | }; |
| 16 | |
| 17 | struct dtconvlist {char *from,*to,*filef,*filet;int size;} cnvs[]={ |
| 18 | #include "dtconv.h" |
| 19 | }; |
| 20 | |
| 21 | int dtcnt=sizeof(dts)/sizeof(dts[0]); |
| 22 | int cnvcnt=sizeof(cnvs)/sizeof(cnvs[0]); |
| 23 | |
| 24 | signed char *have; |
| 25 | |
| 26 | #define CHAR 1 |
| 27 | #define UCHAR 2 |
| 28 | #define SHORT 3 |
| 29 | #define USHORT 4 |
| 30 | #define INT 5 |
| 31 | #define UINT 6 |
| 32 | #define LONG 7 |
| 33 | #define ULONG 8 |
| 34 | #define LLONG 9 |
| 35 | #define ULLONG 10 |
| 36 | #define FLOAT 11 |
| 37 | #define DOUBLE 12 |
| 38 | #define LDOUBLE 13 |
| 39 | #define POINTER 14 |
| 40 | |
| 41 | #define TYPECNT POINTER |
| 42 | |
| 43 | char *typen[TYPECNT+1]={"error","char","uchar","short","ushort","int","uint", |
| 44 | "long","ulong","llong","ullong","float","double","ldouble", |
| 45 | "pointer"}; |
| 46 | char *ftypen[TYPECNT+1]={"error","char","unsigned char","short","unsigned short", |
| 47 | "int","unsigned int","long","unsigned long", |
| 48 | "long long","unsigned long long", |
| 49 | "float","double","long double", |
| 50 | "char *"}; |
| 51 | |
| 52 | int dt[TYPECNT+1],cnv[TYPECNT+1]; |
| 53 | char *nt[TYPECNT+1]; |
| 54 | FILE *fin,*cout,*hout; |
| 55 | int crosscompiler; |
| 56 | |
| 57 | void *mymalloc(size_t size) |
| 58 | { |
| 59 | void *p=malloc(size); |
| 60 | if(!p){ |
| 61 | printf("Out of memory!\n"); |
| 62 | exit(EXIT_FAILURE); |
| 63 | } |
| 64 | return p; |
| 65 | } |
| 66 | |
| 67 | #define TESTTYPE(type,VALA,VALB) \ |
| 68 | if(sizeof(type)*CHAR_BIT==bits){\ |
| 69 | type tst=VALA;\ |
| 70 | if(islittle&&*((unsigned char *)&tst)==VALB)\ |
| 71 | return yn?"y":#type;\ |
| 72 | if(isbig&&*(((unsigned char *)(&tst+1))-1)==VALB)\ |
| 73 | return yn?"y":#type;\ |
| 74 | }\ |
| 75 | |
| 76 | |
| 77 | char *yndefault(char *spec,int yn) |
| 78 | { |
| 79 | int isieee=0,isunsigned=0,issigned,islittle=0,isbig=0,bits=0; |
| 80 | char *none; |
| 81 | if(yn) none="n"; else none=""; |
| 82 | if(*spec++!='S') return none; |
| 83 | while(isdigit(*(unsigned char *)spec)) |
| 84 | bits=bits*10+*spec++-'0'; |
| 85 | if(*spec++!='B') return none; |
| 86 | if(!strncmp(spec,"IEEE",4)) |
| 87 | {isieee=1;spec+=4;} |
| 88 | else if(*spec=='U') |
| 89 | {isunsigned=1;spec++;} |
| 90 | else if(*spec=='S') |
| 91 | {issigned=1;spec++;} |
| 92 | else |
| 93 | return none; |
| 94 | if(spec[0]=='B'&&spec[1]=='E') |
| 95 | {isbig=1;spec++;} |
| 96 | else if(spec[0]=='L'&&spec[1]=='E') |
| 97 | {islittle=1;spec++;} |
| 98 | else |
| 99 | islittle=isbig=1; |
| 100 | if(isieee){ |
| 101 | TESTTYPE(float,1.0,0); |
| 102 | TESTTYPE(double,1.0,0); |
| 103 | TESTTYPE(long double,1.0,0); |
| 104 | return none; |
| 105 | } |
| 106 | if(isunsigned){ |
| 107 | TESTTYPE(unsigned char,123,123); |
| 108 | TESTTYPE(unsigned short,123,123); |
| 109 | TESTTYPE(unsigned int,123,123); |
| 110 | TESTTYPE(unsigned long,123,123); |
| 111 | #if __STDC_VERSION__==199901L |
| 112 | TESTTYPE(unsigned long long,123,123); |
| 113 | #endif |
| 114 | return none; |
| 115 | } |
| 116 | if(issigned){ |
| 117 | TESTTYPE(signed char,123,123); |
| 118 | TESTTYPE(signed short,123,123); |
| 119 | TESTTYPE(signed int,123,123); |
| 120 | TESTTYPE(signed long,123,123); |
| 121 | #if __STDC_VERSION__==199901L |
| 122 | TESTTYPE(signed long long,123,123); |
| 123 | #endif |
| 124 | return none; |
| 125 | } |
| 126 | return none; |
| 127 | } |
| 128 | |
| 129 | |
| 130 | int askyn(char *def) |
| 131 | { |
| 132 | char in[8]; |
| 133 | do{ |
| 134 | printf("Type y or n [%s]: ",def); |
| 135 | fflush(stdout); |
| 136 | fgets(in,sizeof(in),stdin); |
| 137 | if(*in=='\n') strcpy(in,def); |
| 138 | }while(*in!='y'&&*in!='n'); |
| 139 | return *in=='y'; |
| 140 | } |
| 141 | |
| 142 | char *asktype(char *def) |
| 143 | { |
| 144 | char *in=mymalloc(128); |
| 145 | printf("Enter that type[%s]: ",def); |
| 146 | fflush(stdout); |
| 147 | fgets(in,127,stdin); |
| 148 | if(in[strlen(in)-1]=='\n') in[strlen(in)-1]=0; |
| 149 | if(!*in) strcpy(in,def); |
| 150 | return in; |
| 151 | } |
| 152 | |
| 153 | int tst(int type,char *spec) |
| 154 | { |
| 155 | int i,j; |
| 156 | for(i=0;i<dtcnt;i++){ |
| 157 | if(strstr(spec,dts[i].spec)){ |
| 158 | if(have[i]==-2) continue; |
| 159 | if(have[i]>=0){ |
| 160 | /* printf("auto: %s == %s\n",dts[i].spec,nt[have[i]]); */ |
| 161 | dt[type]=i; |
| 162 | nt[type]=nt[have[i]]; |
| 163 | cnv[type]=-1; |
| 164 | return 1; |
| 165 | }else{ |
| 166 | printf("Does your system/compiler support a type implemented as\n%s?\n",dts[i].descr); |
| 167 | if(askyn(yndefault(dts[i].spec,1))){ |
| 168 | dt[type]=i; |
| 169 | nt[type]=asktype(yndefault(dts[i].spec,0)); |
| 170 | have[i]=type; |
| 171 | cnv[type]=-1; |
| 172 | return 1; |
| 173 | }else{ |
| 174 | have[i]=-2; |
| 175 | } |
| 176 | } |
| 177 | } |
| 178 | } |
| 179 | for(j=0;j<cnvcnt;j++){ |
| 180 | char *s=0; |
| 181 | if(strstr(spec,cnvs[j].from)) s=cnvs[j].to; |
| 182 | /* if(strstr(spec,cnvs[j].to)) s=cnvs[j].from; */ |
| 183 | if(s){ |
| 184 | for(i=0;i<dtcnt;i++){ |
| 185 | if(!strcmp(s,dts[i].spec)){ |
| 186 | if(have[i]==-2) continue; |
| 187 | if(have[i]>=0){ |
| 188 | dt[type]=i; |
| 189 | nt[type]=nt[have[i]]; |
| 190 | cnv[type]=j; |
| 191 | return 2; |
| 192 | }else{ |
| 193 | printf("Does your system/compiler support a type implemented as\n%s?\n",dts[i].descr); |
| 194 | if(askyn(yndefault(dts[i].spec,1))){ |
| 195 | dt[type]=i; |
| 196 | nt[type]=asktype(yndefault(dts[i].spec,0)); |
| 197 | have[i]=type; |
| 198 | cnv[type]=j; |
| 199 | return 2; |
| 200 | }else{ |
| 201 | have[i]=-2; |
| 202 | } |
| 203 | } |
| 204 | } |
| 205 | } |
| 206 | } |
| 207 | } |
| 208 | return 0; |
| 209 | } |
| 210 | |
| 211 | char *castfrom(int type) |
| 212 | { |
| 213 | if(cnv[type]>=0){ |
| 214 | char *s=mymalloc(16); |
| 215 | sprintf(s,"dtcnv%df",type); |
| 216 | return s; |
| 217 | }else{ |
| 218 | return ""; |
| 219 | } |
| 220 | } |
| 221 | char *castto(int type) |
| 222 | { |
| 223 | if(cnv[type]>=0){ |
| 224 | char *s=mymalloc(16); |
| 225 | sprintf(s,"dtcnv%dt",type); |
| 226 | return s; |
| 227 | }else{ |
| 228 | return ""; |
| 229 | } |
| 230 | } |
| 231 | void gen_cast(char *name,int from,int to) |
| 232 | { |
| 233 | fprintf(hout,"#define %s(x) %s((%s)%s(x))\n",name,castto(to),nt[to],castfrom(from)); |
| 234 | } |
| 235 | void gen_2op(char *name,char *op,int type) |
| 236 | { |
| 237 | fprintf(hout,"#define %s(a,b) %s(%s(a)%s%s(b))\n",name,castto(type),castfrom(type),op,castfrom(type)); |
| 238 | } |
| 239 | void gen_1op(char *name,char *op,int type) |
| 240 | { |
| 241 | fprintf(hout,"#define %s(a) %s(%s%s(a))\n",name,castto(type),op,castfrom(type)); |
| 242 | } |
| 243 | void gen_cmp(char *name,char *op,int type) |
| 244 | { |
| 245 | fprintf(hout,"#define %s(a,b) (%s(a)%s%s(b))\n",name,castfrom(type),op,castfrom(type)); |
| 246 | } |
| 247 | int main(int argc,char **argv) |
| 248 | { |
| 249 | char type[128],spec[128]; |
| 250 | int i,r; |
| 251 | if(argc!=4){ printf("Usage: dtgen <config-file> <output-file.h> <output-file.c>\n");exit(EXIT_FAILURE);} |
| 252 | /* printf("%d datatypes, %d conversions\n",dtcnt,cnvcnt); */ |
| 253 | have=mymalloc(dtcnt*sizeof(*have)); |
| 254 | memset(have,-1,sizeof(*have)*dtcnt); |
| 255 | fin=fopen(argv[1],"r"); |
| 256 | if(!fin){ printf("Could not open <%s> for input!\n",argv[1]);exit(EXIT_FAILURE);} |
| 257 | hout=fopen(argv[2],"w"); |
| 258 | if(!hout){ printf("Could not open <%s> for output!\n",argv[2]);exit(EXIT_FAILURE);} |
| 259 | cout=fopen(argv[3],"w"); |
| 260 | if(!hout){ printf("Could not open <%s> for output!\n",argv[3]);exit(EXIT_FAILURE);} |
| 261 | printf("Are you building a cross-compiler?\n"); |
| 262 | crosscompiler=askyn("y"); |
| 263 | for(i=1;i<=TYPECNT;i++){ |
| 264 | fgets(spec,127,fin); |
| 265 | /* printf("Specs for z%s:\n%s\n",typen[i],spec); */ |
| 266 | if(!crosscompiler){ |
| 267 | dt[i]=i; |
| 268 | nt[i]=ftypen[i]; |
| 269 | have[i]=i; |
| 270 | cnv[i]=-1; |
| 271 | }else{ |
| 272 | if(!tst(i,spec)){ |
| 273 | printf("Problem! Your system does not seem to provide all of the data types\n" |
| 274 | "this version of vbcc needs.\nWrite to vb@compilers.de!\n"); |
| 275 | exit(EXIT_FAILURE); |
| 276 | } |
| 277 | } |
| 278 | } |
| 279 | fprintf(hout,"\n\n/* Machine generated file. DON'T TOUCH ME! */\n\n\n"); |
| 280 | fprintf(cout,"\n\n/* Machine generated file. DON'T TOUCH ME! */\n\n\n"); |
| 281 | fprintf(hout,"#ifndef DT_H\n"); |
| 282 | fprintf(hout,"#define DT_H 1\n"); |
| 283 | fprintf(cout,"#include \"dt.h\"\n\n"); |
| 284 | for(i=1;i<=TYPECNT;i++){ |
| 285 | if(cnv[i]>=0){ |
| 286 | int bits; |
| 287 | sscanf(cnvs[cnv[i]].from,"S%dB",&bits); |
| 288 | fprintf(hout,"typedef struct {char a[%d];} dt%df;\n",cnvs[cnv[i]].size,i); |
| 289 | fprintf(hout,"typedef dt%df z%s;\n",i,typen[i]); |
| 290 | fprintf(hout,"typedef %s dt%dt;\n",nt[i],i); |
| 291 | fprintf(hout,"dt%dt dtcnv%df(dt%df);\n",i,i,i); |
| 292 | fprintf(hout,"dt%df dtcnv%dt(dt%dt);\n",i,i,i); |
| 293 | fprintf(cout,"#undef BITSIZE\n#define BITSIZE %d\n",bits); |
| 294 | fprintf(cout,"#undef DTTTYPE\n#define DTTTYPE dt%dt\n",i); |
| 295 | fprintf(cout,"#undef DTFTYPE\n#define DTFTYPE dt%df\n",i); |
| 296 | fprintf(cout,"dt%dt dtcnv%df(dt%df\n",i,i,i); |
| 297 | fprintf(cout,"#include \"%s\"\n",cnvs[cnv[i]].filef); |
| 298 | fprintf(cout,"dt%df dtcnv%dt(dt%dt\n",i,i,i); |
| 299 | fprintf(cout,"#include \"%s\"\n",cnvs[cnv[i]].filet); |
| 300 | }else{ |
| 301 | fprintf(hout,"typedef %s z%s;\n",nt[i],typen[i]); |
| 302 | } |
| 303 | } |
| 304 | |
| 305 | gen_cast("zc2zm",CHAR,LLONG); |
| 306 | gen_cast("zs2zm",SHORT,LLONG); |
| 307 | gen_cast("zi2zm",INT,LLONG); |
| 308 | gen_cast("zl2zm",LONG,LLONG); |
| 309 | gen_cast("zll2zm",LLONG,LLONG); |
| 310 | gen_cast("zm2zc",LLONG,CHAR); |
| 311 | gen_cast("zm2zs",LLONG,SHORT); |
| 312 | gen_cast("zm2zi",LLONG,INT); |
| 313 | gen_cast("zm2zl",LLONG,LONG); |
| 314 | gen_cast("zm2zll",LLONG,LLONG); |
| 315 | |
| 316 | gen_cast("zuc2zum",UCHAR,ULLONG); |
| 317 | gen_cast("zus2zum",USHORT,ULLONG); |
| 318 | gen_cast("zui2zum",UINT,ULLONG); |
| 319 | gen_cast("zul2zum",ULONG,ULLONG); |
| 320 | gen_cast("zull2zum",ULLONG,ULLONG); |
| 321 | gen_cast("zum2zuc",ULLONG,UCHAR); |
| 322 | gen_cast("zum2zus",ULLONG,USHORT); |
| 323 | gen_cast("zum2zui",ULLONG,UINT); |
| 324 | gen_cast("zum2zul",ULLONG,ULONG); |
| 325 | gen_cast("zum2zull",ULLONG,ULLONG); |
| 326 | |
| 327 | gen_cast("zum2zm",ULLONG,LLONG); |
| 328 | gen_cast("zm2zum",LLONG,ULLONG); |
| 329 | gen_cast("zf2zld",FLOAT,LDOUBLE); |
| 330 | gen_cast("zd2zld",DOUBLE,LDOUBLE); |
| 331 | gen_cast("zld2zf",LDOUBLE,FLOAT); |
| 332 | gen_cast("zld2zd",LDOUBLE,DOUBLE); |
| 333 | gen_cast("zld2zm",LDOUBLE,LLONG); |
| 334 | gen_cast("zm2zld",LLONG,LDOUBLE); |
| 335 | gen_cast("zld2zum",LDOUBLE,ULLONG); |
| 336 | gen_cast("zum2zld",ULLONG,LDOUBLE); |
| 337 | gen_cast("zp2zum",POINTER,ULLONG); |
| 338 | gen_cast("zum2zp",ULLONG,POINTER); |
| 339 | |
| 340 | fprintf(hout,"#define l2zm(x) %s((%s)(x))\n",castto(LLONG),nt[LLONG]); |
| 341 | fprintf(hout,"#define ul2zum(x) %s((%s)(x))\n",castto(ULLONG),nt[ULLONG]); |
| 342 | fprintf(hout,"#define d2zld(x) %s((%s)(x))\n",castto(LDOUBLE),nt[LDOUBLE]); |
| 343 | fprintf(hout,"#define zm2l(x) ((long)%s(x))\n",castfrom(LLONG)); |
| 344 | fprintf(hout,"#define zum2ul(x) ((unsigned long)%s(x))\n",castfrom(ULLONG)); |
| 345 | fprintf(hout,"#define zld2d(x) ((double)%s(x))\n",castfrom(LDOUBLE)); |
| 346 | |
| 347 | gen_2op("zmadd","+",LLONG); |
| 348 | gen_2op("zumadd","+",ULLONG); |
| 349 | gen_2op("zldadd","+",LDOUBLE); |
| 350 | gen_2op("zmsub","-",LLONG); |
| 351 | gen_2op("zumsub","-",ULLONG); |
| 352 | gen_2op("zldsub","-",LDOUBLE); |
| 353 | gen_2op("zmmult","*",LLONG); |
| 354 | gen_2op("zummult","*",ULLONG); |
| 355 | gen_2op("zldmult","*",LDOUBLE); |
| 356 | gen_2op("zmdiv","/",LLONG); |
| 357 | gen_2op("zumdiv","/",ULLONG); |
| 358 | gen_2op("zlddiv","/",LDOUBLE); |
| 359 | gen_2op("zmmod","%",LLONG); |
| 360 | gen_2op("zummod","%",ULLONG); |
| 361 | gen_2op("zmlshift","<<",LLONG); |
| 362 | gen_2op("zumlshift","<<",ULLONG); |
| 363 | gen_2op("zmrshift",">>",LLONG); |
| 364 | gen_2op("zumrshift",">>",ULLONG); |
| 365 | gen_2op("zmand","&",LLONG); |
| 366 | gen_2op("zumand","&",ULLONG); |
| 367 | gen_2op("zmor","|",LLONG); |
| 368 | gen_2op("zumor","|",ULLONG); |
| 369 | gen_2op("zmxor","^",LLONG); |
| 370 | gen_2op("zumxor","^",ULLONG); |
| 371 | gen_2op("zmmod","%",LLONG); |
| 372 | gen_2op("zummod","%",ULLONG); |
| 373 | |
| 374 | gen_1op("zmkompl","~",LLONG); |
| 375 | gen_1op("zumkompl","~",ULLONG); |
| 376 | |
| 377 | gen_cmp("zmleq","<=",LLONG); |
| 378 | gen_cmp("zumleq","<=",ULLONG); |
| 379 | gen_cmp("zldleq","<=",LDOUBLE); |
| 380 | gen_cmp("zmeqto","==",LLONG); |
| 381 | gen_cmp("zumeqto","==",ULLONG); |
| 382 | gen_cmp("zldeqto","==",LDOUBLE); |
| 383 | |
| 384 | fprintf(hout,"#endif\n"); |
| 385 | |
| 386 | fclose(fin); |
| 387 | fclose(hout); |
| 388 | fclose(cout); |
| 389 | free(have); |
| 390 | return 0; |
| 391 | } |
| 392 | |
| 393 | |
| 394 | |
| 395 | |
| 396 | |
| 397 | |