IDFstepper
IDF to STEP converter
src/Main.cpp
Go to the documentation of this file.
00001 #include "../inc/IdfParser.hpp"
00002 #include "../inc/IdfStructure.hpp"
00003 #include "../inc/StepGenerator.hpp"
00004 #include "../inc/ConfigParser.hpp"
00005 #include "../inc/ConfigType.hpp"
00006 #include <iostream>
00007 #include <fstream>
00008 #include <string>
00009 #include <sstream>
00010 #include <vector>
00011 #include <set>
00012 
00016 #define VERSION     "V1.0"
00017 
00172 #define err(stream);    std::cerr << stream; errBuf << stream;
00173 
00174 static void parseFile(
00175         const char* file,
00176         std::vector<config::Config>& configs,
00177         std::vector<idf::BoardPanelStruct>& panels,
00178         std::vector<idf::BoardPanelStruct>& boards,
00179         std::vector<idf::LibraryStruct>& libraries,
00180         std::ostringstream& errBuf);
00181 
00182 static bool parseIterator(
00183         std::string::const_iterator& iter,
00184         const std::string::const_iterator& end,
00185         std::vector<config::Config>& configs,
00186         std::vector<idf::BoardPanelStruct>& panels,
00187         std::vector<idf::BoardPanelStruct>& boards,
00188         std::vector<idf::LibraryStruct>& libraries);
00189 
00190 static void handleConfigs(
00191         const std::vector<config::Config>& configs,
00192         std::set<std::string>& usedConfigs,
00193         stepper::StepGenerator& generator,
00194         bool& alwaysExit,
00195         bool& alwaysWait,
00196         std::ostringstream& errBuf);
00197 
00198 static void createLibraries(
00199         const stepper::StepGenerator& generator,
00200         const std::vector<idf::LibraryStruct>& libs);
00201         
00202 static void createBoards(
00203         const stepper::StepGenerator& generator,
00204         const std::vector<idf::BoardPanelStruct>& boards);
00205         
00206 static void createPanels(
00207         const stepper::StepGenerator& generator,
00208         const std::vector<idf::BoardPanelStruct>& panels);
00209 
00210 static void handleOption(
00211         const std::pair<std::string, config::Value>& option,
00212         std::set<std::string>& usedConfigs,
00213         stepper::StepGenerator& generator,
00214         bool& alwaysExit,
00215         bool& alwaysWait,
00216         std::ostringstream& errBuf);
00217 
00218 static std::string exepath();
00219 
00220 
00221 int main(int argc, char** argv) {
00222   std::cout << "IDFstepper " VERSION "\n\n";
00223   
00224   std::ostringstream errBuf;
00225   
00226   std::vector<config::Config> configs;
00227   std::vector<idf::BoardPanelStruct> panels;
00228   std::vector<idf::BoardPanelStruct> boards;
00229   std::vector<idf::LibraryStruct> libraries;
00230   std::set<std::string> usedConfigs;
00231   
00232   // Parse the main config file
00233   std::string mainconf(exepath() + "idfstepper.conf");
00234   parseFile(mainconf.c_str(), configs, panels, boards, libraries, errBuf);
00235   usedConfigs.insert(mainconf);
00236   if (configs.empty()) {
00237     err("WARNING: Main configuration file could not be read.\n");
00238   }
00239   
00240   if (argc > 1) {
00241 
00242     for (int i = 1; i < argc; ++i) {
00243       parseFile(argv[i], configs, panels, boards, libraries, errBuf);
00244     }
00245 
00246     std::cout << "Parser summary:\n";
00247     int cs = configs.size(), ps = panels.size();
00248     int bs = boards.size(), ls = libraries.size();
00249     std::cout << cs << " config file" << (cs==1?"":"s") << ",\n";
00250     std::cout << ps << " panel" << (ps==1?"":"s") << ",\n";
00251     std::cout << bs << " board" << (bs==1?"":"s") << ",\n";
00252     std::cout << ls << " librar" << (ls==1?"y":"ies") << "\n";
00253     std::cout << std::endl;
00254     
00255   }
00256   
00257   bool alwaysExit = false, alwaysWait = false;
00258   stepper::StepGenerator generator(errBuf);
00259   
00260   handleConfigs(configs, usedConfigs, generator,
00261           alwaysExit, alwaysWait, errBuf);
00262   
00263   if (argc < 2) {
00264     err("ERROR: No files have been specified for processing.\n\n");
00265     err("Usage: " << argv[0]);
00266     err(" file1 [file2] [file3] [...]\n\n");
00267     err("Each file may be:\n");
00268     err("- A configuration file,\n");
00269     err("- an IDF library file,\n");
00270     err("- an IDF board file, or\n");
00271     err("- an IDF panel file.\n\n");
00272     err("The default configuration file in the executable's folder\n");
00273     err("does not need to be passed explicitly. Configuration files\n");
00274     err("are processed in the order specified. The order of IDF\n");
00275     err("files does not matter, they are always processed in the\n");
00276     err("following order:\n");
00277     err("1. Library files\n");
00278     err("2. Board files\n");
00279     err("3. Panel files\n\n");
00280     err("File types are determined by their content, name\n");
00281     err("extensions are not considered.\n\n");
00282     err("This software depends on parts of the OpenCASCADE 3D solid\n");
00283     err("modelling library. See http://opencascade.org\n\n");
00284     err("Check http://hb9etc.ch for more information.\n\n");
00285     if (alwaysWait || !alwaysExit) {
00286       err("\nPress ENTER to exit.\n");
00287       std::cin.get();
00288     }
00289     return -1;
00290   }
00291 
00292   createLibraries(generator, libraries);
00293   createBoards(generator, boards);
00294   createPanels(generator, panels);
00295   
00296   bool wait = false;
00297   if (errBuf.str().size() > 0) {
00298     std::cerr << "\nThere have been errors/warnings:\n";
00299     std::cerr << "--------------------------------------------------\n";
00300     std::cerr << errBuf.str();
00301     std::cerr << "--------------------------------------------------\n";
00302     wait = true;
00303   }
00304   
00305   wait &= !alwaysExit;
00306   wait |= alwaysWait;
00307   if (wait) {
00308     std::cerr << "\nPress ENTER to exit.\n";
00309     std::cin.get();
00310   }
00311   
00312   return 0;
00313 }
00314 
00315 static void parseFile(
00316         const char* file,
00317         std::vector<config::Config>& configs,
00318         std::vector<idf::BoardPanelStruct>& panels,
00319         std::vector<idf::BoardPanelStruct>& boards,
00320         std::vector<idf::LibraryStruct>& libraries,
00321         std::ostringstream& errBuf)
00322 {
00323   std::ifstream infile;
00324   infile.open(file);
00325   if (!infile.is_open()) {
00326     err("WARNING: Unable to open file '" << file << "'.\n");
00327     return;
00328   }
00329   
00330   std::stringstream buffer;
00331   buffer << infile.rdbuf();
00332   std::string input(buffer.str());
00333   std::string::const_iterator iter = input.begin();
00334   std::string::const_iterator end = input.end();
00335   
00336   int n = 0;
00337   while (iter != end) {
00338     if (!parseIterator(iter, end, configs, panels, boards, libraries)) {
00339       break;
00340     }
00341     ++n;
00342   }
00343   
00344   if (n == 0) {
00345     err("WARNING: Failed to parse file '" << file << "'.\n");
00346     
00347     std::string::const_iterator some = iter+30;
00348     if (some > end) some = end;
00349     std::string context(iter, some);
00350     
00351     err("Parser context at end: '" << context << "'.\n");
00352   } else {
00353     std::cout << "Parsed file '" << file << "' into " << n;
00354     std::cout << " structure" << (n==1?"":"s") << ".\n";
00355   }
00356 }
00357 
00358 static bool parseIterator(
00359         std::string::const_iterator& iter,
00360         const std::string::const_iterator& end,
00361         std::vector<config::Config>& configs,
00362         std::vector<idf::BoardPanelStruct>& panels,
00363         std::vector<idf::BoardPanelStruct>& boards,
00364         std::vector<idf::LibraryStruct>& libraries)
00365 {
00366   config::Config conf;
00367   bool r = config::parseConfig(iter, end, conf);
00368   
00369   if (r) {
00370     configs.push_back(conf);
00371   } else {
00372     idf::BoardPanelStruct board;  
00373     r = idf::parseBoardPanel(iter, end, board);
00374     
00375     if (r) {
00376       if (board.fileType == idf::PANEL_FILE) {
00377         panels.push_back(board);
00378       } else {
00379         boards.push_back(board);
00380       }
00381       
00382     } else {
00383       idf::LibraryStruct library;
00384       r = idf::parseLibrary(iter, end, library);
00385       
00386       if (r) {
00387         libraries.push_back(library);
00388       }
00389     }
00390   }
00391   
00392   return r;
00393 }
00394 
00395 static void handleConfigs(
00396         const std::vector<config::Config>& configs,
00397         std::set<std::string>& usedConfigs,
00398         stepper::StepGenerator& generator,
00399         bool& alwaysExit,
00400         bool& alwaysWait,
00401         std::ostringstream& errBuf)
00402 {
00403   
00404   for (size_t i = 0; i < configs.size(); ++i) {
00405     
00406     config::Config::const_iterator iter = configs[i].begin();
00407     config::Config::const_iterator end = configs[i].end();
00408     
00409     while (iter != end) {
00410       handleOption(*iter, usedConfigs, generator,
00411               alwaysExit, alwaysWait, errBuf);
00412       
00413       ++iter;
00414     }
00415   }
00416 }
00417 
00418 static void createLibraries(
00419         const stepper::StepGenerator& generator,
00420         const std::vector<idf::LibraryStruct>& libs)
00421 {
00422   std::vector<idf::LibraryStruct>::const_iterator it = libs.begin();
00423   while (it != libs.end()) {
00424     generator.generateLibrary(*it++);
00425   }
00426 }
00427 
00428 static void createBoards(
00429         const stepper::StepGenerator& generator,
00430         const std::vector<idf::BoardPanelStruct>& boards)
00431 {
00432   std::vector<idf::BoardPanelStruct>::const_iterator it = boards.begin();
00433   while (it != boards.end()) {
00434     generator.generateBoard(*it++);
00435   }
00436 }
00437 
00438 static void createPanels(
00439         const stepper::StepGenerator& generator,
00440         const std::vector<idf::BoardPanelStruct>& panels)
00441 {
00442   std::vector<idf::BoardPanelStruct>::const_iterator it = panels.begin();
00443   while (it != panels.end()) {
00444     generator.generatePanel(*it++);
00445   }
00446 }
00447 
00448 static void handleOption(
00449         const std::pair<std::string, config::Value>& option,
00450         std::set<std::string>& usedConfigs,
00451         stepper::StepGenerator& generator,
00452         bool& alwaysExit,
00453         bool& alwaysWait,
00454         std::ostringstream& errBuf)
00455 {
00456   try {
00457     // Handle general options first
00458     if (option.first == "ALWAYS_EXIT") {
00459       alwaysExit = boost::get<bool>(option.second);
00460       
00461     } else if (option.first == "ALWAYS_WAIT") {
00462       alwaysWait = boost::get<bool>(option.second);
00463       
00464     } else if (option.first == "INCLUDE") {
00465       std::string file = boost::get<std::string>(option.second);
00466       
00467       if (!file.empty()) {
00468         // Break the recursion if a config file includes itself
00469         if (usedConfigs.find(file) != usedConfigs.end()) {
00470           err("WARNING: Ignoring already processed config file '");
00471           err(file << "'.\n");
00472         } else {
00473           usedConfigs.insert(file);
00474           std::cout << "Processing included config file '" << file;
00475           std::cout << "'...\n";
00476           std::ifstream infile;
00477           infile.open(file.c_str());
00478           if (!infile.is_open()) {
00479             err("WARNING: Unable to open included config file '");
00480             err(file << "'.\n");
00481           } else {
00482             std::stringstream buffer;
00483             buffer << infile.rdbuf();
00484             std::string input(buffer.str());
00485             config::Config conf;
00486             std::string::const_iterator iter = input.begin();
00487             std::string::const_iterator end = input.end();
00488             if (!config::parseConfig(iter, end, conf)) {
00489               err("WARNING: Failed to parse file '" << file << "'.\n");            
00490               std::string::const_iterator some = iter+30;
00491               if (some > end) some = end;
00492               std::string context(iter, some);            
00493               err("WARNING: Parser context at end: '" << context << "'.\n");
00494             } else {
00495               std::vector<config::Config> configs;
00496               configs.push_back(conf);
00497               handleConfigs(configs, usedConfigs, generator,
00498                       alwaysExit, alwaysWait, errBuf);
00499               
00500               std::cout << "Parsed config file '" << file << "'.\n";
00501             }
00502           }
00503         }
00504       }
00505     } else {
00506       if (!generator.setConfigOption(option.first, option.second)) {
00507         err("WARNING: Ignoring unknown config option '");
00508         err(option.first << "'.\n");
00509       }
00510     }
00511   } catch (boost::bad_get ex) {
00512     err("WARNING: Config value of " << option.first);
00513     err(" is of incompatible type.\n");
00514   }
00515 }
00516 
00517 #ifdef _WIN32
00518 // No clue why this is needed...
00519 #undef NONLS
00520 #include <windows.h>
00521 #include <winnls.h>
00522 static std::string exepath() {
00523   wchar_t result[MAX_PATH];
00524   char cstr[MAX_PATH+1];
00525   unsigned long found;
00526   GetModuleFileName(0, result, MAX_PATH);
00527   WideCharToMultiByte(CP_UTF8, 0, result, -1, cstr, MAX_PATH, 0, 0);
00528   cstr[MAX_PATH] = 0;
00529   found = std::string(cstr).find_last_of("\\");
00530   return(std::string(cstr).substr(0,found) + "\\");
00531 }
00532 #else
00533 #include <unistd.h>
00537 static std::string exepath() {
00538   char result[PATH_MAX+1];
00539   unsigned long found;
00540   ssize_t count = readlink( "/proc/self/exe", result, PATH_MAX );
00541   if (count > 0) {
00542     result[count] = 0;
00543     found = std::string(result).find_last_of("/");
00544     return(std::string(result).substr(0,found) + "/");
00545   } else {
00547     return std::string();
00548   }
00549 }
00550 #endif
00551 
00552 
00553 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines