1 /* -----------------------------------------------------------------------------
2  * This file is part of SWIG, which is licensed as a whole under version 3
3  * (or any later version) of the GNU General Public License. Some additional
4  * terms also apply to certain portions of SWIG. The full details of the SWIG
5  * license and copyrights can be found in the LICENSE and COPYRIGHT files
6  * included with the SWIG source code as distributed by the SWIG developers
7  * and at http://www.swig.org/legal.html.
8  *
9  * include.c
10  *
11  * The functions in this file are used to manage files in the SWIG library.
12  * General purpose functions for opening, including, and retrieving pathnames
13  * are provided.
14  * ----------------------------------------------------------------------------- */
15 
16 #include "swig.h"
17 
18 static List   *directories = 0;	        /* List of include directories */
19 static String *lastpath = 0;	        /* Last file that was included */
20 static List   *pdirectories = 0;        /* List of pushed directories  */
21 static int     dopush = 1;		/* Whether to push directories */
22 static int file_debug = 0;
23 
24 /* This functions determine whether to push/pop dirs in the preprocessor */
Swig_set_push_dir(int push)25 void Swig_set_push_dir(int push) {
26   dopush = push;
27 }
28 
Swig_get_push_dir(void)29 int Swig_get_push_dir(void) {
30   return dopush;
31 }
32 
33 /* -----------------------------------------------------------------------------
34  * Swig_add_directory()
35  *
36  * Adds a directory to the SWIG search path.
37  * ----------------------------------------------------------------------------- */
38 
Swig_add_directory(const_String_or_char_ptr dirname)39 List *Swig_add_directory(const_String_or_char_ptr dirname) {
40   String *adirname;
41   if (!directories)
42     directories = NewList();
43   assert(directories);
44   if (dirname) {
45     adirname = NewString(dirname);
46     Append(directories,adirname);
47     Delete(adirname);
48   }
49   return directories;
50 }
51 
52 /* -----------------------------------------------------------------------------
53  * Swig_push_directory()
54  *
55  * Inserts a directory at the front of the SWIG search path.  This is used by
56  * the preprocessor to grab files in the same directory as other included files.
57  * ----------------------------------------------------------------------------- */
58 
Swig_push_directory(const_String_or_char_ptr dirname)59 void Swig_push_directory(const_String_or_char_ptr dirname) {
60   String *pdirname;
61   if (!Swig_get_push_dir())
62     return;
63   if (!pdirectories)
64     pdirectories = NewList();
65   assert(pdirectories);
66   pdirname = NewString(dirname);
67   assert(pdirname);
68   Insert(pdirectories,0,pdirname);
69   Delete(pdirname);
70 }
71 
72 /* -----------------------------------------------------------------------------
73  * Swig_pop_directory()
74  *
75  * Pops a directory off the front of the SWIG search path.  This is used by
76  * the preprocessor.
77  * ----------------------------------------------------------------------------- */
78 
Swig_pop_directory(void)79 void Swig_pop_directory(void) {
80   if (!Swig_get_push_dir())
81     return;
82   if (!pdirectories)
83     return;
84   Delitem(pdirectories, 0);
85 }
86 
87 /* -----------------------------------------------------------------------------
88  * Swig_last_file()
89  *
90  * Returns the full pathname of the last file opened.
91  * ----------------------------------------------------------------------------- */
92 
Swig_last_file(void)93 String *Swig_last_file(void) {
94   assert(lastpath);
95   return lastpath;
96 }
97 
98 /* -----------------------------------------------------------------------------
99  * Swig_search_path_any()
100  *
101  * Returns a list of the current search paths.
102  * ----------------------------------------------------------------------------- */
103 
Swig_search_path_any(int syspath)104 static List *Swig_search_path_any(int syspath) {
105   String *filename;
106   List   *slist;
107   int     i, ilen;
108 
109   slist = NewList();
110   assert(slist);
111   filename = NewStringEmpty();
112   assert(filename);
113 #ifdef MACSWIG
114   Printf(filename, "%s", SWIG_FILE_DELIMITER);
115 #else
116   Printf(filename, ".%s", SWIG_FILE_DELIMITER);
117 #endif
118   Append(slist, filename);
119   Delete(filename);
120 
121   /* If there are any pushed directories.  Add them first */
122   if (pdirectories) {
123     ilen = Len(pdirectories);
124     for (i = 0; i < ilen; i++) {
125       filename = NewString(Getitem(pdirectories,i));
126       Append(filename,SWIG_FILE_DELIMITER);
127       Append(slist,filename);
128       Delete(filename);
129     }
130   }
131   /* Add system directories next */
132   ilen = Len(directories);
133   for (i = 0; i < ilen; i++) {
134     filename = NewString(Getitem(directories,i));
135     Append(filename,SWIG_FILE_DELIMITER);
136     if (syspath) {
137       /* If doing a system include, put the system directories first */
138       Insert(slist,i,filename);
139     } else {
140       /* Otherwise, just put the system directories after the pushed directories (if any) */
141       Append(slist,filename);
142     }
143     Delete(filename);
144   }
145   return slist;
146 }
147 
Swig_search_path()148 List *Swig_search_path() {
149   return Swig_search_path_any(0);
150 }
151 
152 
153 
154 /* -----------------------------------------------------------------------------
155  * Swig_open()
156  *
157  * open a file, optionally looking for it in the include path.  Returns an open
158  * FILE * on success.
159  * ----------------------------------------------------------------------------- */
160 
Swig_open_file(const_String_or_char_ptr name,int sysfile,int use_include_path)161 static FILE *Swig_open_file(const_String_or_char_ptr name, int sysfile, int use_include_path) {
162   FILE *f;
163   String *filename;
164   List *spath = 0;
165   char *cname;
166   int i, ilen, nbytes;
167   char bom[3];
168 
169   if (!directories)
170     directories = NewList();
171   assert(directories);
172 
173   cname = Char(name);
174   filename = NewString(cname);
175   assert(filename);
176   if (file_debug) {
177     Printf(stdout, "  Open: %s\n", filename);
178   }
179   f = fopen(Char(filename), "r");
180   if (!f && use_include_path) {
181     spath = Swig_search_path_any(sysfile);
182     ilen = Len(spath);
183     for (i = 0; i < ilen; i++) {
184       Clear(filename);
185       Printf(filename, "%s%s", Getitem(spath, i), cname);
186       f = fopen(Char(filename), "r");
187       if (f)
188 	break;
189     }
190     Delete(spath);
191   }
192   if (f) {
193     Delete(lastpath);
194     lastpath = filename;
195 
196     /* Skip the UTF-8 BOM if it's present */
197     nbytes = (int)fread(bom, 1, 3, f);
198     if (nbytes == 3 && bom[0] == (char)0xEF && bom[1] == (char)0xBB && bom[2] == (char)0xBF) {
199       /* skip */
200     } else {
201       fseek(f, 0, SEEK_SET);
202     }
203   }
204   return f;
205 }
206 
207 /* Open a file - searching the include paths to find it */
Swig_include_open(const_String_or_char_ptr name)208 FILE *Swig_include_open(const_String_or_char_ptr name) {
209   return Swig_open_file(name, 0, 1);
210 }
211 
212 /* Open a file - does not use include paths to find it */
Swig_open(const_String_or_char_ptr name)213 FILE *Swig_open(const_String_or_char_ptr name) {
214   return Swig_open_file(name, 0, 0);
215 }
216 
217 
218 
219 /* -----------------------------------------------------------------------------
220  * Swig_read_file()
221  *
222  * Reads data from an open FILE * and returns it as a string.
223  * ----------------------------------------------------------------------------- */
224 
Swig_read_file(FILE * f)225 String *Swig_read_file(FILE *f) {
226   int len;
227   char buffer[4096];
228   String *str = NewStringEmpty();
229 
230   assert(str);
231   while (fgets(buffer, 4095, f)) {
232     Append(str, buffer);
233   }
234   len = Len(str);
235   /* Add a newline if not present on last line -- the preprocessor seems to
236    * rely on \n and not EOF terminating lines */
237   if (len) {
238     char *cstr = Char(str);
239     if (cstr[len - 1] != '\n') {
240       Append(str, "\n");
241     }
242   }
243   return str;
244 }
245 
246 /* -----------------------------------------------------------------------------
247  * Swig_include()
248  *
249  * Opens a file and returns it as a string.
250  * ----------------------------------------------------------------------------- */
251 
Swig_include_any(const_String_or_char_ptr name,int sysfile)252 static String *Swig_include_any(const_String_or_char_ptr name, int sysfile) {
253   FILE *f;
254   String *str;
255   String *file;
256 
257   f = Swig_open_file(name, sysfile, 1);
258   if (!f)
259     return 0;
260   str = Swig_read_file(f);
261   fclose(f);
262   Seek(str, 0, SEEK_SET);
263   file = Copy(Swig_last_file());
264   Setfile(str, file);
265   Delete(file);
266   Setline(str, 1);
267   return str;
268 }
269 
Swig_include(const_String_or_char_ptr name)270 String *Swig_include(const_String_or_char_ptr name) {
271   return Swig_include_any(name, 0);
272 }
273 
Swig_include_sys(const_String_or_char_ptr name)274 String *Swig_include_sys(const_String_or_char_ptr name) {
275   return Swig_include_any(name, 1);
276 }
277 
278 /* -----------------------------------------------------------------------------
279  * Swig_insert_file()
280  *
281  * Copies the contents of a file into another file
282  * ----------------------------------------------------------------------------- */
283 
Swig_insert_file(const_String_or_char_ptr filename,File * outfile)284 int Swig_insert_file(const_String_or_char_ptr filename, File *outfile) {
285   char buffer[4096];
286   int nbytes;
287   FILE *f = Swig_include_open(filename);
288 
289   if (!f)
290     return -1;
291   while ((nbytes = Read(f, buffer, 4096)) > 0) {
292     Write(outfile, buffer, nbytes);
293   }
294   fclose(f);
295   return 0;
296 }
297 
298 /* -----------------------------------------------------------------------------
299  * Swig_register_filebyname()
300  *
301  * Register a "named" file with the core.  Named files can become targets
302  * for %insert directives and other SWIG operations.  This function takes
303  * the place of the f_header, f_wrapper, f_init, and other global variables
304  * in SWIG1.1
305  * ----------------------------------------------------------------------------- */
306 
307 static Hash *named_files = 0;
308 
Swig_register_filebyname(const_String_or_char_ptr filename,File * outfile)309 void Swig_register_filebyname(const_String_or_char_ptr filename, File *outfile) {
310   if (!named_files)
311     named_files = NewHash();
312   Setattr(named_files, filename, outfile);
313 }
314 
315 /* -----------------------------------------------------------------------------
316  * Swig_filebyname()
317  *
318  * Get a named file
319  * ----------------------------------------------------------------------------- */
320 
Swig_filebyname(const_String_or_char_ptr filename)321 File *Swig_filebyname(const_String_or_char_ptr filename) {
322   if (!named_files)
323     return 0;
324   return Getattr(named_files, filename);
325 }
326 
327 /* -----------------------------------------------------------------------------
328  * Swig_file_extension()
329  *
330  * Returns the extension of a file
331  * ----------------------------------------------------------------------------- */
332 
Swig_file_extension(const_String_or_char_ptr filename)333 String *Swig_file_extension(const_String_or_char_ptr filename) {
334   String *name = Swig_file_filename(filename);
335   const char *c = strrchr(Char(name), '.');
336   String *extension = c ? NewString(c) : NewString("");
337   Delete(name);
338   return extension;
339 }
340 
341 /* -----------------------------------------------------------------------------
342  * Swig_file_basename()
343  *
344  * Returns the filename with the extension removed.
345  * ----------------------------------------------------------------------------- */
346 
Swig_file_basename(const_String_or_char_ptr filename)347 String *Swig_file_basename(const_String_or_char_ptr filename) {
348   String *extension = Swig_file_extension(filename);
349   String *basename = NewStringWithSize(filename, Len(filename) - Len(extension));
350   Delete(extension);
351   return basename;
352 }
353 
354 /* -----------------------------------------------------------------------------
355  * Swig_file_filename()
356  *
357  * Return the file name with any leading path stripped off
358  * ----------------------------------------------------------------------------- */
Swig_file_filename(const_String_or_char_ptr filename)359 String *Swig_file_filename(const_String_or_char_ptr filename) {
360   const char *delim = SWIG_FILE_DELIMITER;
361   const char *c = strrchr(Char(filename), *delim);
362   return c ? NewString(c + 1) : NewString(filename);
363 }
364 
365 /* -----------------------------------------------------------------------------
366  * Swig_file_dirname()
367  *
368  * Return the name of the directory associated with a file
369  * ----------------------------------------------------------------------------- */
Swig_file_dirname(const_String_or_char_ptr filename)370 String *Swig_file_dirname(const_String_or_char_ptr filename) {
371   const char *delim = SWIG_FILE_DELIMITER;
372   const char *c = strrchr(Char(filename), *delim);
373   return c ? NewStringWithSize(filename, (int)(c - Char(filename) + 1)) : NewString("");
374 }
375 
376 /*
377  * Swig_file_debug()
378  */
Swig_file_debug_set()379 void Swig_file_debug_set() {
380   file_debug = 1;
381 }
382