Modules | Files | Inheritance Tree | Inheritance Graph | Name Index | Config
File: Synopsis/Parser/C++/occ/driver.cc
    1| /*
    2|   Copyright (C) 1997-2000 Shigeru Chiba, University of Tsukuba.
    3| 
    4|   Permission to use, copy, distribute and modify this software and   
    5|   its documentation for any purpose is hereby granted without fee,        
    6|   provided that the above copyright notice appear in all copies and that 
    7|   both that copyright notice and this permission notice appear in 
    8|   supporting documentation.
    9| 
   10|   Shigeru Chiba makes no representations about the suitability of this 
   11|   software for any purpose.  It is provided "as is" without express or
   12|   implied warranty.
   13| */
   14| /*
   15|   Copyright (c) 1995, 1996 Xerox Corporation.
   16|   All Rights Reserved.
   17| 
   18|   Use and copying of this software and preparation of derivative works
   19|   based upon this software are permitted. Any copy of this software or
   20|   of any derivative work must include the above copyright notice of
   21|   Xerox Corporation, this paragraph and the one after it.  Any
   22|   distribution of this software or derivative works must comply with all
   23|   applicable United States export control laws.
   24| 
   25|   This software is made available AS IS, and XEROX CORPORATION DISCLAIMS
   26|   ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE
   27|   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   28|   PURPOSE, AND NOTWITHSTANDING ANY OTHER PROVISION CONTAINED HEREIN, ANY
   29|   LIABILITY FOR DAMAGES RESULTING FROM THE SOFTWARE OR ITS USE IS
   30|   EXPRESSLY DISCLAIMED, WHETHER ARISING IN CONTRACT, TORT (INCLUDING
   31|   NEGLIGENCE) OR STRICT LIABILITY, EVEN IF XEROX CORPORATION IS ADVISED
   32|   OF THE POSSIBILITY OF SUCH DAMAGES.
   33| */
   34| 
   35| #include <stdio.h>
   36| #include <iostream>
   37| #include <string.h>
   38| #include "token.h"
   39| #include "buffer.h"
   40| #include "parse.h"
   41| #include "walker.h"
   42| #include "classwalk.h"
   43| #include "ptree-core.h"
   44| #include "mop.h"
   45| 
   46| #if defined(_MSC_VER)
   47| #include <stdlib.h>
   48| #else
   49| #include <unistd.h>
   50| #endif
   51| 
   52| static char thisVersion[] = "2.5.10";
   53| 
   54| static char copyingNote[]
   55|         = "Copyright (c) 1997-2000 Shigeru Chiba.  All Rights Reserved.\n"
   56|           "Copyright (c) 1995, 1996 Xerox Corporation. All Rights Reserved.";
   57| 
   58| const char opencxxErrorMessage[] = " Error(s).  OpenC++ stops.\n";
   59| 
   60| extern const charcompilerName;
   61| 
   62| bool showProgram;
   63| bool doCompile;
   64| bool makeExecutable;
   65| bool doPreprocess;
   66| bool doTranslate;
   67| bool verboseMode;
   68| bool regularCpp;
   69| bool makeSharedLibrary;
   70| charsharedLibraryName;
   71| bool preprocessTwice;
   72| 
   73| const int NARGS = 64;
   74| const charcppArgv[NARGS];
   75| const charccArgv[NARGS];
   76| static const charcc2Argv[NARGS];      // arguments following a source file
   77| int cppArgc = 0;
   78| int ccArgc = 0;
   79| static int cc2Argc = 0;
   80| static int numOfObjectFiles = 0;
   81| 
   82| // defined in driver2.cc
   83| extern bool ParseTargetSpecificOptions(char* arg, char*& source_file);
   84| extern void RunLinker();
   85| extern charRunPreprocessor(const char* src);
   86| extern charOpenCxxOutputFileName(const char* src);
   87| extern void RunCompiler(const char* src, const char* occserc);
   88| 
   89| // defined in metaclass.cc
   90| extern void LoadMetaclass(char*);
   91| 
   92| void Compile(int argc, char** argv);
   93| void ParseCmdOptions(int from, int argc, char** argv, char*& source_file);
   94| void AddCppOption(const char* arg);
   95| void AddCcOption(const char* arg);
   96| void CloseCcOptions();
   97| bool IsCxxSource(char* fname);
   98| void ShowCommandLine(const char* cmd, const char** args);
   99| 
  100| static void ReadStdin();
  101| static void ReadFile(const char* src);
  102| static charRunOpencxx(const char* src);
  103| static int ParseOpencxx(Program* parse);
  104| static charParseOptions(int argc, char** argv);
  105| static void ShowVersion();
  106| static void ShowHelp(char**);
  107| static void AddCc2Option(const char* arg);
  108| static void RecordCmdOption(char* option);
  109| static void ParseCcOptions(char* arg, char*& source_file);
  110| 
  111| 
  112| void Compile(int argc, char** argv)
  113| {
  114|     charsrc = ParseOptions(argcargv);
  115|     if(src != nil)
  116|         ReadFile(src);
  117|     else
  118|         if(numOfObjectFiles == 0)
  119|             ReadStdin();
  120|         else
  121|             RunLinker();
  122| }
  123| 
  124| static void ReadStdin()
  125| {
  126|     std::cerr << "OpenC++: No source file.  Read from console.\n";
  127| 
  128|     ProgramFromStdin prog;
  129|     int nerrors = ParseOpencxx(&prog);
  130| 
  131|     if(!showProgram)
  132|         if(nerrors == 0)
  133|             prog.Write(cout, "stdout");
  134|         else{
  135|             std::cerr << nerrors << opencxxErrorMessage;
  136|             exit(1);
  137|         }
  138| }
  139| 
  140| static void ReadFile(const char* src)
  141| {
  142|     char *occfile;
  143| 
  144|     if(doPreprocess){
  145|         charcppfile = RunPreprocessor(src);
  146|         occfile = RunOpencxx(cppfile);
  147|         unlink(cppfile);
  148|         delete cppfile;
  149|     }
  150|     else
  151|         occfile = RunOpencxx(src);
  152| 
  153|     if(doCompile){
  154|         RunCompiler(srcoccfile);
  155|         // unlink(occfile);
  156|     }
  157| 
  158|     delete occfile;
  159| }
  160| 
  161| static charRunOpencxx(const char* src)
  162| {
  163|     chardest = OpenCxxOutputFileName(src);
  164| 
  165|     ifstream src_stream(src);
  166|     if(!src_stream){
  167|         perror(src);
  168|         exit(1);
  169|     }
  170| 
  171|     ProgramFile src_prog(src_stream);
  172|     if(verboseMode){
  173|         if(doTranslate)
  174|             std::cerr << "[Translate... " << src
  175|                 << " into: " << dest << "]\n";
  176|         else
  177|             std::cerr << "[Parse... " << src << "]\n";
  178|     }
  179| 
  180|     int nerrors = ParseOpencxx(&src_prog);
  181| 
  182|     if(nerrors != 0){
  183|         std::cerr << nerrors << opencxxErrorMessage;
  184|         exit(1);
  185|     }
  186| 
  187|     if(doTranslate){
  188|         ofstream dest_stream(dest, (ios::out | ios::trunc));
  189|         if(!dest_stream){
  190|             perror(dest);
  191|             exit(1);
  192|         }
  193| 
  194|         src_prog.Write(dest_streamdest);
  195|     }
  196| 
  197|     src_stream.close();
  198|     return dest;
  199| }
  200| 
  201| static int ParseOpencxx(Program* prog)
  202| {
  203|     Lex lex(prog);
  204|     Parser parse(&lex);
  205|     ClassWalker w(&parse);
  206|     Ptreedef;
  207| 
  208|     while(parse.rProgram(def)){
  209|         if(showProgram)
  210|             def->Display2(cout);
  211| 
  212|         if(doTranslate){
  213|             Ptreedef2 = w.Translate(def);
  214|             Ptreebefore = w.GetInsertedPtree();
  215|             Ptreeafter = w.GetAppendedPtree();
  216| 
  217|             prog->Insert(defbeforeafter);
  218|             if(def != def2)
  219|                prog->MinimumSubst(def2def);
  220|         }
  221|     }
  222| 
  223|     return parse.NumOfErrors();
  224| }
  225| 
  226| static charParseOptions(int argc, char** argv)
  227| {
  228|     charsource_file = nil;
  229|     showProgram = FALSE;
  230|     doCompile = TRUE;
  231|     verboseMode = FALSE;
  232|     makeExecutable = TRUE;
  233|     doPreprocess = TRUE;
  234|     doTranslate = TRUE;
  235|     regularCpp = FALSE;
  236|     makeSharedLibrary = FALSE;
  237|     sharedLibraryName = nil;
  238|     preprocessTwice = FALSE;
  239| 
  240|     AddCppOption(compilerName);
  241|     AddCcOption(compilerName);
  242| 
  243|     ParseCmdOptions(1argcargvsource_file);
  244| 
  245|     return source_file;
  246| }
  247| 
  248| void ParseCmdOptions(int from, int argc, char** argv, char*& source_file)
  249| {
  250|     int i;
  251|     for(i = fromi < argc; ++i)
  252|         if(strcmp("--"argv[i]) == 0)
  253|           break;
  254|         else if(strcmp("-E"argv[i]) == 0)
  255|             doCompile = FALSE;
  256|         else if(strcmp("-g"argv[i]) == 0)
  257|             AddCcOption(argv[i]);
  258|         else if (strcmp("-n"argv[i]) == 0)
  259|             doPreprocess = FALSE;
  260|         else if(*argv[i] == '-' && argv[i][1] == 'm'){
  261|             makeSharedLibrary = TRUE;
  262|             sharedLibraryName = &argv[i][2];
  263|         }
  264|         else if (strcmp("-P"argv[i]) == 0)
  265|             preprocessTwice = TRUE;
  266|         else if (strcmp("-p"argv[i]) == 0)
  267|             doTranslate = FALSE;
  268|         else if (strcmp("-C"argv[i]) == 0) {
  269|             AddCppOption("-C");
  270|             preprocessTwice = TRUE;
  271|         }
  272|         else if(strcmp("-c"argv[i]) == 0)
  273|             makeExecutable = FALSE;
  274|         else if(strcmp("-l"argv[i]) == 0){
  275|             cout << "[Loaded metaclasses...]\n";
  276|             opcxx_ListOfMetaclass::PrintAllMetaclasses();
  277|             exit(0);
  278|         }
  279|         else if(*argv[i] == '-' && argv[i][1] == 'S')
  280|             LoadMetaclass(&argv[i][2]);
  281|         else if(strcmp("-s"argv[i]) == 0)
  282|             showProgram = TRUE;
  283|         else if(strcmp("-v"argv[i]) == 0)
  284|             verboseMode = TRUE;
  285|         else if(strcmp("-V"argv[i]) == 0){
  286|             ShowVersion();
  287|             exit(1);
  288|         }
  289|         else if (strcmp("--regular-c++"argv[i]) == 0)
  290|             regularCpp = TRUE;
  291|         else if(*argv[i] == '-'
  292|                && (argv[i][1] == 'D' || argv[i][1] == 'I'))
  293|             AddCppOption(argv[i]);
  294|         else if(*argv[i] == '-' && argv[i][1] == 'd' && argv[i][2] != '\0')
  295|             AddCppOption(&argv[i][2]);
  296|         else if(*argv[i] == '-' && argv[i][1] == 'M')
  297|             RecordCmdOption(&argv[i][2]);
  298|         else if(*argv[i] == '-'){
  299|             ShowVersion();
  300|             ShowHelp(argv);
  301|             exit(1);
  302|         }
  303|         else if(!ParseTargetSpecificOptions(argv[i], source_file))
  304|             ParseCcOptions(argv[i], source_file);
  305| 
  306|     while(++i < argc)
  307|         if(!ParseTargetSpecificOptions(argv[i], source_file))
  308|             ParseCcOptions(argv[i], source_file);
  309| 
  310|     if(!doTranslate)
  311|         doCompile = FALSE;
  312| }
  313| 
  314| static void ShowVersion()
  315| {
  316|     std::cerr << "OpenC++ version " << thisVersion << "\n" << copyingNote << "\n";
  317| }
  318| 
  319| static void ShowHelp(char** argv)
  320| {
  321|     std::cerr << "Usage: "
  322|               << argv[0]
  323|               << " [-l][-s][-V][-v][-E][-m[<file name>]][-c][-n][-p][--regular-c++]\n"
  324|               << "\t\t[-I<directory>][-D<macro>[=<def>]][-M<option>[=<value>]]\n"
  325|               << "\t\t[-g][-d<option>][-S<metaclass>]\n"
  326|               << "\t\t[-- <compiler options>] <source file>\n"
  327|              << "\n"
  328|               << "    -g             Produce debugging information\n"
  329|               << "    -M             Specify an <option> with <value> passed to metaobjects\n"
  330|               << "    -l             List metaclasses\n"
  331|               << "    -S             Load a metaclass\n"
  332|               << "    -s             Show program tree on stdout\n"
  333|               << "    -V             Show version\n"
  334|               << "    -v             Verbose mode\n"
  335|              << "\n"
  336|               << " Building stages options\n"
  337|               << "    -n             Don't preprocess\n"
  338|               << "    -p             Don't translate (stop after parsing)\n"
  339|               << "    -E             Don't compile (stop after translation)\n"
  340|               << "    -c             Don't make executable (stop after compilation)\n"
  341| #if !defined(IRIX_CC) && !defined (_MSC_VER)
  342|               << "    -P             Preprocess again after translation\n"
  343| #endif
  344|               << "    -m             Compile a metaclass (make a shared library)\n"
  345|              << "\n"
  346|               << " Preprocessor options\n"
  347|               << "    -I<directory>  Add <directory> to the #include path\n"
  348|               << "    -D<name>=<def> Define a macro <name> as <def>\n"
  349|               << "    -d<option>     Specify a preprocessor option\n"
  350| #if !defined(IRIX_CC) && !defined (_MSC_VER)
  351|               << "    -C             Don't discard comments\n"
  352| #endif
  353|              << "\n"
  354|               << " Other options\n"
  355|               << "    --regular-c++  Inhibit the extended syntax\n";
  356| }
  357| 
  358| void AddCppOption(const char* arg)
  359| {
  360|     if(cppArgc < NARGS)
  361|         cppArgv[cppArgc++] = arg;
  362|     else{
  363|         std::cerr << "OpenC++: too many arguments\n";
  364|         exit(1);
  365|     }
  366| }
  367| 
  368| void AddCcOption(const char* arg)
  369| {
  370|     if(ccArgc < NARGS)
  371|         ccArgv[ccArgc++] = arg;
  372|     else{
  373|         std::cerr << "OpenC++: too many arguments\n";
  374|         exit(1);
  375|     }
  376| }
  377| 
  378| void CloseCcOptions()
  379| {
  380|     for(int i = 0i < cc2Argc; ++i)
  381|         AddCcOption(cc2Argv[i]);
  382| 
  383|     AddCcOption((char*)0);
  384| }
  385| 
  386| static void AddCc2Option(const char* arg)
  387| {
  388|     if(cc2Argc < NARGS)
  389|         cc2Argv[cc2Argc++] = arg;
  390|     else{
  391|         std::cerr << "OpenC++: too many arguments\n";
  392|         exit(1);
  393|     }
  394| }
  395| 
  396| static void RecordCmdOption(char* option)
  397| {
  398|     if(option == nil || *option == '\0')
  399|         return;
  400| 
  401|     charvalue = strchr(option'=');
  402|     if(value != nil)
  403|         *value++ = '\0';
  404| 
  405|     if(!Class::RecordCmdLineOption(optionvalue)){
  406|         std::cerr << "OpenC++: Too many -M options.\n";
  407|         exit(1);
  408|     }
  409| }
  410| 
  411| static void ParseCcOptions(char* arg, char*& source_file)
  412| {
  413|     static charerrmsg
  414|         "OpenC++: only a single source file is accepted at a time.\n";
  415| 
  416|     if(arg != nil && arg[0] != '-'){
  417|         if(IsCxxSource(arg))
  418|             if(source_file == nil){
  419|                source_file = arg;
  420|         return;
  421|         }
  422|          else{
  423|                std::cerr << errmsg;
  424|                exit(1);
  425|         }
  426|     }
  427| 
  428|     ++numOfObjectFiles;
  429|     if(source_file == nil)      // source file is already
  430|         AddCcOption(arg);
  431|     else
  432|         AddCc2Option(arg);
  433| 
  434|     return;
  435| }
  436| 
  437| /*
  438|   File Naming convention
  439| 
  440|   .c, .C, .cc, .cpp, .cxx : C++ source files
  441|   .mc : metaclass files
  442|   .occ, .ii, .i (IRIX_CC): temporary files used by OpenC++
  443| */
  444| bool IsCxxSource(char* fname)
  445| {
  446|     charext = strrchr(fname'.');
  447|     if(ext == nil)
  448|         return FALSE;
  449| 
  450|     if(strcmp(ext,    ".cc") == 0
  451|        || strcmp(ext".C") == 0
  452|        || strcmp(ext".c") == 0
  453|        || strcmp(ext".mc") == 0
  454|        || strcmp(ext".cxx") == 0
  455|        || strcmp(ext".cpp") == 0
  456|        || strcmp(ext".ii") == 0
  457|        || strcmp(ext".i") == 0
  458|        || strcmp(ext".occ") == 0)
  459|         return TRUE;
  460| 
  461|     return FALSE;
  462| }
  463| 
  464| void ShowCommandLine(const char*, const char** args)
  465| {
  466|     while(*args != nil)
  467|         std::cerr << ' ' << *args++;
  468| }