77
PackageVisitor(const string&, const string&);
101
static void createModules(const UnitPtr&, const string&, const string&);
79
virtual bool visitModuleStart(const ModulePtr&);
80
103
virtual void visitModuleEnd(const ModulePtr&);
107
PackageVisitor(StringList&);
84
109
enum ReadState { PreModules, InModules, InSubmodules };
86
111
static const char* _moduleTag;
87
112
static const char* _submoduleTag;
89
void createDirectory(const string&);
91
void addModule(const string&, const string&);
92
void addSubmodule(const string&, const string&);
94
void readInit(const string&, StringList&, StringList&);
95
void writeInit(const string&, const StringList&, const StringList&);
98
StringList _pathStack;
114
static void createDirectory(const string&);
116
static void addModule(const string&, const string&, const string&);
117
static void addSubmodule(const string&, const string&, const string&);
119
static void readInit(const string&, StringList&, StringList&);
120
static void writeInit(const string&, const string&, const StringList&, const StringList&);
122
StringList& _modules;
101
125
const char* PackageVisitor::_moduleTag = "# Modules:";
102
126
const char* PackageVisitor::_submoduleTag = "# Submodules:";
104
PackageVisitor::PackageVisitor(const string& module, const string& dir) :
128
PackageVisitor::PackageVisitor(StringList& modules) :
109
_pathStack.push_front(".");
113
_pathStack.push_front(dir);
118
PackageVisitor::visitModuleStart(const ModulePtr& p)
134
PackageVisitor::createModules(const UnitPtr& unit, const string& module, const string& dir)
120
assert(!_pathStack.empty());
121
string name = fixIdent(p->name());
124
if(_pathStack.size() == 1)
126
path = _pathStack.front();
129
// Check top-level modules for package metadata and create the package
132
string package = getPackageMetadata(p);
136
if(!IceUtilInternal::splitString(package, ".", v))
140
for(vector<string>::iterator q = v.begin(); q != v.end(); ++q)
144
addSubmodule(path, fixIdent(*q));
148
createDirectory(path);
150
addModule(path, _module);
153
addSubmodule(path, name);
160
path = _pathStack.front() + "/" + name;
163
string parentPath = _pathStack.front();
164
_pathStack.push_front(path);
166
createDirectory(path);
169
// If necessary, add this module to the set of imported modules in __init__.py.
171
addModule(path, _module);
174
// If this is a submodule, then modify the parent's __init__.py to import us.
176
ModulePtr mod = ModulePtr::dynamicCast(p->container());
179
addSubmodule(parentPath, name);
137
PackageVisitor v(modules);
138
unit->visit(&v, false);
140
for(StringList::iterator p = modules.begin(); p != modules.end(); ++p)
143
if(!IceUtilInternal::splitString(*p, ".", v))
147
string currentModule;
148
string path = dir.empty() ? "." : dir;
149
for(vector<string>::iterator q = v.begin(); q != v.end(); ++q)
153
addSubmodule(path, currentModule, *q);
154
currentModule += ".";
159
createDirectory(path);
161
addModule(path, currentModule, module);
186
167
PackageVisitor::visitModuleEnd(const ModulePtr& p)
188
assert(!_pathStack.empty());
189
_pathStack.pop_front();
170
// Collect the most deeply-nested modules. For example, if we have a
171
// module named M.N.O, then we don't need to keep M or M.N in the list.
173
string abs = getAbsolute(p);
174
if(find(_modules.begin(), _modules.end(), abs) == _modules.end())
176
_modules.push_back(abs);
178
string::size_type pos = abs.rfind('.');
179
if(pos != string::npos)
181
string parent = abs.substr(0, pos);
182
_modules.remove(parent);
372
371
"-IDIR Put DIR in the include file search path.\n"
373
372
"-E Print preprocessor output on stdout.\n"
374
373
"--output-dir DIR Create files in the directory DIR.\n"
374
"--depend Generate Makefile dependencies.\n"
375
375
"-d, --debug Print debug messages.\n"
376
"--ice Permit `Ice' prefix (for building Ice source code only)\n"
376
"--ice Permit `Ice' prefix (for building Ice source code only).\n"
377
"--underscore Permit underscores in Slice identifiers.\n"
377
378
"--all Generate code for Slice definitions in included files.\n"
378
"--no-package Do not create Python packages.\n"
379
379
"--checksum Generate checksums for Slice definitions.\n"
380
380
"--prefix PREFIX Prepend filenames of Python modules with PREFIX.\n"
382
// Note: --case-sensitive is intentionally not shown here!
386
main(int argc, char* argv[])
385
compile(int argc, char* argv[])
388
387
IceUtilInternal::Options opts;
389
388
opts.addOpt("h", "help");
393
392
opts.addOpt("I", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat);
394
393
opts.addOpt("E");
395
394
opts.addOpt("", "output-dir", IceUtilInternal::Options::NeedArg);
395
opts.addOpt("", "depend");
396
396
opts.addOpt("d", "debug");
397
397
opts.addOpt("", "ice");
398
opts.addOpt("", "underscore");
398
399
opts.addOpt("", "all");
399
400
opts.addOpt("", "no-package");
400
401
opts.addOpt("", "checksum");
401
402
opts.addOpt("", "prefix", IceUtilInternal::Options::NeedArg);
402
opts.addOpt("", "case-sensitive");
404
404
vector<string> args;
407
#if defined(__BCPLUSPLUS__) && (__BCPLUSPLUS__ >= 0x0600)
408
IceUtil::DummyBCC dummy;
410
407
args = opts.parse(argc, (const char**)argv);
412
409
catch(const IceUtilInternal::BadOptException& e)
414
cerr << argv[0] << ": error: " << e.reason << endl;
411
getErrorStream() << argv[0] << ": error: " << e.reason << endl;
416
413
return EXIT_FAILURE;
478
477
IceUtil::CtrlCHandler ctrlCHandler;
479
478
ctrlCHandler.setCallback(interruptedCallback);
480
bool keepComments = true;
482
482
for(i = args.begin(); i != args.end(); ++i)
484
Preprocessor icecpp(argv[0], *i, cppArgs);
485
FILE* cppHandle = icecpp.preprocess(false);
485
// Ignore duplicates.
487
vector<string>::iterator p = find(args.begin(), args.end(), *i);
495
while(fgets(buf, static_cast<int>(sizeof(buf)), cppHandle) != NULL)
497
if(fputs(buf, stdout) == EOF)
495
PreprocessorPtr icecpp = Preprocessor::create(argv[0], *i, cppArgs);
496
FILE* cppHandle = icecpp->preprocess(false);
504
500
return EXIT_FAILURE;
509
UnitPtr u = Unit::createUnit(false, all, ice, caseSensitive);
503
UnitPtr u = Unit::createUnit(false, false, ice, underscore);
510
504
int parseStatus = u->parse(*i, cppHandle, debug);
518
507
if(parseStatus == EXIT_FAILURE)
520
status = EXIT_FAILURE;
512
if(!icecpp->printMakefileDependencies(Preprocessor::Python, includePaths, "", prefix))
524
PreprocessorPtr icecpp = Preprocessor::create(argv[0], *i, cppArgs);
525
FILE* cppHandle = icecpp->preprocess(keepComments);
535
while(fgets(buf, static_cast<int>(sizeof(buf)), cppHandle) != NULL)
537
if(fputs(buf, stdout) == EOF)
524
string base = icecpp.getBaseName();
525
string::size_type pos = base.find_last_of("/\\");
526
if(pos != string::npos)
528
base.erase(0, pos + 1);
532
// Append the suffix "_ice" to the filename in order to avoid any conflicts
533
// with Slice module names. For example, if the file Test.ice defines a
534
// Slice module named "Test", then we couldn't create a Python package named
535
// "Test" and also call the generated file "Test.py".
537
string file = prefix + base + "_ice.py";
540
file = output + '/' + file;
545
IceUtilInternal::Output out;
546
out.open(file.c_str());
550
os << "cannot open`" << file << "': " << strerror(errno);
551
throw FileException(__FILE__, __LINE__, os.str());
553
FileTracker::instance()->addFile(file);
556
out << "\n# Generated from file `" << base << ".ice'\n";
559
// Generate the Python mapping.
561
generate(u, all, checksum, includePaths, out);
566
// Create or update the Python package hierarchy.
570
PackageVisitor visitor(prefix + base + "_ice", output);
571
u->visit(&visitor, false);
574
catch(const Slice::FileException& ex)
576
// If a file could not be created, then cleanup any
578
FileTracker::instance()->cleanup();
549
UnitPtr u = Unit::createUnit(false, all, ice, underscore);
550
int parseStatus = u->parse(*i, cppHandle, debug);
580
getErrorStream() << argv[0] << ": error: " << ex.reason() << endl;
581
555
return EXIT_FAILURE;
583
catch(const string& err)
558
if(parseStatus == EXIT_FAILURE)
585
FileTracker::instance()->cleanup();
586
getErrorStream() << argv[0] << ": error: " << err << endl;
587
560
status = EXIT_FAILURE;
564
string base = icecpp->getBaseName();
565
string::size_type pos = base.find_last_of("/\\");
566
if(pos != string::npos)
568
base.erase(0, pos + 1);
572
// Append the suffix "_ice" to the filename in order to avoid any conflicts
573
// with Slice module names. For example, if the file Test.ice defines a
574
// Slice module named "Test", then we couldn't create a Python package named
575
// "Test" and also call the generated file "Test.py".
577
string file = prefix + base + "_ice.py";
580
file = output + '/' + file;
585
IceUtilInternal::Output out;
586
out.open(file.c_str());
590
os << "cannot open`" << file << "': " << strerror(errno);
591
throw FileException(__FILE__, __LINE__, os.str());
593
FileTracker::instance()->addFile(file);
596
printGeneratedHeader(out, base + ".ice", "#");
598
// Generate the Python mapping.
600
generate(u, all, checksum, includePaths, out);
605
// Create or update the Python package hierarchy.
609
PackageVisitor::createModules(u, prefix + base + "_ice", output);
612
catch(const Slice::FileException& ex)
614
// If a file could not be created, then cleanup any
616
FileTracker::instance()->cleanup();
618
getErrorStream() << argv[0] << ": error: " << ex.reason() << endl;
621
catch(const string& err)
623
FileTracker::instance()->cleanup();
624
getErrorStream() << argv[0] << ": error: " << err << endl;
625
status = EXIT_FAILURE;
595
IceUtil::StaticMutex::Lock lock(_mutex);
634
IceUtilInternal::MutexPtrLock<IceUtil::Mutex> sync(mutex);
599
638
FileTracker::instance()->cleanup();
600
639
return EXIT_FAILURE;