00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 #include <iostream.h>
00039 #include <string.h>
00040 #include "token.h"
00041 #include "buffer.h"
00042 #include "parse.h"
00043 #include "walker.h"
00044 #include "classwalk.h"
00045 #include "ptree-core.h"
00046 #include "mop.h"
00047
00048 #if defined(_MSC_VER)
00049 #include <stdlib.h>
00050 #else
00051 #include <unistd.h>
00052 #endif
00053
00054 static char thisVersion[] = "2.5.12";
00055
00056 static char copyingNote[]
00057 = "Copyright (c) 1997-2001 Shigeru Chiba. All Rights Reserved.\n"
00058 "Copyright (c) 1995, 1996 Xerox Corporation. All Rights Reserved.";
00059
00060 const char opencxxErrorMessage[] = " Error(s). OpenC++ stops.\n";
00061
00062 extern const char* compilerName;
00063
00064 bool showProgram;
00065 bool doCompile;
00066 bool makeExecutable;
00067 bool doPreprocess;
00068 bool doTranslate;
00069 bool verboseMode;
00070 bool regularCpp;
00071 bool makeSharedLibrary;
00072 char* sharedLibraryName;
00073 bool preprocessTwice;
00074
00075 const int NARGS = 64;
00076 const char* cppArgv[NARGS];
00077 const char* ccArgv[NARGS];
00078 static const char* cc2Argv[NARGS];
00079 int cppArgc = 0;
00080 int ccArgc = 0;
00081 static int cc2Argc = 0;
00082 static int numOfObjectFiles = 0;
00083
00084
00085 extern bool ParseTargetSpecificOptions(char* arg, char*& source_file);
00086 extern void RunLinker();
00087 extern char* RunPreprocessor(const char* src);
00088 extern char* OpenCxxOutputFileName(const char* src);
00089 extern void RunCompiler(const char* src, const char* occserc);
00090
00091
00092 extern void LoadMetaclass(char*);
00093
00094 void Compile(int argc, char** argv);
00095 void ParseCmdOptions(int from, int argc, char** argv, char*& source_file);
00096 void AddCppOption(const char* arg);
00097 void AddCcOption(const char* arg);
00098 void CloseCcOptions();
00099 bool IsCxxSource(char* fname);
00100 void ShowCommandLine(const char* cmd, const char** args);
00101
00102 static void ReadStdin();
00103 static void ReadFile(const char* src);
00104 static char* RunOpencxx(const char* src);
00105 static int ParseOpencxx(Program* parse);
00106 static char* ParseOptions(int argc, char** argv);
00107 static void ShowVersion();
00108 static void ShowHelp(char**);
00109 static void AddCc2Option(const char* arg);
00110 static void RecordCmdOption(char* option);
00111 static void ParseCcOptions(char* arg, char*& source_file);
00112
00113
00114 void Compile(int argc, char** argv)
00115 {
00116 char* src = ParseOptions(argc, argv);
00117 if(src != nil)
00118 ReadFile(src);
00119 else
00120 if(numOfObjectFiles == 0)
00121 ReadStdin();
00122 else
00123 RunLinker();
00124 }
00125
00126 static void ReadStdin()
00127 {
00128 cerr << "OpenC++: No source file. Read from console.\n";
00129
00130 ProgramFromStdin prog;
00131 int nerrors = ParseOpencxx(&prog);
00132
00133 if(!showProgram)
00134 if(nerrors == 0)
00135 prog.Write(cout, "stdout");
00136 else{
00137 cerr << nerrors << opencxxErrorMessage;
00138 exit(1);
00139 }
00140 }
00141
00142 static void ReadFile(const char* src)
00143 {
00144 char *occfile;
00145
00146 if(doPreprocess){
00147 char* cppfile = RunPreprocessor(src);
00148 occfile = RunOpencxx(cppfile);
00149 unlink(cppfile);
00150 delete cppfile;
00151 }
00152 else
00153 occfile = RunOpencxx(src);
00154
00155 if(doCompile){
00156 RunCompiler(src, occfile);
00157
00158 }
00159
00160 delete occfile;
00161 }
00162
00163 static char* RunOpencxx(const char* src)
00164 {
00165 char* dest = OpenCxxOutputFileName(src);
00166
00167 ifstream src_stream(src);
00168 if(!src_stream){
00169 perror(src);
00170 exit(1);
00171 }
00172
00173 ProgramFile src_prog(src_stream);
00174 if(verboseMode){
00175 if(doTranslate)
00176 cerr << "[Translate... " << src
00177 << " into: " << dest << "]\n";
00178 else
00179 cerr << "[Parse... " << src << "]\n";
00180 }
00181
00182 int nerrors = ParseOpencxx(&src_prog);
00183
00184 if(nerrors != 0){
00185 cerr << nerrors << opencxxErrorMessage;
00186 exit(1);
00187 }
00188
00189 if(doTranslate){
00190 ofstream dest_stream(dest, (ios::out | ios::trunc));
00191 if(!dest_stream){
00192 perror(dest);
00193 exit(1);
00194 }
00195
00196 src_prog.Write(dest_stream, dest);
00197 }
00198
00199 src_stream.close();
00200 return dest;
00201 }
00202
00203 static int ParseOpencxx(Program* prog)
00204 {
00205 Lex lex(prog);
00206 Parser parse(&lex);
00207 ClassWalker w(&parse);
00208 Ptree* def;
00209
00210 while(parse.rProgram(def)){
00211 if(showProgram)
00212 def->Display2(cout);
00213
00214 if(doTranslate){
00215 Ptree* def2 = w.Translate(def);
00216 Ptree* before = w.GetInsertedPtree();
00217 Ptree* after = w.GetAppendedPtree();
00218
00219 prog->Insert(def, before, after);
00220 if(def != def2)
00221 prog->MinimumSubst(def2, def);
00222 }
00223 }
00224
00225 return parse.NumOfErrors();
00226 }
00227
00228 static char* ParseOptions(int argc, char** argv)
00229 {
00230 char* source_file = nil;
00231 showProgram = FALSE;
00232 doCompile = TRUE;
00233 verboseMode = FALSE;
00234 makeExecutable = TRUE;
00235 doPreprocess = TRUE;
00236 doTranslate = TRUE;
00237 regularCpp = FALSE;
00238 makeSharedLibrary = FALSE;
00239 sharedLibraryName = nil;
00240 preprocessTwice = FALSE;
00241
00242 AddCppOption(compilerName);
00243 AddCcOption(compilerName);
00244
00245 ParseCmdOptions(1, argc, argv, source_file);
00246
00247 return source_file;
00248 }
00249
00250 void ParseCmdOptions(int from, int argc, char** argv, char*& source_file)
00251 {
00252 int i;
00253 for(i = from; i < argc; ++i)
00254 if(strcmp("--", argv[i]) == 0)
00255 break;
00256 else if(strcmp("-E", argv[i]) == 0)
00257 doCompile = FALSE;
00258 else if(strcmp("-g", argv[i]) == 0)
00259 AddCcOption(argv[i]);
00260 else if (strcmp("-n", argv[i]) == 0)
00261 doPreprocess = FALSE;
00262 else if(*argv[i] == '-' && argv[i][1] == 'm'){
00263 makeSharedLibrary = TRUE;
00264 sharedLibraryName = &argv[i][2];
00265 }
00266 else if (strcmp("-P", argv[i]) == 0)
00267 preprocessTwice = TRUE;
00268 else if (strcmp("-p", argv[i]) == 0)
00269 doTranslate = FALSE;
00270 else if (strcmp("-C", argv[i]) == 0) {
00271 AddCppOption("-C");
00272 preprocessTwice = TRUE;
00273 }
00274 else if(strcmp("-c", argv[i]) == 0)
00275 makeExecutable = FALSE;
00276 else if(strcmp("-l", argv[i]) == 0){
00277 cout << "[Loaded metaclasses...]\n";
00278 opcxx_ListOfMetaclass::PrintAllMetaclasses();
00279 exit(0);
00280 }
00281 else if(*argv[i] == '-' && argv[i][1] == 'S')
00282 LoadMetaclass(&argv[i][2]);
00283 else if(strcmp("-s", argv[i]) == 0)
00284 showProgram = TRUE;
00285 else if(strcmp("-v", argv[i]) == 0)
00286 verboseMode = TRUE;
00287 else if(strcmp("-V", argv[i]) == 0){
00288 ShowVersion();
00289 exit(1);
00290 }
00291 else if (strcmp("--regular-c++", argv[i]) == 0)
00292 regularCpp = TRUE;
00293 else if(*argv[i] == '-'
00294 && (argv[i][1] == 'D' || argv[i][1] == 'I'))
00295 AddCppOption(argv[i]);
00296 else if(*argv[i] == '-' && argv[i][1] == 'd' && argv[i][2] != '\0')
00297 AddCppOption(&argv[i][2]);
00298 else if(*argv[i] == '-' && argv[i][1] == 'M')
00299 RecordCmdOption(&argv[i][2]);
00300 else if(*argv[i] == '-'){
00301 ShowVersion();
00302 ShowHelp(argv);
00303 exit(1);
00304 }
00305 else if(!ParseTargetSpecificOptions(argv[i], source_file))
00306 ParseCcOptions(argv[i], source_file);
00307
00308 while(++i < argc)
00309 if(!ParseTargetSpecificOptions(argv[i], source_file))
00310 ParseCcOptions(argv[i], source_file);
00311
00312 if(!doTranslate)
00313 doCompile = FALSE;
00314 }
00315
00316 static void ShowVersion()
00317 {
00318 cerr << "OpenC++ version " << thisVersion << "\n" << copyingNote << "\n";
00319 }
00320
00321 static void ShowHelp(char** argv)
00322 {
00323 cerr << "Usage: "
00324 << argv[0]
00325 << " [-l][-s][-V][-v][-E][-m[<file name>]][-c][-n][-p][--regular-c++]\n"
00326 << "\t\t[-I<directory>][-D<macro>[=<def>]][-M<option>[=<value>]]\n"
00327 << "\t\t[-g][-d<option>][-S<metaclass>]\n"
00328 << "\t\t[-- <compiler options>] <source file>\n"
00329 << "\n"
00330 << " -g Produce debugging information\n"
00331 << " -M Specify an <option> with <value> passed to metaobjects\n"
00332 << " -l List metaclasses\n"
00333 << " -S Load a metaclass\n"
00334 << " -s Show program tree on stdout\n"
00335 << " -V Show version\n"
00336 << " -v Verbose mode\n"
00337 << "\n"
00338 << " Building stages options\n"
00339 << " -n Don't preprocess\n"
00340 << " -p Don't translate (stop after parsing)\n"
00341 << " -E Don't compile (stop after translation)\n"
00342 << " -c Don't make executable (stop after compilation)\n"
00343 #if !defined(IRIX_CC) && !defined (_MSC_VER)
00344 << " -P Preprocess again after translation\n"
00345 #endif
00346 << " -m Compile a metaclass (make a shared library)\n"
00347 << "\n"
00348 << " Preprocessor options\n"
00349 << " -I<directory> Add <directory> to the #include path\n"
00350 << " -D<name>=<def> Define a macro <name> as <def>\n"
00351 << " -d<option> Specify a preprocessor option\n"
00352 #if !defined(IRIX_CC) && !defined (_MSC_VER)
00353 << " -C Don't discard comments\n"
00354 #endif
00355 << "\n"
00356 << " Other options\n"
00357 << " --regular-c++ Inhibit the extended syntax\n";
00358 }
00359
00360 void AddCppOption(const char* arg)
00361 {
00362 if(cppArgc < NARGS)
00363 cppArgv[cppArgc++] = arg;
00364 else{
00365 cerr << "OpenC++: too many arguments\n";
00366 exit(1);
00367 }
00368 }
00369
00370 void AddCcOption(const char* arg)
00371 {
00372 if(ccArgc < NARGS)
00373 ccArgv[ccArgc++] = arg;
00374 else{
00375 cerr << "OpenC++: too many arguments\n";
00376 exit(1);
00377 }
00378 }
00379
00380 void CloseCcOptions()
00381 {
00382 for(int i = 0; i < cc2Argc; ++i)
00383 AddCcOption(cc2Argv[i]);
00384
00385 AddCcOption((char*)0);
00386 }
00387
00388 static void AddCc2Option(const char* arg)
00389 {
00390 if(cc2Argc < NARGS)
00391 cc2Argv[cc2Argc++] = arg;
00392 else{
00393 cerr << "OpenC++: too many arguments\n";
00394 exit(1);
00395 }
00396 }
00397
00398 static void RecordCmdOption(char* option)
00399 {
00400 if(option == nil || *option == '\0')
00401 return;
00402
00403 char* value = strchr(option, '=');
00404 if(value != nil)
00405 *value++ = '\0';
00406
00407 if(!Class::RecordCmdLineOption(option, value)){
00408 cerr << "OpenC++: Too many -M options.\n";
00409 exit(1);
00410 }
00411 }
00412
00413 static void ParseCcOptions(char* arg, char*& source_file)
00414 {
00415 static char* errmsg
00416 = "OpenC++: only a single source file is accepted at a time.\n";
00417
00418 if(arg != nil && arg[0] != '-'){
00419 if(IsCxxSource(arg))
00420 if(source_file == nil){
00421 source_file = arg;
00422 return;
00423 }
00424 else{
00425 cerr << errmsg;
00426 exit(1);
00427 }
00428 }
00429
00430 ++numOfObjectFiles;
00431 if(source_file == nil)
00432 AddCcOption(arg);
00433 else
00434 AddCc2Option(arg);
00435
00436 return;
00437 }
00438
00439
00440
00441
00442
00443
00444
00445
00446 bool IsCxxSource(char* fname)
00447 {
00448 char* ext = strrchr(fname, '.');
00449 if(ext == nil)
00450 return FALSE;
00451
00452 if(strcmp(ext, ".cc") == 0
00453 || strcmp(ext, ".C") == 0
00454 || strcmp(ext, ".c") == 0
00455 || strcmp(ext, ".mc") == 0
00456 || strcmp(ext, ".cxx") == 0
00457 || strcmp(ext, ".cpp") == 0
00458 || strcmp(ext, ".ii") == 0
00459 || strcmp(ext, ".i") == 0
00460 || strcmp(ext, ".occ") == 0)
00461 return TRUE;
00462
00463 return FALSE;
00464 }
00465
00466 void ShowCommandLine(const char*, const char** args)
00467 {
00468 while(*args != nil)
00469 cerr << ' ' << *args++;
00470 }