IDFstepper
IDF to STEP converter
|
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