mirror of https://github.com/swig/swig
378 lines
11 KiB
C
378 lines
11 KiB
C
/* -----------------------------------------------------------------------------
|
|
* This file is part of SWIG, which is licensed as a whole under version 3
|
|
* (or any later version) of the GNU General Public License. Some additional
|
|
* terms also apply to certain portions of SWIG. The full details of the SWIG
|
|
* license and copyrights can be found in the LICENSE and COPYRIGHT files
|
|
* included with the SWIG source code as distributed by the SWIG developers
|
|
* and at https://www.swig.org/legal.html.
|
|
*
|
|
* include.c
|
|
*
|
|
* The functions in this file are used to manage files in the SWIG library.
|
|
* General purpose functions for opening, including, and retrieving pathnames
|
|
* are provided.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
#include "swig.h"
|
|
|
|
static List *directories = 0; /* List of include directories */
|
|
static String *lastpath = 0; /* Last file that was included */
|
|
static List *pdirectories = 0; /* List of pushed directories */
|
|
static int dopush = 1; /* Whether to push directories */
|
|
static int file_debug = 0;
|
|
|
|
/* This functions determine whether to push/pop dirs in the preprocessor */
|
|
void Swig_set_push_dir(int push) {
|
|
dopush = push;
|
|
}
|
|
|
|
int Swig_get_push_dir(void) {
|
|
return dopush;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_add_directory()
|
|
*
|
|
* Adds a directory to the SWIG search path.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
List *Swig_add_directory(const_String_or_char_ptr dirname) {
|
|
String *adirname;
|
|
if (!directories)
|
|
directories = NewList();
|
|
assert(directories);
|
|
if (dirname) {
|
|
adirname = NewString(dirname);
|
|
Append(directories,adirname);
|
|
Delete(adirname);
|
|
}
|
|
return directories;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_push_directory()
|
|
*
|
|
* Inserts a directory at the front of the SWIG search path. This is used by
|
|
* the preprocessor to grab files in the same directory as other included files.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
void Swig_push_directory(const_String_or_char_ptr dirname) {
|
|
String *pdirname;
|
|
if (!Swig_get_push_dir())
|
|
return;
|
|
if (!pdirectories)
|
|
pdirectories = NewList();
|
|
assert(pdirectories);
|
|
pdirname = NewString(dirname);
|
|
assert(pdirname);
|
|
Insert(pdirectories,0,pdirname);
|
|
Delete(pdirname);
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_pop_directory()
|
|
*
|
|
* Pops a directory off the front of the SWIG search path. This is used by
|
|
* the preprocessor.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
void Swig_pop_directory(void) {
|
|
if (!Swig_get_push_dir())
|
|
return;
|
|
if (!pdirectories)
|
|
return;
|
|
Delitem(pdirectories, 0);
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_last_file()
|
|
*
|
|
* Returns the full pathname of the last file opened.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
String *Swig_last_file(void) {
|
|
assert(lastpath);
|
|
return lastpath;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_search_path_any()
|
|
*
|
|
* Returns a list of the current search paths.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
static List *Swig_search_path_any(int syspath) {
|
|
String *filename;
|
|
List *slist;
|
|
int i, ilen;
|
|
|
|
slist = NewList();
|
|
assert(slist);
|
|
filename = NewStringEmpty();
|
|
assert(filename);
|
|
Printf(filename, ".%s", SWIG_FILE_DELIMITER);
|
|
Append(slist, filename);
|
|
Delete(filename);
|
|
|
|
/* If there are any pushed directories. Add them first */
|
|
if (pdirectories) {
|
|
ilen = Len(pdirectories);
|
|
for (i = 0; i < ilen; i++) {
|
|
filename = NewString(Getitem(pdirectories,i));
|
|
Append(filename,SWIG_FILE_DELIMITER);
|
|
Append(slist,filename);
|
|
Delete(filename);
|
|
}
|
|
}
|
|
/* Add system directories next */
|
|
ilen = Len(directories);
|
|
for (i = 0; i < ilen; i++) {
|
|
filename = NewString(Getitem(directories,i));
|
|
Append(filename,SWIG_FILE_DELIMITER);
|
|
if (syspath) {
|
|
/* If doing a system include, put the system directories first */
|
|
Insert(slist,i,filename);
|
|
} else {
|
|
/* Otherwise, just put the system directories after the pushed directories (if any) */
|
|
Append(slist,filename);
|
|
}
|
|
Delete(filename);
|
|
}
|
|
return slist;
|
|
}
|
|
|
|
List *Swig_search_path(void) {
|
|
return Swig_search_path_any(0);
|
|
}
|
|
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_open()
|
|
*
|
|
* open a file, optionally looking for it in the include path. Returns an open
|
|
* FILE * on success.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
static FILE *Swig_open_file(const_String_or_char_ptr name, int sysfile, int use_include_path) {
|
|
FILE *f;
|
|
String *filename;
|
|
List *spath = 0;
|
|
char *cname;
|
|
int i, ilen, nbytes;
|
|
char bom[3];
|
|
|
|
if (!directories)
|
|
directories = NewList();
|
|
assert(directories);
|
|
|
|
cname = Char(name);
|
|
filename = NewString(cname);
|
|
assert(filename);
|
|
if (file_debug) {
|
|
Printf(stdout, " Open: %s\n", filename);
|
|
}
|
|
f = fopen(Char(filename), "r");
|
|
if (!f && use_include_path) {
|
|
spath = Swig_search_path_any(sysfile);
|
|
ilen = Len(spath);
|
|
for (i = 0; i < ilen; i++) {
|
|
Clear(filename);
|
|
Printf(filename, "%s%s", Getitem(spath, i), cname);
|
|
f = fopen(Char(filename), "r");
|
|
if (f)
|
|
break;
|
|
}
|
|
Delete(spath);
|
|
}
|
|
if (f) {
|
|
Delete(lastpath);
|
|
lastpath = filename;
|
|
|
|
/* Skip the UTF-8 BOM if it's present */
|
|
nbytes = (int)fread(bom, 1, 3, f);
|
|
if (nbytes == 3 && bom[0] == (char)0xEF && bom[1] == (char)0xBB && bom[2] == (char)0xBF) {
|
|
/* skip */
|
|
} else {
|
|
fseek(f, 0, SEEK_SET);
|
|
}
|
|
}
|
|
return f;
|
|
}
|
|
|
|
/* Open a file - searching the include paths to find it */
|
|
FILE *Swig_include_open(const_String_or_char_ptr name) {
|
|
return Swig_open_file(name, 0, 1);
|
|
}
|
|
|
|
/* Open a file - does not use include paths to find it */
|
|
FILE *Swig_open(const_String_or_char_ptr name) {
|
|
return Swig_open_file(name, 0, 0);
|
|
}
|
|
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_read_file()
|
|
*
|
|
* Reads data from an open FILE * and returns it as a string.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
String *Swig_read_file(FILE *f) {
|
|
int len;
|
|
char buffer[4096];
|
|
String *str = NewStringEmpty();
|
|
|
|
assert(str);
|
|
while (fgets(buffer, 4095, f)) {
|
|
Append(str, buffer);
|
|
}
|
|
len = Len(str);
|
|
/* Add a newline if not present on last line -- the preprocessor seems to
|
|
* rely on \n and not EOF terminating lines */
|
|
if (len) {
|
|
char *cstr = Char(str);
|
|
if (cstr[len - 1] != '\n') {
|
|
Append(str, "\n");
|
|
}
|
|
}
|
|
return str;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_include()
|
|
*
|
|
* Opens a file and returns it as a string.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
static String *Swig_include_any(const_String_or_char_ptr name, int sysfile) {
|
|
FILE *f;
|
|
String *str;
|
|
String *file;
|
|
|
|
f = Swig_open_file(name, sysfile, 1);
|
|
if (!f)
|
|
return 0;
|
|
str = Swig_read_file(f);
|
|
fclose(f);
|
|
Seek(str, 0, SEEK_SET);
|
|
file = Copy(Swig_last_file());
|
|
Setfile(str, file);
|
|
Delete(file);
|
|
Setline(str, 1);
|
|
return str;
|
|
}
|
|
|
|
String *Swig_include(const_String_or_char_ptr name) {
|
|
return Swig_include_any(name, 0);
|
|
}
|
|
|
|
String *Swig_include_sys(const_String_or_char_ptr name) {
|
|
return Swig_include_any(name, 1);
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_insert_file()
|
|
*
|
|
* Copies the contents of a file into another file
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
int Swig_insert_file(const_String_or_char_ptr filename, File *outfile) {
|
|
char buffer[4096];
|
|
int nbytes;
|
|
FILE *f = Swig_include_open(filename);
|
|
|
|
if (!f)
|
|
return -1;
|
|
while ((nbytes = Read(f, buffer, 4096)) > 0) {
|
|
Write(outfile, buffer, nbytes);
|
|
}
|
|
fclose(f);
|
|
return 0;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_register_filebyname()
|
|
*
|
|
* Register a "named" file with the core. Named files can become targets
|
|
* for %insert directives and other SWIG operations. This function takes
|
|
* the place of the f_header, f_wrapper, f_init, and other global variables
|
|
* in SWIG1.1
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
static Hash *named_files = 0;
|
|
|
|
void Swig_register_filebyname(const_String_or_char_ptr filename, File *outfile) {
|
|
if (!named_files)
|
|
named_files = NewHash();
|
|
Setattr(named_files, filename, outfile);
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_filebyname()
|
|
*
|
|
* Get a named file
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
File *Swig_filebyname(const_String_or_char_ptr filename) {
|
|
if (!named_files)
|
|
return 0;
|
|
return Getattr(named_files, filename);
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_file_extension()
|
|
*
|
|
* Returns the extension of a file
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
String *Swig_file_extension(const_String_or_char_ptr filename) {
|
|
String *name = Swig_file_filename(filename);
|
|
const char *c = strrchr(Char(name), '.');
|
|
String *extension = c ? NewString(c) : NewString("");
|
|
Delete(name);
|
|
return extension;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_file_basename()
|
|
*
|
|
* Returns the filename with the extension removed.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
String *Swig_file_basename(const_String_or_char_ptr filename) {
|
|
String *extension = Swig_file_extension(filename);
|
|
String *basename = NewStringWithSize(filename, Len(filename) - Len(extension));
|
|
Delete(extension);
|
|
return basename;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_file_filename()
|
|
*
|
|
* Return the file name with any leading path stripped off
|
|
* ----------------------------------------------------------------------------- */
|
|
String *Swig_file_filename(const_String_or_char_ptr filename) {
|
|
const char *delim = SWIG_FILE_DELIMITER;
|
|
const char *c = strrchr(Char(filename), *delim);
|
|
return c ? NewString(c + 1) : NewString(filename);
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_file_dirname()
|
|
*
|
|
* Return the name of the directory associated with a file
|
|
* ----------------------------------------------------------------------------- */
|
|
String *Swig_file_dirname(const_String_or_char_ptr filename) {
|
|
const char *delim = SWIG_FILE_DELIMITER;
|
|
const char *c = strrchr(Char(filename), *delim);
|
|
return c ? NewStringWithSize(filename, (int)(c - Char(filename) + 1)) : NewString("");
|
|
}
|
|
|
|
/*
|
|
* Swig_file_debug()
|
|
*/
|
|
void Swig_file_debug_set(void) {
|
|
file_debug = 1;
|
|
}
|