Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

driver2.cpp

Go to the documentation of this file.
00001 /*
00002   Copyright (C) 1997-2001 Shigeru Chiba, Tokyo Institute of Technology.
00003 
00004   Permission to use, copy, distribute and modify this software and   
00005   its documentation for any purpose is hereby granted without fee,        
00006   provided that the above copyright notice appear in all copies and that 
00007   both that copyright notice and this permission notice appear in 
00008   supporting documentation.
00009 
00010   Shigeru Chiba makes no representations about the suitability of this 
00011   software for any purpose.  It is provided "as is" without express or
00012   implied warranty.
00013 */
00014 
00015 /*
00016   Copyright (c) 1995, 1996 Xerox Corporation.
00017   All Rights Reserved.
00018 
00019   Use and copying of this software and preparation of derivative works
00020   based upon this software are permitted. Any copy of this software or
00021   of any derivative work must include the above copyright notice of
00022   Xerox Corporation, this paragraph and the one after it.  Any
00023   distribution of this software or derivative works must comply with all
00024   applicable United States export control laws.
00025 
00026   This software is made available AS IS, and XEROX CORPORATION DISCLAIMS
00027   ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE
00028   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029   PURPOSE, AND NOTWITHSTANDING ANY OTHER PROVISION CONTAINED HEREIN, ANY
00030   LIABILITY FOR DAMAGES RESULTING FROM THE SOFTWARE OR ITS USE IS
00031   EXPRESSLY DISCLAIMED, WHETHER ARISING IN CONTRACT, TORT (INCLUDING
00032   NEGLIGENCE) OR STRICT LIABILITY, EVEN IF XEROX CORPORATION IS ADVISED
00033   OF THE POSSIBILITY OF SUCH DAMAGES.
00034 */
00035 
00036 #include <stdio.h>
00037 #include <fstream.h>
00038 #include <string.h>
00039 
00040 /*** driver2.cpp is a Win32 version of driver2.cc ***/
00041 
00042 // No possibility to include types.h, because of type clash
00043 // at BOOL between types.h and windows.h
00044 // So, windows.h is included always (it is needed for dynamic
00045 // loading support) and it is assumed that USE_DLOADER is always
00046 // on for Microsoft Visual C++
00047 
00048 #define STRICT
00049 #define WIN32_LEAN_AND_MEAN
00050 #define NOSERVICE
00051 #include <windows.h>
00052 
00053 #include <stdlib.h>     // For exit
00054 #include <process.h>    // For _spawn
00055 #include <fcntl.h>      // For _O_RDONLY
00056 #include <io.h>         // For open, lseek, read
00057 
00058 /*
00059   Be carefull !!! I have changed the meaning of the extensions!!!!!!
00060   In the original openc++ :
00061 
00062   ".cpp" file --(preprocessor)--> ".occ" file --(translator)--> ".i" file
00063   --(compiler)--> ".o" file
00064 
00065  In this version :
00066 
00067   ".cpp" file --(preprocessor)--> ".i" file --(translator)--> ".occ" file
00068   --(compiler)--> ".o" file
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 // defined in driver.cc
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"); // Use -EP if you don't want the directives #line
00139     AddCppOption("-P"); // Preprocessor output to <file>.i
00140     AddCppOption("-Tp"); // Consider source file as C++ file,
00141                          // whatever extension.
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         // VIC Feb 20 1998
00157         // MSVC 5.0 returns non-zero exit code on normal input
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         // Add superclass libraries
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         // Add linked libraries
00204         if(linkerArgc == 0){
00205             AddCcOption("occ.lib");     // default
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     // not implemented
00233 }
00234 
00235 void* LoadSoLib(char* file_name)
00236 {
00237     // NYI - error handling
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   Arguments parsing (low-level stuff)
00272  The goal of this section is to split a string into an argv[] array
00273  This is necessary for two reasons:
00274         - To be able to parse an options file (a text file containg
00275           options, allowing to overcome the MS-DOS limitation to 128
00276           characters for the command line (under win31)
00277         - To be able to convert the LPSTR cmdLine argument of the WinMain
00278           function (for future developments I have planned to do)
00279 */
00280 
00281 bool ParseTargetSpecificOptions(char* arg, char*& source_file)
00282 {
00283     if(*arg == '@'){
00284         // +1 to skip '@' : the following characters are the filename
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 //                                IN            IN        OUT         OUT
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   Parsing Command-Line Arguments
00342 
00343   Microsoft C startup code uses the following rules when parsing arguments
00344   given on the MS-DOS command line:
00345 
00346   Arguments are delimited by white space, which is either a space or a
00347   tab.  A string surrounded by double quotation marks is interpreted as
00348   a single argument, regardless of white space contained within. A
00349   quoted string can be embedded in an argument.. Note that the caret (^)
00350   is not recognized as an escape character or delimiter. A double
00351   quotation mark preceded by a backslash, \", is interpreted as a
00352   literal double quotation mark (").  Backslashes are interpreted
00353   literally, unless they immediately precede a double quotation mark.
00354   If an even number of backslashes is followed by a double quotation
00355   mark, one \ is placed in the argv array for every \\ pair, and the "
00356   is interpreted as a string delimiter.  If an odd number of backslashes
00357   is followed by a double quotation mark, one is placed in the argv
00358   array for every \ pair, and the " is escaped by the \ remaining,
00359   causing a literal " to be placed in argv.
00360 
00361   The following list shows the interpreted result passed to argv for
00362   several examples of command-line arguments.
00363 
00364   Command-Line Input    argv[1] argv[2] argv[3]
00365   "a b c" d e           a b c   d       e
00366   "ab\"c" "\\" d        ab"c    \       d
00367   a\\\b d"e f"g h       a\\\b   de fg   h
00368   a\\\"b c d            a\"b    c       d
00369   a\\\\"b c" d e        a\\b c  d       e
00370 */
00371 
00372 #define is_blank(c)     ((c) == ' ' || (c) == '\t' || (c) == '\f' || (c) == '\r' || (c) == '\n')
00373 
00374 /*                           IN          IN        OUT         OUT    */
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 }

Generated on Mon Feb 10 17:32:46 2003 for VFiasco Semantics Compiler by doxygen1.2.15