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