00001 #include<ImLib3D/ImageProcessorsDescription.hpp>
00002 #include<ImLib3D/XMLTools.hpp>
00003 #include<ImLib3D/Base64.hpp>
00004 #include <stdexcept>
00005
00006
00007 void DeclareArg(XIPD::Argument arg,int j,string &out);
00008 void
00009 GenerateDefinitionsStandardTemplated(ImageProcessorsDescription &imProcsDescription,vector<string> procNames,string &out);
00010 void
00011 GenerateDefinitionsStandardNonTemplated(ImageProcessorsDescription &imProcsDescription,vector<string> procNames,string &out);
00012 void
00013 GenerateTemplateGroups(ImageProcessorsDescription &imProcsDescription,vector<string> procNames,string &out);
00014 void
00015 GenerateCalls(ImageProcessorsDescription &imProcsDescription,vector<string> procNames,string &out);
00016 void
00017 GenerateHardCodedDescription(string xmlDescriptionFile,string &out);
00018 void
00019 GeneratePlugin(ImageProcessorsDescription &imProcsDescription,vector<string> procNames,string xmlDescriptionFile,string userHeader,string &out);
00020
00021 void
00022 WriteStringToFileIfChanged(const string &fname,const string &data);
00023
00024
00025 string warning="// *************** DO NOT MODIFY!!! ***********\n// ** AUTOMATICALLY GENERATED SRC CODE **\n\n";
00026
00027 string definitionsFilename="ImageProcessorsByNameDefinitions.cpp";
00028 string callsFilename="ImageProcessorsByNameCalls.cpp";
00029 string templateGroupsFilename="TemplateGroups.hpp";
00030
00031 void
00032 Usage()
00033 {
00034 printf("Usage:\n");
00035 printf("imlib3d-code-generation --definitions descriptions.xml %s [--extra-description=extra.xml]\n",definitionsFilename.c_str());
00036 printf("imlib3d-code-generation --calls descriptions.xml %s [--extra-description=extra.xml]\n",callsFilename.c_str());
00037 printf("imlib3d-code-generation --template-groups descriptions.xml %s \n",templateGroupsFilename.c_str());
00038 printf("imlib3d-code-generation --hardcode source dest\n");
00039 printf("imlib3d-code-generation --plugin descriptions.xml Header.hpp Plugin.cpp [extra.xml] \n");
00040 ThrowError("bad commandline");
00041 exit(1);
00042 }
00043
00044 string
00045 ParseOptionalArg(vector<string> &args,const string &name)
00046 {
00047 string baseName=name;
00048 bool hasValue=false;
00049 if(name.size() && name[name.size()-1]=='=')
00050 {
00051 hasValue=true;
00052 }
00053 for(uint i=0;i<args.size();i++)
00054 {
00055 if(args[i].size()>=baseName.size() &&
00056 args[i].substr(0,baseName.size())==baseName)
00057 {
00058 string arg=args[i];
00059 args.erase(args.begin()+i);
00060 if(hasValue)
00061 {
00062 return arg.substr(name.size());
00063 }
00064 else
00065 {
00066 return "yes";
00067 }
00068 }
00069 }
00070 return "";
00071 }
00072 int
00073 main(int argc,char **argv)
00074 {
00075 vector<string> args;
00076 for(int i=1;i<argc;i++){args.push_back(argv[i]);}
00077
00078 SetErrorManagementType(ERROR_USE_EXCEPTIONS);
00079
00080 if(args.size()==0){Usage();}
00081
00082
00083 if(args[0]=="--definitions" ||
00084 args[0]=="--calls" ||
00085 args[0]=="--template-groups" ||
00086 args[0]=="--plugin" )
00087 {
00088
00089 string extraDescription=ParseOptionalArg(args,"--extra-description=");
00090 string xmlDescriptionFile=args[1];
00091 string outputFile=args[2];
00092 string out=warning;
00093 ImageProcessorsDescription imProcsDescription;
00094 imProcsDescription.ReadFromFile(xmlDescriptionFile);
00095 vector<string> procNames=imProcsDescription.GetNames(true);
00096 if(extraDescription!="")
00097 {
00098
00099
00100 ImageProcessorsDescription extra;
00101 extra.ReadFromFile(extraDescription);
00102 imProcsDescription.Merge(extra);
00103 }
00104
00105 if(args[0]=="--definitions")
00106 {
00107 if(args.size()!=3){Usage();}
00108 GenerateDefinitionsStandardTemplated(imProcsDescription,procNames,out);
00109 GenerateDefinitionsStandardNonTemplated(imProcsDescription,procNames,out);
00110 }
00111 else
00112 if(args[0]=="--calls")
00113 {
00114 if(args.size()!=3){Usage();}
00115 GenerateCalls(imProcsDescription,procNames,out);
00116 }
00117 else
00118 if(args[0]=="--template-groups")
00119 {
00120 if(args.size()!=3){Usage();}
00121 GenerateTemplateGroups(imProcsDescription,procNames,out);
00122 }
00123 else
00124 if(args[0]=="--plugin")
00125 {
00126 if(args.size()!=4){Usage();}
00127 outputFile=args[3];
00128 GeneratePlugin(imProcsDescription,procNames,xmlDescriptionFile,args[2],out);
00129 }
00130 else
00131 {
00132 ThrowError("imlib3d-code-generation: incoherence!");
00133 }
00134 WriteStringToFileIfChanged(outputFile,out);
00135 exit(0);
00136 }
00137 if(args[0]=="--hardcode")
00138 {
00139 if(args.size()!=3){Usage();}
00140
00141 string srcData=args[1];
00142 string destFile=args[2];
00143 string out;
00144 GenerateHardCodedDescription(srcData,out);
00145 WriteStringToFileIfChanged(destFile,out);
00146 exit(0);
00147 }
00148 Usage();
00149 }
00150 void
00151 GenerateDefinitionsStandardTemplated(ImageProcessorsDescription &imProcsDescription,vector<string> procNames,string &out)
00152 {
00153
00154 for(uint i=0;i<procNames.size();i++)
00155 {
00156 try{
00157 string procName=procNames[i];
00158 XIPD::ImageProcessor proc=*imProcsDescription.GetImageProcessor(procName);
00159 if(proc.type!="standard templated"){continue;}
00160
00161 out+="template<class ImageType >\n";
00162 out+="void\n";
00163 out+="ImProc_"+procName+"_";
00164 out+="StrArgs(const string &procName,const vector<string> &args,vector<TypeSafeGenericPointer> &alternateArgs)\n";
00165 out+="{\n";
00166 if(proc.conditional!=""){out+="#ifdef "+proc.conditional+"\n";}
00167 out+="\ttypedef typename ImageType::value_type Im3DValue;\n";
00168
00169 for(uint j=0;j<proc.arguments.size();j++){DeclareArg(proc.arguments[j],j,out);}
00170
00171 out+="\tIP3D::"+procName+"(";
00172 for(uint j=0;j<proc.arguments.size();j++)
00173 {
00174 out+=(j>0 ? ", " : "")+
00175 string(proc.arguments[j].optType=="pointer" ? "&" : "")+
00176 SPrintf("arg%d",j);
00177 }
00178 out+=");\n";
00179
00180 for(uint j=0;j<proc.arguments.size();j++)
00181 {
00182 XIPD::Argument arg=proc.arguments[j];
00183 if(arg.direction=="output" && arg.ignoreOutput!="yes")
00184 {
00185 out+="\tImProcOutputArg< "+arg.type+" >("+SPrintf("arg%d",j)+","
00186 +SPrintf("args[%d]",j)+",alternateArgs,"+SPrintf("%d",j)+");\n";
00187 }
00188 if(arg.isOptional!="true" || arg.optType=="pointer")
00189 {
00190 out+="\tCleanupArg< "+arg.type+" >("+SPrintf("arg%d",j)+",alternateArgs,"+SPrintf("%d",j)+");\n";
00191 }
00192 }
00193
00194 if(proc.conditional!="")
00195 {
00196 out+="#else\n ThrowError(\"support for "+procName+" was not compiled\");\n#endif\n";
00197 }
00198 out+="}\n";
00199 }catch(std::exception& __fail){ThrowError("problem in parsing processor \"%s\"",procNames[i].c_str());}
00200 }
00201 }
00202
00203 void
00204 GenerateDefinitionsStandardNonTemplated(ImageProcessorsDescription &imProcsDescription,vector<string> procNames,string &out)
00205 {
00206
00207
00208 for(uint i=0;i<procNames.size();i++)
00209 {
00210 try
00211 {
00212 string procName=procNames[i];
00213 XIPD::ImageProcessor proc=*imProcsDescription.GetImageProcessor(procName);
00214 if(proc.type!="standard"){continue;}
00215 out+="void\n";
00216 out+="ImProc_"+procName+"_";
00217 out+="StrArgs(const string &procName,const vector<string> &args,vector<TypeSafeGenericPointer> &alternateArgs)\n";
00218 out+="{\n";
00219 if(proc.conditional!=""){out+="#ifdef "+proc.conditional+"\n";}
00220
00221 for(uint j=0;j<proc.arguments.size();j++){DeclareArg(proc.arguments[j],j,out);}
00222
00223 out+="\tIP3D::"+procName+"(";
00224 for(uint j=0;j<proc.arguments.size();j++)
00225 {
00226 out+=(j>0 ? ", " : "")+
00227 string(proc.arguments[j].optType=="pointer" ? "&" : "")+
00228 SPrintf("arg%d",j);
00229 }
00230 out+=");\n";
00231
00232 for(uint j=0;j<proc.arguments.size();j++)
00233 {
00234 XIPD::Argument arg=proc.arguments[j];
00235 if(arg.direction=="output")
00236 {
00237 out+="\tImProcOutputArg< "+arg.type+" >("+SPrintf("arg%d",j)+","+
00238 SPrintf("args[%d]",j)+",alternateArgs,"+SPrintf("%d",j)+");\n";
00239 }
00240 if(!(arg.isOptional=="true") || arg.optType=="pointer")
00241 {
00242 out+="\tCleanupArg< "+arg.type+" >("+SPrintf("arg%d",j)+",alternateArgs,"+SPrintf("%d",j)+");\n";
00243 }
00244 }
00245
00246 if(proc.conditional!="")
00247 {
00248 out+="#else\n ThrowError(\"support for "+procName+" was not compiled\");\n#endif\n";
00249 }
00250 out+="}\n";
00251 }
00252 catch(std::exception& __fail)
00253 {
00254 ThrowError("problem in parsing processor \"%s\"",procNames[i].c_str());
00255 }
00256 }
00257 }
00258 void
00259 GenerateCalls(ImageProcessorsDescription &imProcsDescription,vector<string> procNames,string &out2)
00260 {
00261
00262 out2+="void StandardImProcCalls(const string &procName,const vector<string> &args,string typeName,vector<TypeSafeGenericPointer> alternateArgs=vector<TypeSafeGenericPointer>())\n{\n";
00263 for(uint i=0;i<procNames.size();i++)
00264 {
00265 try{
00266 string procName=procNames[i];
00267 XIPD::ImageProcessor proc=*imProcsDescription.GetImageProcessor(procName);
00268 string fct="ImProc_"+procName+"_StrArgs";
00269 if(proc.type=="standard templated")
00270 {
00271 string group=proc.templateGroup;
00272
00273 if(!imProcsDescription.GetTemplateGroup(group))
00274 {
00275 printf("Warning: template group \"%s\" is not described\n",group.c_str());
00276 }
00277
00278 string macroName= "CallWith"+group+"_3";
00279 out2+=" if(procName==\""+procName+"\"){"+macroName+"("+fct+",typeName,procName,args,alternateArgs);}\n";
00280 out2+=" else\n";
00281 }
00282 else
00283 if(proc.type=="standard")
00284 {
00285 out2+=" if(procName==\""+procName+"\"){"+fct+"(procName,args,alternateArgs);}\n";
00286 out2+=" else\n";
00287 }
00288 }catch(std::exception& __fail){ThrowError("problem in parsing processor \"%s\"",procNames[i].c_str());}
00289 }
00290 out2+=" {ThrowError(\"unimplemented call by name image processor interface for:\\\"%s\\\"please report this bug\",procName);}\n";
00291 out2+="}\n";
00292
00293 }
00294
00295
00297 void
00298 GenerateHardCodedDescription(string xmlDescriptionFile,string &out)
00299 {
00300 string fileContents;
00301 int dataSize;
00302
00303 void *data=Read(xmlDescriptionFile,&dataSize,true);
00304 char *cdata=(char *)data;
00305 fileContents.reserve(dataSize);
00306 for(int i=0;i<dataSize;i++){fileContents+=cdata[i];}
00307
00308 out+="string hardcodedDescription(\n\t\"";
00309
00310 string encoded=Base64::Encode(fileContents);
00311 for(uint i=0;i<encoded.size();i++)
00312 {
00313 if(i>0 && !(i%80)){out+="\"\n\t\"";}
00314 out+=encoded[i];
00315 }
00316 out+="\");\n";
00317
00318 delete [] cdata;
00319 }
00320
00321 void
00322 GenerateTemplateGroups(ImageProcessorsDescription &imProcsDescription,vector<string> procNames,string &out)
00323 {
00324 printf(" found %d template groups\n",imProcsDescription.templateGroups.size());
00325 for(uint i=0;i<imProcsDescription.templateGroups.size();i++)
00326 {
00327 XIPD::TemplateGroup &group=imProcsDescription.templateGroups[i];
00328 uint maxNbArgs=5;
00329 for(uint nbArgs=0;nbArgs<maxNbArgs;nbArgs++)
00330 {
00331 string macroName= "CallWith"+group.name+SPrintf("_%d",nbArgs);
00332 out+="#define "+macroName+"(fct,typeName";
00333 for(uint j=0;j<nbArgs;j++){out+=SPrintf(",a%d",j);}
00334 out+=")\\\n";
00335 for(uint j=0;j<group.types.size();j++)
00336 {
00337 string type=group.types[j];
00338 out+=" if(typeName==\""+type+"\"){fct< "+type+" >(";
00339 for(uint k=0;k<nbArgs;k++){out+=(k>0 ? "," : "")+SPrintf("a%d",k);}
00340 out+=");}\\\n";
00341 out+=" else\\\n";
00342 }
00343 out+=" {ThrowError(\""+macroName+" failed, type \\\"%s\\\" is not in template group \\\""+
00344 group.name+"\\\"\",typeName);}\n";
00345 }
00346 }
00347 }
00348 void
00349 GeneratePlugin(ImageProcessorsDescription &imProcsDescription,vector<string> procNames,string xmlDescriptionFile,string userHeader,string &out)
00350 {
00351 out+="#include<ImLib3D/ImLib3D.hpp>\n";
00352 out+="#include<ImLib3D/TemplateGroups.hpp>\n\n";
00353
00354 out+="#include<ImLib3D/StringArgumentConversion.hpp>\n\n";
00355 out+="#include\""+userHeader+"\"\n\n";
00356
00357 GenerateDefinitionsStandardTemplated(imProcsDescription,procNames,out);
00358 GenerateDefinitionsStandardNonTemplated(imProcsDescription,procNames,out);
00359 GenerateCalls(imProcsDescription,procNames,out);
00360
00361 GenerateHardCodedDescription(xmlDescriptionFile,out);
00362 out+="\n";
00363 out+="#include<ImLib3D/UserPlugin.hpp>\n\n";
00364 out+="int\nmain(int argc,char **argv)\n{\n";
00365 out+="\tUserPluginMain(argc,argv);\n";
00366 out+="\treturn 0;\n}\n";
00367
00368
00369
00370
00371
00372
00373
00374
00375 }
00376
00377 void
00378 DeclareArg(XIPD::Argument iparg,int j,string &out)
00379 {
00380 string type=iparg.type;
00381 string arg=SPrintf(" arg%d ",j);
00382 string str=SPrintf(" args[%d] ",j);
00383 if(!(iparg.isOptional=="true"))
00384 {
00385 if(iparg.direction!="output")
00386 {
00387 out+="\t"+type+"&"+arg+"=*StringOrAlternateInputArg<"+type+" >("+str+",alternateArgs,"+SPrintf("%d ",j)+");\n";
00388 }
00389 else
00390 {
00391 out+="\t"+type+"&"+arg+"=*CreateOutputArg<"+type+" >(alternateArgs,"+SPrintf("%d ",j)+");\n";
00392 }
00393 }
00394 else
00395 {
00396 if(iparg.direction!="output")
00397 {
00398 if(iparg.optType=="pointer")
00399 {
00400 out+="\t"+type+"&"+arg+"=*OptionalPointerArg<"+type+" >("+str+",alternateArgs,"+SPrintf("%d ",j)+");\n";
00401 }
00402 else
00403 {
00404 string def=iparg.defaultValue;
00405 if(def=="" ){ThrowError("No default value for opt arg \"%s\" ",iparg.name);}
00406 out+="\t"+type+"&"+arg+"=*OptionalDefaultValueArg<"+type+" >("+str+",alternateArgs,"+SPrintf("%d ",j)+","+def+");\n";
00407 }
00408 }
00409 else
00410 {
00411 if(iparg.optType=="pointer")
00412 {
00413 out+="\t"+type+"&"+arg+"=*OptionalPointerArgCreateOutput<"+type+" >("+str+",alternateArgs,"+SPrintf("%d ",j)+");\n";
00414
00415
00416 }
00417 else
00418 {
00419
00420 ThrowError("optional default value output arg is not supported!!\n");
00421 }
00422 }
00423 }
00424 }
00425
00426
00427 void
00428 WriteStringToFileIfChanged(const string &fname,const string &data)
00429 {
00430 string tmp=WriteTmpFile(data);
00431 if(!FileExists(fname) || system(SPrintf("diff -q -N %s %s",fname,tmp).c_str())!=0)
00432 {
00433 mprintf("%s has changed, actually modifying\n",fname);
00434 WriteStringToFile(fname,data);
00435 }
00436 RemoveFile(tmp);
00437 }