home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 20 / AACD20.BIN / AACD / Programming / Jikes / Source / src / option.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-03  |  19.4 KB  |  546 lines

  1. // $Id: option.cpp,v 1.52 2001/02/24 22:19:24 mdejong Exp $
  2. //
  3. // This software is subject to the terms of the IBM Jikes Compiler
  4. // License Agreement available at the following URL:
  5. // http://www.ibm.com/research/jikes.
  6. // Copyright (C) 1996, 1998, International Business Machines Corporation
  7. // and others.  All Rights Reserved.
  8. // You must accept the terms of that agreement to use this software.
  9. //
  10.  
  11. #include "option.h"
  12. #include "javasym.h"
  13. #include "error.h"
  14. #include "case.h"
  15.  
  16. //FIXME: include stuff
  17. //#include <ctype.h>
  18.  
  19.  
  20. // FIXME: this and other # defined things need to go in platform.cpp!
  21. #ifdef HAVE_SYS_CYGWIN_H
  22. #include <sys/cygwin.h>
  23. #endif
  24.  
  25. #ifdef    HAVE_JIKES_NAMESPACE
  26. namespace Jikes {    // Open namespace Jikes block
  27. #endif
  28.  
  29. //
  30. //
  31. //
  32. bool ArgumentExpander::ArgumentExpanded(Tuple<char *> &arguments, char *file_name)
  33. {
  34.     struct stat status;
  35.     FILE *afile = fopen(file_name, "r");
  36.     if (afile && (SystemStat(file_name, &status) == 0))
  37.     {
  38.         char *buffer = new char[status.st_size + 2];
  39.         int file_size = fread(buffer, 1, status.st_size, afile);
  40.         buffer[file_size] = '\n';
  41.         for (int k = 0; k < file_size; k++)
  42.         {
  43.             // FIXME : When \r is replaced by \n, we should not need to check for U_CARRIAGE_RETURN.
  44.             // Skip spaces and line termination characters
  45.             while (buffer[k] == U_SPACE || buffer[k] == U_LINE_FEED || buffer[k] == U_CARRIAGE_RETURN)
  46.                 k++;
  47.             // If we are at the end of the file, there must not have been any arguments in the file
  48.             if (k >= file_size)
  49.                 break;
  50.  
  51.             int n;
  52.             for (n = k + 1; ! (buffer[n] == U_SPACE || buffer[n] == U_LINE_FEED || buffer[n] == U_CARRIAGE_RETURN); n++)
  53.                 ;
  54.             buffer[n] = U_NULL;
  55.             char *str = new char[n - k + 1];
  56.             strcpy(str, &buffer[k]);
  57.             arguments.Next() = str;
  58.             k = n;
  59.         }
  60.         delete [] buffer;
  61.         fclose(afile);
  62.  
  63.         return true;
  64.     }
  65.  
  66.     return false;
  67. }
  68.  
  69.  
  70. ArgumentExpander::ArgumentExpander(int argc_, char *argv_[])
  71. {
  72.     Tuple<char *> arguments(8192);
  73.     for (int i = 0; i < argc_; i++)
  74.     {
  75.         char *argument = argv_[i];
  76.         if (argument[0] != '@' || (! ArgumentExpanded(arguments, argument + 1)))
  77.         {
  78.             char *str = new char[strlen(argument) + 1];
  79.             strcpy(str, argument);
  80.             arguments.Next() = str;
  81.         }
  82.     }
  83.  
  84.     argc = arguments.Length();
  85.     argv = new char*[argc];
  86.  
  87.     for (int k = 0; k < argc; k++)
  88.         argv[k] = arguments[k];
  89.  
  90.     return;
  91. }
  92.  
  93.  
  94. ArgumentExpander::ArgumentExpander(Tuple<char> &line)
  95. {
  96.     Tuple<char *> arguments(8192);
  97.  
  98.     int end = 0;
  99.     do
  100.     {
  101.         for (; end < line.Length() && line[end] == U_SPACE; end++)
  102.             ;
  103.         if (end < line.Length())
  104.         {
  105.             int start = end;
  106.             for (end++; end < line.Length() && line[end] != U_SPACE; end++)
  107.                 ;
  108.             int length = end - start;
  109.             char *argument = new char[length + 1];
  110.             for (int i = 0, k = start; k < end; i++, k++)
  111.                 argument[i] = line[k];
  112.             argument[length] = U_NULL;
  113.  
  114.             if (argument[0] == '@' && ArgumentExpanded(arguments, argument + 1))
  115.                  delete argument;
  116.             else arguments.Next() = argument;
  117.         }
  118.     } while(end < line.Length());
  119.  
  120.     argc = arguments.Length();
  121.     argv = new char*[argc];
  122.  
  123.     for (int k = 0; k < argc; k++)
  124.         argv[k] = arguments[k];
  125.  
  126.     return;
  127. }
  128.  
  129.  
  130. #ifdef WIN32_FILE_SYSTEM
  131. void Option::SaveCurrentDirectoryOnDisk(char c)
  132. {
  133.     if (! current_directory[c])
  134.     {
  135.         char *disk_directory = NULL,
  136.              disk[3] = { c, U_COLON, U_NULL },
  137.              tmp[1];
  138.  
  139.         if (SetCurrentDirectory(disk))
  140.         {
  141.             DWORD directory_length = GetCurrentDirectory(0, tmp);  // first, get the right size
  142.             disk_directory = new char[directory_length + 1];       // allocate the directory
  143.             DWORD length = GetCurrentDirectory(directory_length, disk_directory);
  144.             if (length <= directory_length)
  145.             {
  146.                 for (char *ptr = disk_directory; *ptr; ptr++)
  147.                     *ptr = (*ptr != U_BACKSLASH ? *ptr : (char) U_SLASH); // turn '\' to '/'.
  148.             }
  149.         }
  150.  
  151.         if (! disk_directory)
  152.         {
  153.             disk_directory = new char[2];
  154.             strcpy(disk_directory, StringConstant::U8S__DO);
  155.         }
  156.  
  157.         current_directory[Case::ToAsciiLower(c)] = disk_directory;
  158.         current_directory[Case::ToAsciiUpper(c)] = disk_directory;
  159.     }
  160.  
  161.     return;
  162. }
  163. #endif
  164.  
  165.  
  166. Option::Option(ArgumentExpander &arguments) :
  167.                                               first_file_index(arguments.argc),
  168.                                               debug_trap_op(0),
  169.                                               debug_dump_lex(false),
  170.                                               debug_dump_ast(false),
  171.                                               debug_unparse_ast(false),
  172.                                               debug_unparse_ast_debug(false),
  173.                                               debug_dump_class(false),
  174.                                               nocleanup(false),
  175.                                               incremental(false),
  176.                                               makefile(false),
  177.                                               dependence_report(false),
  178.                                               bytecode(true),
  179.                                               full_check(false),
  180.                                               unzip(false),
  181.                                               dump_errors(false),
  182.                                               errors(true),
  183.                                               comments(false),
  184.                                               pedantic(false),
  185.                                               dependence_report_name(NULL)
  186. {
  187. #ifdef WIN32_FILE_SYSTEM
  188.     for (int j = 0; j < 128; j++)
  189.          current_directory[j] = NULL;
  190.  
  191.     char tmp[1];
  192.     DWORD directory_length = GetCurrentDirectory(0, tmp); // first, get the right size
  193.     char *main_current_directory = new char[directory_length + 1];   // allocate the directory
  194.     DWORD length = GetCurrentDirectory(directory_length, main_current_directory);
  195.     if (length > directory_length)
  196.     {
  197.         delete [] main_current_directory; // FIXME: missing a delete of main_current_directory ???
  198.         main_current_directory = StringConstant::U8S__DO;
  199.         main_disk = 0;
  200.     }
  201.     else
  202.     {
  203.         for (char *ptr = main_current_directory; *ptr; ptr++)
  204.             *ptr = (*ptr != U_BACKSLASH ? *ptr : (char) U_SLASH); // turn '\' to '/'.
  205.         main_disk = main_current_directory[0]; // the first character
  206.         current_directory[Case::ToAsciiLower(main_disk)] = main_current_directory;
  207.         current_directory[Case::ToAsciiUpper(main_disk)] = main_current_directory;
  208.     }
  209.     current_directory[0] = main_current_directory;
  210. #endif
  211.  
  212.     char * classpath_buffer;
  213.     Tuple<int> filename_index(2048);
  214.  
  215.     for (int i = 1; i < arguments.argc; i++)
  216.     {
  217.         if (arguments.argv[i][0] == '-')
  218.         {
  219.             if (strcmp(arguments.argv[i],"-classpath") == 0 && ((i + 1) < arguments.argc))
  220.             {
  221.                 classpath = arguments.argv[++i];
  222.         
  223.                 // Create a copy of the -classpath argument so we can modify
  224.                 //   this copy and delete it later in ~JikesOption
  225.                 classpath_buffer = new char[strlen(classpath)+1];
  226.                 strcpy(classpath_buffer, classpath);
  227.                 classpath = classpath_buffer;
  228.  
  229. #ifdef EBCDIC
  230.                 //
  231.                 //  Maintain CLASSPATH in ASCII and translate back to EBCDIC when building file name
  232.                 //
  233.                 for (int k = 0; k < strlen(classpath); k++)
  234.                     classpath[k] = Code::ToASCII(classpath[k]);
  235. #endif
  236.             }
  237.             else if (strcmp(arguments.argv[i], "-depend") == 0 || strcmp(arguments.argv[i], "-Xdepend") == 0)
  238.                  depend = true;
  239. #if defined(HAVE_LIB_ICU_UC) || defined(HAVE_ICONV_H)
  240.             else if (strcmp(arguments.argv[i], "-encoding") == 0 && ((i + 1) < arguments.argc))
  241.             {
  242.                 i++;
  243.                 encoding = new char[strlen(arguments.argv[i]) + 1];
  244.                 strcpy(encoding, arguments.argv[i]);
  245.                 if (! Stream::IsSupportedEncoding(encoding))
  246.                 {
  247.                     bad_options.Next() =
  248.                         new OptionError(SemanticError::UNSUPPORTED_ENCODING, encoding);
  249.                     encoding = NULL;
  250.                 }
  251.  
  252.                 continue;
  253.             }
  254. #endif // defined(HAVE_LIB_ICU_UC) || defined(HAVE_ICONV_H)
  255.             else if (strcmp(arguments.argv[i],"-verbose") == 0)
  256.                  verbose = true;
  257.             else if (strcmp(arguments.argv[i],"-g") == 0)
  258.                  g = true;
  259.             else if (strcmp(arguments.argv[i], "-O") == 0)
  260.                  O = true;
  261.             else if (strcmp(arguments.argv[i],"-deprecation") == 0)
  262.                  deprecation = true;
  263.             else if (strcmp(arguments.argv[i],"-nowrite") == 0)
  264.                  nowrite = true;
  265.             else if (strcmp(arguments.argv[i],"-nowarn") == 0)
  266.                  nowarn = true;
  267.             else if (strcmp(arguments.argv[i],"-Xstdout") == 0)
  268.                  Coutput.StandardOutput();
  269.             else if (strcmp(arguments.argv[i], "-d") == 0 && ((i + 1) < arguments.argc))
  270.             {
  271.                 ++i;
  272. #if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
  273.                 int length = strlen(arguments.argv[i]);
  274.                 directory = new char[length + 1];
  275.                 strcpy(directory, arguments.argv[i]);
  276. #elif defined(WIN32_FILE_SYSTEM)
  277.                 char disk = (strlen(arguments.argv[i]) >= 2 &&
  278.                             Case::IsAsciiAlpha(arguments.argv[i][0]) &&
  279.                             arguments.argv[i][1] == U_COLON
  280.                                      ? arguments.argv[i][0]
  281.                                      : 0);
  282.                 SaveCurrentDirectoryOnDisk(disk);
  283.                 if (SetCurrentDirectory(arguments.argv[i]))
  284.                 {
  285.                     char tmp[1];
  286.                     DWORD directory_length = GetCurrentDirectory(0, tmp); // first, get the right size
  287.                     directory = new char[directory_length + 1]; // allocate the directory
  288.                     DWORD length = GetCurrentDirectory(directory_length, directory);
  289.                     if (length > directory_length)
  290.                     {
  291.                         delete [] directory;
  292.                         directory = NULL;
  293.                     }
  294.                 }
  295.  
  296.                 ResetCurrentDirectoryOnDisk(disk); // reset the current directory on the disk
  297.                 SetMainCurrentDirectory();       // reset the real current directory...
  298.  
  299.                 if (! directory)
  300.                     bad_options.Next() = new OptionError(SemanticError::INVALID_DIRECTORY, arguments.argv[i]);
  301. #endif
  302. #ifdef EBCDIC
  303.                 //
  304.                 // need to translate directory name to ASCII
  305.                 //
  306.                 for (int k = 0; k < directory_length; k++)
  307.                     directory[k] = Code::ToASCII(directory[k]);
  308. #endif
  309.                 if (directory)
  310.                 {
  311.                     for (char *ptr = directory; *ptr; ptr++)
  312.                         *ptr = (*ptr != U_BACKSLASH ? *ptr : (char) U_SLASH); // turn '\' to '/'.
  313.                 }
  314.             }
  315.             else bad_options.Next() = new OptionError(SemanticError::INVALID_OPTION, arguments.argv[i]);
  316.         }
  317.         else if (arguments.argv[i][0] == '+')
  318.         {
  319.             if (strcmp(arguments.argv[i], "+A") == 0)
  320.                  debug_dump_ast = true;
  321.             else if (strcmp(arguments.argv[i], "+u") == 0)
  322.                  debug_unparse_ast = true;
  323.             else if (strcmp(arguments.argv[i], "+ud") == 0)
  324.             {
  325.                 debug_unparse_ast = true;
  326.                 debug_unparse_ast_debug = true;
  327.             }
  328. #ifdef EBCDIC
  329.             else if (strcmp(arguments.argv[i], "+ASCII") == 0)
  330.                      ascii = true;
  331. #endif
  332.             else if (strcmp(arguments.argv[i], "+B") == 0)
  333.                  bytecode = false;
  334.             else if (strcmp(arguments.argv[i], "+c") == 0)
  335.                  comments = true;
  336.             else if (strcmp(arguments.argv[i], "+C") == 0)
  337.                  debug_dump_class = true;
  338.             else if (strcmp(arguments.argv[i], "+OLDCSO") == 0)
  339.                  old_classpath_search_order = true;
  340.             else if (strcmp(arguments.argv[i],"+D") == 0)
  341.             {
  342.                  dump_errors = true;
  343.                  errors = false;
  344.             }
  345.             else if (strcmp(arguments.argv[i],"+E") == 0)
  346.             {
  347.                 errors = false;
  348.             }
  349.             else if (arguments.argv[i][0] == '+' && arguments.argv[i][1] == 'K')
  350.             {
  351.                 char *name = arguments.argv[i] + 2,
  352.                      *image;
  353.                 for (image = name; *image && *image != '='; image++)
  354.                     ;
  355.  
  356.                 if (*image != '=')
  357.                     bad_options.Next() = new OptionError(SemanticError::INVALID_K_OPTION, arguments.argv[i]);
  358.                 else
  359.                 {
  360.                     int key = 0; // assume undefined
  361.                     image++;
  362.  
  363.                     if (strcmp(image, "boolean") == 0)
  364.                          key = TK_boolean;
  365.                     else if (strcmp(image, "byte") == 0)
  366.                          key = TK_byte;
  367.                     else if (strcmp(image, "char") == 0)
  368.                          key = TK_char;
  369.                     else if (strcmp(image, "short") == 0)
  370.                          key = TK_short;
  371.                     else if (strcmp(image, "int") == 0)
  372.                          key = TK_int;
  373.                     else if (strcmp(image, "long") == 0)
  374.                          key = TK_long;
  375.                     else if (strcmp(image, "float") == 0)
  376.                          key = TK_float;
  377.                     else if (strcmp(image, "double") == 0)
  378.                          key = TK_double;
  379.                     else bad_options.Next() = new OptionError(SemanticError::INVALID_K_TARGET, image);
  380.  
  381.                     if (key != 0)
  382.                     {
  383.                         int i = keyword_map.NextIndex();
  384.                         keyword_map[i].key = key;
  385.                         keyword_map[i].length = image - name - 1;
  386.                         keyword_map[i].name = new wchar_t[keyword_map[i].length];
  387.                         for (int k = 0; k < keyword_map[i].length; k++)
  388.                             keyword_map[i].name[k] = name[k];
  389.                     }
  390.                 }
  391.             }
  392.             else if (strcmp(arguments.argv[i],"+F") == 0)
  393.                  full_check = true;
  394.             else if (strcmp(arguments.argv[i],"+M") == 0)
  395.             {
  396.                  makefile = true;
  397.                  full_check = true;
  398.             }
  399.             else if (strncmp(arguments.argv[i], "+DR=", 4) == 0)
  400.             {
  401.                  makefile = true;
  402.                  dependence_report=true;
  403.                  full_check = true;
  404.          dependence_report_name =
  405.              new char[strlen(&arguments.argv[i][4]) + 1];
  406.          strcpy(dependence_report_name, &arguments.argv[i][4]);
  407.             }
  408.             else if (strcmp(arguments.argv[i], "+O") == 0)
  409.             {
  410.                  debug_trap_op = atoi(arguments.argv[i + 1]);
  411.                  i++;
  412.             }
  413.             else if (strcmp(arguments.argv[i],"+P") == 0)
  414.                  pedantic = true;
  415.             else if (arguments.argv[i][0] == U_PLUS && arguments.argv[i][1] == U_T)
  416.             {
  417.                 int tab_size = 0;
  418.                 char *image = arguments.argv[i] + 2,
  419.                      *p;
  420.                 for (p = image; *p && Code::IsDigit(*p); p++)
  421.                 {
  422.                     int digit = *p - U_0;
  423.                     tab_size = tab_size * 10 + digit;
  424.                 }
  425.  
  426.                 if (*p)
  427.                      bad_options.Next() = new OptionError(SemanticError::INVALID_TAB_VALUE, image);
  428.                 Tab::SetTabSize(tab_size == 0 ? Tab::DEFAULT_TAB_SIZE : tab_size);
  429.             }
  430.             else if (strcmp(arguments.argv[i], "+L") == 0)
  431.                  debug_dump_lex = true;
  432.             else if (strcmp(arguments.argv[i],"+U") == 0)
  433.             {
  434.                  unzip = true;
  435.                  full_check = true;
  436.             }
  437.             else if (strcmp(arguments.argv[i],"++") == 0)
  438.             {
  439.                  incremental = true;
  440.                  full_check = true;
  441.             }
  442.             else if (strcmp(arguments.argv[i], "+Z") == 0)
  443.                  zero_defect = true;
  444.             else bad_options.Next() = new OptionError(SemanticError::INVALID_OPTION, arguments.argv[i]);
  445.         }
  446.         else filename_index.Next() = i;
  447.     }
  448.  
  449.     if (! classpath)
  450.     {
  451.         classpath = getenv("JIKESPATH");
  452.         if (! classpath)
  453.             classpath = getenv("CLASSPATH");
  454.  
  455.         if (classpath)
  456.         {
  457.             /* Create a copy of the classpath string we can modify
  458.                this copy without worry that it will effect the env array */
  459.             classpath_buffer = new char[strlen(classpath)+1];
  460.             strcpy(classpath_buffer, classpath);
  461.             classpath = classpath_buffer;
  462.  
  463. #ifdef EBCDIC
  464.             //
  465.             //  Maintain CLASSPATH in ASCII and translate back to EBCDIC when building file name
  466.             //
  467.             for (int k = 0; k < strlen(classpath); k++)
  468.                 classpath[k] = Code::ToASCII(classpath[k]);
  469. #endif
  470.             while (isspace(*classpath))
  471.                 classpath++;
  472.  
  473.             if (*classpath == U_NULL) {
  474.                 delete [] classpath;
  475.                 classpath = NULL;
  476.             }
  477.         }
  478.  
  479.         if (! classpath)
  480.         {
  481.             classpath = new char[2];
  482.             classpath[0] = '.';
  483.             classpath[1] = U_NULL;
  484.         }
  485.     }
  486.     
  487.     // If we need to do a cygwin CLASSPATH conversion do it after the env is checked
  488.     // so that it will work for a -classpath argument or a CLASSPATH env var.
  489.  
  490. #ifdef HAVE_CYGWIN_WIN32_TO_POSIX_PATH_LIST
  491.     // Under Cygwin, we convert a windows style path into a unix
  492.     // style path. A path like "C:\Cygwin\tmp;C:\Windows" is converted
  493.     // into "/tmp:/cygdrive/c/Windows" (assuming C:\Cygwin is cygroot).
  494.     // We can then parse it using the unix path seperator char ':'
  495.     classpath_buffer = new char[cygwin_win32_to_posix_path_list_buf_size(classpath)];
  496.     cygwin_win32_to_posix_path_list(classpath, classpath_buffer);
  497.     delete [] classpath;
  498.     classpath = classpath_buffer;
  499. #endif
  500.  
  501.     //
  502.     // Initially, first_file_index is set to argc. Since the array filename_index
  503.     // contains the indices of all the input files in arguments in reverse order,
  504.     // we reverse the order here again to get the original list...
  505.     //
  506.     for (int k = filename_index.Length() - 1; k >= 0; k--)
  507.     {
  508.         first_file_index--;
  509.  
  510.         int i = filename_index[k];
  511.         char *temp = arguments.argv[i];
  512.         arguments.argv[i] = arguments.argv[first_file_index];
  513.         arguments.argv[first_file_index] = temp;
  514.     }
  515.  
  516.     //
  517.     // If the traditional batch output form for reporting errors is requested,
  518.     // then wide character expansion is turned on.
  519.     //
  520.     if (errors && (! dump_errors))
  521.         Coutput.SetExpandWchar();
  522.  
  523.     return;
  524. }
  525.  
  526.  
  527. Option::~Option()
  528. {
  529.     for (int i = 0; i < bad_options.Length(); i++)
  530.         delete bad_options[i];
  531.  
  532.     delete [] dependence_report_name;
  533.  
  534. #ifdef WIN32_FILE_SYSTEM
  535.     for (char c = 'a'; c <= 'z'; c++)
  536.         delete [] current_directory[c];
  537. #endif
  538.  
  539.     return;
  540. }
  541.  
  542. #ifdef    HAVE_JIKES_NAMESPACE
  543. }            // Close namespace Jikes block
  544. #endif
  545.  
  546.