Пример #1
0
/* Pushes a new file into the lexer's input stream while preserving
 * the existing stream. */
void setup_include(compiler_core_type* compiler, ins_stream_type *arg) {

  FILE *include_file = 0;
  char *file_name = 0;
  char new_include_path_buf[PATH_MAX];
  char *new_include_path = 0;
  char new_file_name[PATH_MAX];
  char raw_file_name[PATH_MAX];
  size_t length = 0;

  /* Get the file name for this node */
  file_name = arg->head->value.literal;

  /* Unless the file starts with a / look for it in the current include directory */
  if (file_name[0] == '/' || compiler->include_depth < 0) {
    include_file = fopen(file_name, "r");
  } else {

    /* setup include path */
    strcpy(new_include_path_buf, compiler->include_stack[compiler->include_depth]);
    new_include_path = dirname(new_include_path_buf);
    
    /* add 1 for null and 1 for / */
    length = strlen(new_include_path) + strlen(file_name) + 2;

    if (length > PATH_MAX) {
      (void)fprintf(stderr, "Error %i! Including '%s' - Search path too long: %zi characters\n",
        errno, file_name, length);
      parse_error(compiler, compiler->scanner, "Unable to open include file!");
      assert(0);
    }
  
    /* Assmeble the new filename */
    strcpy(raw_file_name, new_include_path);
    strcat(raw_file_name, "/");
    strcat(raw_file_name, file_name);

    /* Resolve the path so it makes sense later */
    file_name = realpath(raw_file_name, new_file_name);

    include_file = fopen(file_name, "r");
  }

  if ( !include_file ) {
    // TODO: Add file name tracking to compiler so we can 
    // report what file include failed in.
   
    (void)fprintf(stderr, "Error %i! Including '%s'\n", errno, raw_file_name);
    parse_error(compiler, compiler->scanner, "Unable to open include file!'");
  } else {
    parse_push_state(compiler, include_file);
    push_include_path(compiler, file_name);
  }
}
Пример #2
0
/* Compile a file */
void compile_file(compiler_type *comp_void, char *file_name, bool include_baselib) {
  compiler_core_type *compiler = (compiler_core_type *)comp_void;
  ins_stream_type *baselib = 0; /* TODO: should be gc root */
  FILE *in = 0;
  char path[PATH_MAX];

  /* Actually parse the input stream. */
  yylex_init_extra(compiler, &(compiler->scanner));

  in = fopen(file_name, "r");
  if (!in) {
    (void)fprintf(stderr, "Error %i while attempting to open '%s'\n",
      errno, file_name);
      assert(0);
  }

  //yyset_in(in, compiler->scanner);
  yy_switch_to_buffer(
    yy_create_buffer(in, YY_BUF_SIZE, compiler->scanner), compiler->scanner);

  push_include_path(compiler, file_name);

  /* TODO: Need a better way to handle GC than leaking */
  gc_protect(compiler->gc);

  /* Inject include for base library */
  if (include_baselib) {
    strcpy(path, compiler->home);
    strcat(path, "/lib/baselib.scm");

    STREAM_NEW(baselib, string, path);
    setup_include(compiler, baselib); 
  }
  
  parse_internal(compiler, compiler->scanner);
  
  gc_unprotect(compiler->gc);

  yylex_destroy(compiler->scanner);
}
Пример #3
0
FILE *rpp::pp::find_include_file(std::string const &p_input_filename, std::string *p_filepath,
                                 INCLUDE_POLICY p_include_policy, bool p_skip_current_path)  {
    assert(p_filepath != 0);
    assert(!p_input_filename.empty());

    p_filepath->assign(p_input_filename);

    if(is_absolute(*p_filepath))
        return std::fopen(p_filepath->c_str(), "r");

    if(!env.current_file.empty())
        _PP_internal::extract_file_path(env.current_file, p_filepath);

    if(p_include_policy == INCLUDE_LOCAL && !p_skip_current_path) {
        std::string __tmp(*p_filepath);
        __tmp += p_input_filename;

        if(file_exists(__tmp) && !file_isdir(__tmp)) {
            p_filepath->append(p_input_filename);
            if((verbose & DEBUGLOG_INCLUDE_DIRECTIVE) != 0)
                std::cout << "** INCLUDE local  " << *p_filepath << ": found" << std::endl;
            return std::fopen(p_filepath->c_str(), "r");
        }
    }

    std::vector<std::string>::const_iterator it = include_paths.begin();

    if(p_skip_current_path) {
        it = std::find(include_paths.begin(), include_paths.end(), *p_filepath);

        if(it != include_paths.end()) {
            ++it;
        } else {
            it = include_paths.begin();
        }
    }

    for(; it != include_paths.end(); ++it) {
        if(p_skip_current_path && it == include_paths.begin())
            continue;

        p_filepath->assign(*it);
        p_filepath->append(p_input_filename);

#ifdef Q_OS_MAC
        /* On MacOSX for those not familiar with the platform, it can group a collection of things
         *  like libraries/header files as installable modules called a framework.  A framework has
         *  a well defined layout, so <OpenGL/gl.h> would be transformed into a path
         *  /.../OpenGL.framework/Headers/gl.h
         */
        QString string = QString::fromStdString(p_input_filename);
        //QStringList list = string.split("/"); //could be used for error checks
        QString module = string.split("/")[0];
        if(!module.contains('.')) {
            string.replace(module + "/", module + ".framework/Headers/");
            string = QString::fromStdString(*it) + string;
            QFileInfo file = QFileInfo(string);
            if(file.exists() && file.isFile()) {
                QString path = QString::fromStdString(*it) + module + ".framework/Headers";
                push_include_path(path.toStdString());
                if((verbose & DEBUGLOG_INCLUDE_DIRECTIVE) != 0)
                    std::cout << "** INCLUDE system " << string.toStdString() << ": found" << std::endl;
                return std::fopen(string.toLatin1().data(), "r");
            }
        }
#endif
        if(file_exists(*p_filepath) && !file_isdir(*p_filepath)) {
            if((verbose & DEBUGLOG_INCLUDE_DIRECTIVE) != 0)
                std::cout << "** INCLUDE system " << *p_filepath << ": found" << std::endl;
            return std::fopen(p_filepath->c_str(), "r");
        }

        // Log all search attempts
        if((verbose & DEBUGLOG_INCLUDE_FULL) != 0)
            std::cout << "** INCLUDE system " << *p_filepath << ": " << strerror(errno) << std::endl;
    }

    return 0;
}