12b8c71998-11-03Marcus Comstedt #!/usr/local/bin/pike /* V=void I=int D=double F=float E=enum B=bitfield
4538f61998-11-03Marcus Comstedt  O=bool
12b8c71998-11-03Marcus Comstedt  R=double/float Q=int/float Z=(byte/)double/float/int/short +XXXX = 3/4/array(3/4) +XXX = 2/3/4/array(2/3/4)
79424a1999-07-18Marcus Comstedt  +XX = 1/2/array(1/2)
1588bf1999-07-17Marcus Comstedt  +X = 1/2/3/4/array(1/2/3/4)
12b8c71998-11-03Marcus Comstedt  =XXXX = 4/array(4) =XXX = 3/array(3) @X = 1/array(n)
66c3f31999-07-24Marcus Comstedt  [nnX = array(nn)
12b8c71998-11-03Marcus Comstedt  # = like =, but add count ! = like =, but no vector version available
1588bf1999-07-17Marcus Comstedt  image object support: w = width of image h = height of image f = format of image t = type of image i = image data
12b8c71998-11-03Marcus Comstedt */ inherit "features"; inherit "constants"; void error(string msg, mixed ... args) { if(sizeof(args)) msg = sprintf(msg, @args); werror(msg+"\n"); exit(1); }
66c3f31999-07-24Marcus Comstedt array(string|array(string)) special_234(int mi, int mx, string ty, int|void a)
12b8c71998-11-03Marcus Comstedt { string tm="BIT_FLOAT|BIT_INT", baset="float|int", rt="if"; array(string) typ=({}); int i, ad; if(sizeof(Array.uniq(values(ty)))!=1) error("Unparsable 234 type '%s'.", ty); switch(ty[0]) { case 'E': case 'B': case 'I':
4538f61998-11-03Marcus Comstedt  case 'O':
12b8c71998-11-03Marcus Comstedt  baset="int"; tm="BIT_INT"; rt="i"; break; case 'D': ad=1; /* fallthrough */ case 'F': baset="float"; tm="BIT_FLOAT"; rt=(ad?"":"f"); break; case 'R': rt="f"; case 'Z': ad=1; break; case 'Q': break; default: error("Unknown 234 type '%s'.", ty[0..0]); } if(ad) rt+="d";
66c3f31999-07-24Marcus Comstedt  if(a) typ+=({"array("+baset+")"}); else for(i=0; i<mx; i++) {
12b8c71998-11-03Marcus Comstedt  string t = baset; if(!i) t+="|array("+baset+")"; if(i>=mi || i>0) t+="|void"; typ+=({t}); } return ({typ,tm,rows((['i':"ZT_INT",'f':"ZT_FLOAT",'d':"ZT_DOUBLE"]), values(rt))*"|",rt}); } array(string) gen_func(string name, string ty) {
2569d41999-07-25Marcus Comstedt  string res="", got="", prot, vdec, vret, vcast, fu=name;
12b8c71998-11-03Marcus Comstedt  array novec, args=({}), argt=({});
2569d41999-07-25Marcus Comstedt  int r234, argt_cut=-1, img_obj=0, polya=-1;
12b8c71998-11-03Marcus Comstedt  string rtypes; switch(ty[0]) { case 'V': prot=":void"; break; case 'I':
4538f61998-11-03Marcus Comstedt  case 'O':
79424a1999-07-18Marcus Comstedt  case 'E':
12b8c71998-11-03Marcus Comstedt  prot=":int"; vdec="INT32"; vret="push_int"; break;
2569d41999-07-25Marcus Comstedt  case 'S': prot=":string"; vdec="const GLubyte *"; vret="push_text"; vcast="(char *)"; break;
12b8c71998-11-03Marcus Comstedt  default: error("%s: Unknown return type '%c'.", name, ty[0]); } res += "static void f_"+name+"(INT32 args)\n{\n"+ (vdec?(" "+vdec+" res;\n"):"");
1588bf1999-07-17Marcus Comstedt  int a=1;
12b8c71998-11-03Marcus Comstedt  for(int i=1; i<sizeof(ty); i++) switch(ty[i]) { case 'B': case 'E':
4538f61998-11-03Marcus Comstedt  case 'O':
12b8c71998-11-03Marcus Comstedt  case 'I': argt += ({"int"});
1588bf1999-07-17Marcus Comstedt  args += ({ "arg"+a }); res += " INT32 arg"+a+";\n"; got += " arg"+a+"=sp["+(a-1)+"-args].u.integer;\n"; a++;
12b8c71998-11-03Marcus Comstedt  break; case 'D': argt += ({"float"});
1588bf1999-07-17Marcus Comstedt  args += ({ "arg"+a }); res += " double arg"+a+";\n"; got += " arg"+a+"=sp["+(a-1)+"-args].u.float_number;\n"; a++;
12b8c71998-11-03Marcus Comstedt  break; case 'F': argt += ({"float"});
1588bf1999-07-17Marcus Comstedt  args += ({ "arg"+a }); res += " float arg"+a+";\n"; got += " arg"+a+"=sp["+(a-1)+"-args].u.float_number;\n"; a++;
12b8c71998-11-03Marcus Comstedt  break;
2569d41999-07-25Marcus Comstedt  case 'Z': argt += ({"float|int"}); args += ({ "sp["+(a-1)+"-args]" }); polya = (a++)-1; break;
12b8c71998-11-03Marcus Comstedt  case '+': int mi, mx; switch(sizeof(ty[i+1..])) {
1588bf1999-07-17Marcus Comstedt  case 1: mi = 1; mx = 4; break;
79424a1999-07-18Marcus Comstedt  case 2: mi = 1; mx = 2; break;
12b8c71998-11-03Marcus Comstedt  case 3: mi = 2; mx = 4; break; case 4: mi = 3; mx = 4; break; default: error("Can't understand + followed by %d chars.\n", sizeof(ty[i+1..])); } array plusfix = special_234(mi, mx, ty[i+1..]); res += " struct zvalue4 zv4;\n";
d919491998-11-03Marcus Comstedt  argt_cut = sizeof(argt);
12b8c71998-11-03Marcus Comstedt  argt += plusfix[0];
1588bf1999-07-17Marcus Comstedt  res += "\n int r234=check_234_args(\""+name+"\", args-"+(a-1)+", "+
12b8c71998-11-03Marcus Comstedt  mi+", "+mx+", "+plusfix[1]+", "+plusfix[2]+", &zv4);\n"; r234=1; rtypes=plusfix[3]; i=sizeof(ty); novec=indices(allocate(mx+1))[mi..]; break; case '#': fu += sizeof(ty[i+1..]); /* fallthrough */ case '!': case '=': array eqfix = special_234(sizeof(ty[i+1..]), sizeof(ty[i+1..]), ty[i+1..]); res += " struct zvalue4 zv4;\n";
d919491998-11-03Marcus Comstedt  argt_cut = sizeof(argt);
12b8c71998-11-03Marcus Comstedt  argt += eqfix[0];
1588bf1999-07-17Marcus Comstedt  res += "\n check_234_args(\""+name+"\", args-"+(a-1)+", "+
12b8c71998-11-03Marcus Comstedt  sizeof(ty[i+1..])+", "+sizeof(ty[i+1..])+", "+eqfix[1]+", "+ eqfix[2]+", &zv4);\n"; r234=2; rtypes=eqfix[3]; if(ty[i]=='!') novec=indices(ty[i+1..]); i=sizeof(ty); break; case '@': array atfix = special_234(1, 1, ty[i+1..]); res += " union zvalue16 zv16;\n";
d919491998-11-03Marcus Comstedt  argt_cut = sizeof(argt);
12b8c71998-11-03Marcus Comstedt  argt += atfix[0];
1588bf1999-07-17Marcus Comstedt  res += "\n int r1n=check_1n_args(\""+name+"\", args-"+(a-1)+", "+
12b8c71998-11-03Marcus Comstedt  atfix[1]+", "+atfix[2]+", &zv16);\n"; r234=3; rtypes=atfix[3]; i=sizeof(ty); break;
66c3f31999-07-24Marcus Comstedt  case '[': int nn; string rst; sscanf(ty[i+1..], "%d%s", nn, rst); array arrfix = special_234(nn, nn, rst, 1); res += " union zvalue16 zv16;\n int r1n;\n"; argt += arrfix[0]; got += " if(sp["+(a-1)+"-args].u.array->size != "+nn+")\n" " error(\""+name+": Array length is wrong (is %d, should be "+nn+ ")\\n\", sp["+(a-1)+"-args].u.array->size);\n\n"; got += " r1n=check_1n_args(\""+name+"\", args-"+(a-1)+", "+ arrfix[1]+", "+arrfix[2]+", &zv16);\n"; r234=-1; rtypes=arrfix[3]; i=sizeof(ty); break;
1588bf1999-07-17Marcus Comstedt  case 'w': img_obj=1; args += ({ "img.width" }); break; case 'h': img_obj=1; args += ({ "img.height" }); break; case 'f': img_obj=1; args += ({ "img.format" }); break; case 't': img_obj=1; args += ({ "img.type" }); break; case 'i': img_obj=1; args += ({ "img.pixels" }); break;
12b8c71998-11-03Marcus Comstedt  default: error("%s: Unknown parameter type '%c'.", name, ty[i]); }
1588bf1999-07-17Marcus Comstedt  if(img_obj) {
7c970f1999-07-29Marcus Comstedt  argt += ({"object|mapping(string:object)"});
1588bf1999-07-17Marcus Comstedt  res += " struct zimage img;\n";
7c970f1999-07-29Marcus Comstedt  got += " check_img_arg(&sp["+(a-1)+"-args], &img, "+a+
1c89cc1999-07-18Marcus Comstedt  ", \""+name+"\");\n";
1588bf1999-07-17Marcus Comstedt  }
12b8c71998-11-03Marcus Comstedt  prot = (argt*",")+prot;
d919491998-11-03Marcus Comstedt  if(sizeof(argt)) res += "\n check_all_args(\""+name+"\", args, "+ ((Array.map((argt_cut<0?argt:argt[..argt_cut-1]), lambda(string t) {
66c3f31999-07-24Marcus Comstedt  string t2; while(3==sscanf(t, "%s(%*s)%s", t, t2)) t+=t2;
d919491998-11-03Marcus Comstedt  return Array.map(t/"|", lambda(string t) { return "BIT_"+upper_case(t); })*"|"; }))+
66c3f31999-07-24Marcus Comstedt  (r234>0?({"BIT_MANY|BIT_MIXED|BIT_VOID"}):({}))+({"0"}))*", "+");\n";
d919491998-11-03Marcus Comstedt 
12b8c71998-11-03Marcus Comstedt  if(sizeof(got)) res += "\n"+got+"\n"; switch(r234) { case 0:
2569d41999-07-25Marcus Comstedt  if(polya<0) res += (vret?" res=":" ")+fu+"("+(args*",")+");\n"; else res += " switch("+args[polya]+".type) {\n"+ Array.map(argt[polya]/"|", lambda(string t) { array(string) a = copy_value(args); a[polya] += ".u"; switch(t) { case "int": a[polya]+=".integer"; break; case "float": a[polya]+=".float_number"; break; } return " case T_"+upper_case(t)+": "+ (vret?"res=":"")+fu+t[0..0]+"("+ (a*",")+"); break;\n"; })*""+" }\n";
12b8c71998-11-03Marcus Comstedt  break; case 1: if(sizeof(rtypes)==1) res += " switch(r234) {\n"+Array.map(novec, lambda(int i, string vret, string r, string fu, array(string) args) { return " case "+i+": "+ (vret?"res=":"")+ fu+i+"v("+ (args+({"zv4.v."+r}))* ","+"); break;"; }, vret, rtypes, fu, args)* "\n"+"\n }\n"; else res += " switch(zv4.ty) {\n"+ Array.map(indices(rtypes), lambda(int i, string r, string fu, string vret, array(string) args, array(int) novec) { return " case ZT_"+ (['i':"INT",'f':"FLOAT",'d':"DOUBLE"])[r[i]]+ ": switch(r234) {\n"+ Array.map(novec, lambda(int i, string vret, string r, string fu, array(string) args) { return " case "+i+": "+ (vret?"res=":"")+ fu+i+r+"v("+ (args+({"zv4.v."+r}))* ","+"); break;"; }, vret, r[i..i], fu, args)* "\n"+"\n }\n break;"; }, rtypes, fu, vret, args, novec)*"\n"+ "\n }\n"; break; case 2: if(sizeof(rtypes)==1) res += (vret?" res=":" ")+fu+"("+ ((args+(novec? Array.map(novec, lambda(int i, string rtypes) { return "zv4.v."+rtypes+"["+i+"]"; }, rtypes):({"zv4.v."+rtypes})))*",")+ ");\n"; else res += " switch(zv4.ty) {\n"+ Array.map(indices(rtypes), lambda(int i, string r, string fu, string vret, array(string) args, array(int) novec) { return " case ZT_"+ (['i':"INT",'f':"FLOAT",'d':"DOUBLE"])[r[i]]+": "+ (vret?"res=":"")+fu+r[i..i]+(novec?"(":"v(")+ ((args+(novec? Array.map(novec, lambda(int i, string r) { return "zv4.v."+r+ "["+i+"]"; }, r[i..i]): ({"zv4.v."+r[i..i]})))*",")+"); break;"; }, rtypes, fu, vret, args, novec)*"\n"+ "\n }\n"; break; case 3: if(sizeof(rtypes)==1) res += " if(r1n&ZT_ARRAY)\n"+ (vret?" res=":" ")+fu+"v("+(args+({"zv16."+rtypes}))*","+ ");\n else\n"+ (vret?" res=":" ")+fu+"("+(args+({"zv16."+rtypes+"[0]"}))*","+ ");\n"; else res += " switch(r1n) {\n"+ Array.map(indices(rtypes), lambda(int i, string r, string fu, string vret, array(string) args, array(int) novec) { return " case ZT_"+ (['i':"INT",'f':"FLOAT",'d':"DOUBLE"])[r[i]]+": "+ (vret?"res=":"")+fu+r[i..i]+"("+ ((args+({"zv16."+r[i..i]+"[0]"}))*",")+"); break;\n"+ " case ZT_ARRAY|ZT_"+ (['i':"INT",'f':"FLOAT",'d':"DOUBLE"])[r[i]]+": "+ (vret?"res=":"")+fu+r[i..i]+"v("+ ((args+({"zv16."+r[i..i]}))*",")+"); break;"; }, rtypes, fu, vret, args, novec)*"\n"+ "\n }\n"; break;
66c3f31999-07-24Marcus Comstedt  case -1: res += " switch(r1n) {\n"+ Array.map(indices(rtypes), lambda(int i, string r, string fu, string vret, array(string) args, array(int) novec) { return " case ZT_ARRAY|ZT_"+ (['i':"INT",'f':"FLOAT",'d':"DOUBLE"])[r[i]]+": "+ (vret?"res=":"")+fu+r[i..i]+"("+ ((args+({"zv16."+r[i..i]}))*",")+"); break;"; }, rtypes, fu, vret, args, novec)*"\n"+ "\n }\n"; break;
12b8c71998-11-03Marcus Comstedt  }
1588bf1999-07-17Marcus Comstedt  if(img_obj) { res += " release_img(&img);\n"; }
12b8c71998-11-03Marcus Comstedt  res += " pop_n_elems(args);\n";
2569d41999-07-25Marcus Comstedt  res += (vret? " "+vret+"("+(vcast||"")+"res);\n":/*" push_int(0);\n"*/"");
12b8c71998-11-03Marcus Comstedt  res += "}\n\n"; return ({res,prot}); } string gen() { string res = ""; array t = Array.transpose(func_misc); array fn=t[0]; mapping ty = mkmapping(@t); mapping prot = ([]); foreach(indices(func_cat), string cat) { fn += func_cat[cat]; ty |= mkmapping(func_cat[cat], rows(({cat}), allocate(sizeof(func_cat[cat])))); } sort(fn); foreach(fn, string f) { array(string) r = gen_func(f, ty[f]); res += r[0]; prot[f]=r[1]; }
1cdf801999-07-25Marcus Comstedt  res += "void GL_add_auto_funcs()\n{\n";
1588bf1999-07-17Marcus Comstedt  res += " pre_init();\n";
12b8c71998-11-03Marcus Comstedt  foreach(fn, string f) res += " add_function_constant(\""+f+"\", f_"+f+",\n\t\t\t\"function("+ prot[f]+")\", OPT_SIDE_EFFECT);\n"; foreach(sort(indices(constants)), string co)
174ef51999-11-07Per Hedbor  res += " add_integer_constant(\""+co+"\", "+ (string)constants[co]+", 0);\n";
1588bf1999-07-17Marcus Comstedt  res += " post_init();\n";
12b8c71998-11-03Marcus Comstedt  res += "}\n"; return res; } void main(int argc, array(string) argv) { array(string) f = Stdio.File("stdin")->read()/"@@"; write(({f[0],gen(),@f[1..]})*""); }