Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

imlib3d-code-generation.cpp

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         // optionally mergein another description, for extra info (such as types)
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             // when generating for plugins, it is usefull to give the main XML description file.
00099             // That way you can use  the normal template groups
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         // hardcode file into string using base64 encoding
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     // ******************* generate standard templated ***********************
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         // generate function declaration
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         // generate argument declarations and initialisations
00169         for(uint j=0;j<proc.arguments.size();j++){DeclareArg(proc.arguments[j],j,out);}
00170         // generate actual call to image processor
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         // generate output res and cleanup 
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     // ******************* generate standard non templated ***********************
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         // generate argument declarations and initialisations
00221         for(uint j=0;j<proc.arguments.size();j++){DeclareArg(proc.arguments[j],j,out);}
00222         // generate actual call to image processor
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         // generate output res and cleanup 
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     // ******************* generate  improc fct calls ***********************
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             // this only checks if template group is valid
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 //      cout << out << endl;        
00293 }
00294 
00295 
00297 void
00298 GenerateHardCodedDescription(string xmlDescriptionFile,string  &out)
00299 {
00300     string fileContents;
00301     int dataSize;
00302     // in case we are encoding binary data, we read file as binary
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     // now generate code : string hardcodedDescription("jhlkjh...");
00308     out+="string hardcodedDescription(\n\t\"";
00309     // we need to split encoded string into several lines to avoid overflows :-(
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 //  bool CustomImProcCalls(const string &procName,const vector<string> &args,const string typeName,
00369 //                         vector<TypeSafeGenericPointer> alternateArgs)
00370 //  {
00371 //      return false;
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 //                  out+="\t"+type+"*"+arg+"=NULL;\n";
00415 //                  out+="\tif("+str+"!=\"\"){"+arg+"= new "+type+"();}\n";
00416             }
00417             else
00418             {
00419 //              out+="\t"+type+arg+";\n";
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 }

Generated on Fri Jun 17 13:36:04 2005 for ImLib3D by  doxygen 1.4.2