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 <fstream.h>
00038 #include <string.h>
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 #define STRICT
00049 #define WIN32_LEAN_AND_MEAN
00050 #define NOSERVICE
00051 #include <windows.h>
00052
00053 #include <stdlib.h>
00054 #include <process.h>
00055 #include <fcntl.h>
00056 #include <io.h>
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 #define PREPROCESSOR_EXT ".i" // cl generates .i files when preprocessing
00072 #define TRANSLATOR_EXT ".occ"
00073
00074 const char* compilerName = "cl";
00075 const char* opencxxErrorMessage = " Error(s). OpenC++ stops.\n";
00076
00077
00078
00079 extern bool showProgram;
00080 extern bool doCompile;
00081 extern bool makeExecutable;
00082 extern bool doPreprocess;
00083 extern bool doTranslate;
00084 extern bool verboseMode;
00085 extern bool regularCpp;
00086 extern bool makeSharedLibrary;
00087
00088 extern const char* cppArgv[];
00089 extern const char* ccArgv[];
00090
00091 const NLIBS = 32;
00092 static int libsArgc = 0;
00093 const char* libsArgv[NLIBS];
00094
00095 const NLINKERARGS = 32;
00096 static int linkerArgc = 0;
00097 static bool linkerFlag = FALSE;
00098 char* linkerArgv[NLINKERARGS];
00099
00100 extern void ParseCmdOptions(int from, int argc, char** argv, char*& source);
00101 extern void AddCppOption(const char* arg);
00102 extern void AddCcOption(const char* arg);
00103 extern void CloseCcOptions();
00104 extern bool IsCxxSource(char* fname);
00105 extern void ShowCommandLine(const char* cmd, const char** args);
00106
00107 void RunLinker();
00108 char* RunPreprocessor(const char* src);
00109 char* OpenCxxOutputFileName(const char* src);
00110 void RunCompiler(const char* src, const char* occsrc);
00111 void RunSoCompiler(const char* src_file);
00112 void BaseClassUsed(char *name, int len);
00113 void* LoadSoLib(char* file_name);
00114 void* LookupSymbol(void* handle, char* symbol);
00115 bool ParseTargetSpecificOptions(char* arg, char*& source_file);
00116
00117 static int Launch(const char *tool, const char *const *argv);
00118 static char* MakeTempFilename(const char* src, const char* suffix);
00119 static void ParseFileOptions(const char* filename, char*& source_file);
00120 static void File2Args(const char *fname, int max, int &argc, char *argv[]);
00121 static void String2Args(const char *str, int max, int &argc, char *argv[]);
00122 static char *NewArg(const char *from, size_t size, int argc, int max);
00123 static void ParseBackslash(char arg[], size_t &i, const char* &string);
00124 static void ParseDoubleQuote(char arg[], size_t &i, const char* &string);
00125
00126
00127 void RunLinker()
00128 {
00129 cerr << "OpenC++: no source file.\n";
00130 }
00131
00132 char *RunPreprocessor(const char *file_in)
00133 {
00134 AddCppOption("-nologo");
00135 if(!regularCpp)
00136 AddCppOption("-D__opencxx");
00137
00138 AddCppOption("-E");
00139 AddCppOption("-P");
00140 AddCppOption("-Tp");
00141
00142 AddCppOption(file_in);
00143 AddCppOption((char*)0);
00144
00145 if(verboseMode) {
00146 cerr << "[Preprocess... ";
00147 ShowCommandLine(compilerName, cppArgv);
00148 cerr << "]\n";
00149 }
00150
00151 int status = Launch(compilerName, cppArgv);
00152 if(status != 0) {
00153 if(status == -1)
00154 perror("cannot invoke the preprocessor");
00155
00156
00157
00158 if (status != 2)
00159 exit(status);
00160 }
00161
00162 return MakeTempFilename(file_in, PREPROCESSOR_EXT);
00163 }
00164
00165 char* OpenCxxOutputFileName(const char* src)
00166 {
00167 return MakeTempFilename(src, TRANSLATOR_EXT);
00168 }
00169
00170 void BaseClassUsed(char *name, int len)
00171 {
00172 static char tail[] = ".lib";
00173 char *lib_name = new char[len + sizeof(tail)];
00174 memcpy(lib_name, name, len);
00175 strcpy(lib_name + len, tail);
00176 libsArgv[libsArgc++] = lib_name;
00177 }
00178
00179 void RunCompiler(const char* org_src, const char *file_in)
00180 {
00181 AddCcOption("-nologo");
00182 if(!makeExecutable)
00183 AddCcOption("-c");
00184
00185 AddCcOption("-Tp");
00186 AddCcOption(file_in);
00187 if (makeExecutable && makeSharedLibrary) {
00188
00189 for (int i = 0; i < libsArgc; ++i)
00190 AddCcOption(libsArgv[i]);
00191 AddCcOption("-link");
00192 AddCcOption("-dll");
00193 char buffer[256];
00194 strcpy(buffer, "-out:");
00195 strcat(buffer, org_src);
00196 char *last_dot = strrchr(buffer, '.');
00197 if (last_dot != 0) *last_dot = '\0';
00198 strcat(buffer, ".dll");
00199 for (int j = 0; j < linkerArgc; ++j)
00200 AddCcOption(linkerArgv[j]);
00201
00202 AddCcOption(buffer);
00203
00204 if(linkerArgc == 0){
00205 AddCcOption("occ.lib");
00206 AddCcOption("gc.lib");
00207 }
00208 else
00209 for(int j = 0; j < linkerArgc; ++j)
00210 AddCcOption(linkerArgv[j]);
00211 }
00212
00213 CloseCcOptions();
00214
00215 if(verboseMode){
00216 cerr << "[Compile... ";
00217 ShowCommandLine(compilerName, ccArgv);
00218 cerr << "]\n";
00219 }
00220
00221 int status = Launch(compilerName, ccArgv);
00222 if(status != 0){
00223 if(status == -1)
00224 perror("cannot invoke a compiler");
00225
00226 exit(status);
00227 }
00228 }
00229
00230 void RunSoCompiler(const char* src_file)
00231 {
00232
00233 }
00234
00235 void* LoadSoLib(char* file_name)
00236 {
00237
00238 HINSTANCE handle = LoadLibrary(file_name);
00239 if (handle == NULL) {
00240 cerr << "LoadLibrary() failed: " << GetLastError() << '\n';
00241 exit(1);
00242 }
00243 return (void *) handle;
00244 }
00245
00246 void* LookupSymbol(void* handle, char* symbol)
00247 {
00248 return (void *) GetProcAddress((HMODULE) handle, symbol);
00249 }
00250
00251
00252 static int Launch(const char *tool, const char *const *argv)
00253 {
00254 return _spawnvp(_P_WAIT, tool, argv);
00255 }
00256
00257 static char* MakeTempFilename(const char* src, const char* suffix)
00258 {
00259 char drive[_MAX_DRIVE];
00260 char dir[_MAX_DIR];
00261 char fname[_MAX_FNAME];
00262 char ext[_MAX_EXT];
00263
00264 _splitpath(src, drive, dir, fname, ext);
00265 char* tmpfile = new char[_MAX_PATH];
00266 _makepath(tmpfile, drive, dir, fname, suffix);
00267 return tmpfile;
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 bool ParseTargetSpecificOptions(char* arg, char*& source_file)
00282 {
00283 if(*arg == '@'){
00284
00285 ParseFileOptions(arg + 1, source_file);
00286 return TRUE;
00287 }
00288 else if(strcmp("link",arg+1)==0){
00289 linkerFlag = TRUE;
00290 return TRUE;
00291 }
00292 else if(linkerFlag && linkerArgc < NLINKERARGS && IsCxxSource(arg)==FALSE)
00293 {
00294 linkerArgv[linkerArgc] = new char[strlen(arg)+1];
00295 strcpy(linkerArgv[linkerArgc++], arg);
00296 return TRUE;
00297 }
00298 else
00299 return FALSE;
00300 }
00301
00302 static void ParseFileOptions(const char* filename, char*& source_file)
00303 {
00304 const max = 32;
00305 int argc;
00306 char *argv[max];
00307
00308 File2Args(filename, max, argc, argv);
00309 ParseCmdOptions(0, argc, argv, source_file);
00310 }
00311
00312 static void File2Args(const char *filename, int max, int &argc, char *argv[])
00313
00314 {
00315 int handle = open(filename, _O_RDONLY);
00316 if(handle == -1 ){
00317 perror(filename);
00318 exit(1);
00319 }
00320
00321 long size = filelength(handle);
00322 if(size == -1 ){
00323 perror(filename);
00324 exit(1);
00325 }
00326
00327 char *buffer = new char[size+1];
00328 if(buffer == NULL){
00329 cerr << "out of memory\n";
00330 exit(1);
00331 }
00332
00333 size = read(handle, buffer, (int)size);
00334 buffer[size] = '\0';
00335
00336 String2Args(buffer, max, argc, argv);
00337 delete [] buffer;
00338 }
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 #define is_blank(c) ((c) == ' ' || (c) == '\t' || (c) == '\f' || (c) == '\r' || (c) == '\n')
00373
00374
00375 static void String2Args(const char *string, int max, int &argc, char *argv[])
00376 {
00377 argc = 0;
00378 if(string == NULL)
00379 return;
00380
00381 const sizemax = 255;
00382 char arg[sizemax];
00383
00384 while(is_blank(*string))
00385 string++;
00386
00387 size_t i = 0;
00388 while(1){
00389 if(*string == '"')
00390 ParseDoubleQuote(arg, i, string);
00391 else if(*string == '\\')
00392 ParseBackslash(arg, i, string);
00393 else if(is_blank(*string) || *string == '\0'){
00394 argv[argc++] = NewArg(arg, i, argc, max);
00395 i = 0;
00396 while(is_blank(*string))
00397 string++;
00398 if(*string == '\0')
00399 break;
00400 }
00401 else{
00402 if(i == sizemax){
00403 cerr << "argument too long\n";
00404 exit(1);
00405 }
00406
00407 arg[i++] = *string++;
00408 }
00409 }
00410
00411 argv[argc] = NewArg(NULL, 0, argc, max);
00412 }
00413
00414 static char *NewArg(const char *from, size_t size, int argc, int max)
00415 {
00416 if (argc == max) {
00417 cerr << "too many arguments\n";
00418 exit(1);
00419 }
00420
00421 if (from == NULL) return NULL;
00422
00423 char *arg = new char[size+1];
00424 if (arg == NULL) {
00425 cerr << "out of memory\n";
00426 exit(1);
00427 }
00428 strncpy(arg, from, size);
00429 *(arg + size) = '\0';
00430
00431 return arg;
00432 }
00433
00434 static void ParseBackslash(char arg[], size_t &i, const char* &string)
00435 {
00436 string++;
00437 int count = 1;
00438 while(*string == '\\'){
00439 string++;
00440 count++;
00441 }
00442
00443 if(*string == '"'){
00444 if(count % 2 == 0){
00445 count = count / 2;
00446 while(count-- != 0)
00447 arg[i++] = '\\';
00448 }
00449 else{
00450 count = count / 2;
00451 while(count-- != 0)
00452 arg[i++] = '\\';
00453
00454 arg[i++] = *string++;
00455 }
00456 }
00457 else
00458 while(count-- != 0)
00459 arg[i++] = '\\';
00460 }
00461
00462 static void ParseDoubleQuote(char arg[], size_t &i, const char* &string)
00463 {
00464 string++;
00465 while(*string != '\0'){
00466 if(*string == '\\')
00467 ParseBackslash(arg, i, string);
00468 else if(*string == '"'){
00469 string++;
00470 return;
00471 }
00472 else
00473 arg[i++] = *string++;
00474 }
00475
00476 cerr << "missing double quote\n";
00477 exit(1);
00478 }