expose current_include_dirs
[swftools.git] / lib / as3 / files.c
1 /* files.c
2
3    Extension module for the rfxswf library.
4    Part of the swftools package.
5
6    Copyright (c) 2008 Matthias Kramm <kramm@quiss.org>
7  
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <stdarg.h>
25 #include <memory.h>
26 #include <errno.h>
27 #include "files.h"
28 #include "tokenizer.h"
29
30 static int verbose = 0;
31 static void dbg(const char*format, ...)
32 {
33     char buf[1024];
34     int l;
35     va_list arglist;
36     if(!verbose)
37         return;
38     va_start(arglist, format);
39     vsprintf(buf, format, arglist);
40     va_end(arglist);
41     l = strlen(buf);
42     while(l && buf[l-1]=='\n') {
43         buf[l-1] = 0;
44         l--;
45     }
46     printf("(includefilehandler) ");
47     printf("%s\n", buf);
48     fflush(stdout);
49 }
50
51
52 int current_line=1;
53 int current_column=0;
54 char* current_filename=0;
55 char* current_filename_short=0;
56 include_dir_t* current_include_dirs=0;
57
58 #define MAX_INCLUDE_DEPTH 16
59
60 void*include_stack[MAX_INCLUDE_DEPTH];
61 int line_stack[MAX_INCLUDE_DEPTH];
62 int column_stack[MAX_INCLUDE_DEPTH];
63 char* filename_stack[MAX_INCLUDE_DEPTH];
64 char* shortfilename_stack[MAX_INCLUDE_DEPTH];
65 include_dir_t* includedir_stack[MAX_INCLUDE_DEPTH];
66 int include_stack_ptr = 0;
67
68 void add_include_dir(char*dir)
69 {
70     include_dir_t*d = malloc(sizeof(include_dir_t));
71     memset(d , 0, sizeof(include_dir_t));
72     d->path = strdup(dir);
73     d->next = current_include_dirs;
74     current_include_dirs = d;
75 }
76
77 void del_include_dirs(include_dir_t*d, include_dir_t*d2)
78 {
79     while(d && d!=d2) {
80         include_dir_t*next = d->next;
81         free(d->path);d->path=0;
82         d->next = 0;
83         free(d);
84         d = next;
85     }
86 }
87
88 char*get_path(const char*file)
89 {
90     char*path = strdup(file);
91     char*r1 = strrchr(path, '/');
92     char*r2 = strrchr(path, '\\');
93     if(r1<r2) {
94         *r2=0;
95         return path;
96     } else if(r1>r2) {
97         *r1=0;
98         return path;
99     } else {
100         return strdup(".");
101     }
102 }
103 char* concat_paths(const char*base, const char*add)
104 {
105     int l1 = strlen(base);
106     int l2 = strlen(add);
107     int pos = 0;
108     char*n = 0;
109     while(l1 && base[l1-1] == '/')
110         l1--;
111     while(pos < l2 && add[pos] == '/')
112         pos++;
113     n = (char*)malloc(l1 + (l2-pos) + 2);
114     memcpy(n,base,l1);
115     n[l1]='/';
116     memcpy(&n[l1+1],&add[pos],l2-pos+1);
117     return n;
118 }
119 char is_absolute(char*filename) 
120 {
121     if(!filename || !filename[0])
122         return 0;
123     if(filename[0]=='/' || filename[0]=='\\')
124         return 1;
125     if(filename[1]==':' && filename[1]=='/')
126         return 1;
127     if(filename[1]==':' && filename[1]=='\\')
128         return 1;
129     return 0;
130 }
131
132 char*find_file(const char*filename)
133 {
134     include_dir_t*i = current_include_dirs;
135     FILE*fi = 0;
136     if(is_absolute(filename)) {
137         FILE*fi = fopen(filename, "rb");
138         if(fi) {
139             fclose(fi);
140             return strdup(filename);
141         }
142     } else {
143         if(!i) {
144             as3_warning("Include directory stack is empty, while looking for file %s", filename);
145         }
146         while(i) {
147             char*p = concat_paths(i->path, filename);
148             fi = fopen(p, "rb");
149             if(fi) {
150                 fclose(fi);
151                 return p;
152             } else {
153                 free(p);
154             }
155             i = i->next;
156         }
157     }
158
159     as3_error("Couldn't find file %s", filename);
160     i = current_include_dirs;
161     while(i) {
162         fprintf(stderr, "include dir: %s\n", i->path);
163         i = i->next;
164     }
165     return 0;
166 }
167
168 void enter_file(const char*name, const char*filename, void*state)
169 {
170     if(include_stack_ptr >= MAX_INCLUDE_DEPTH) {
171         as3_error("Includes nested too deeply");
172         exit(1);
173     }
174     include_stack[include_stack_ptr] = state;
175     line_stack[include_stack_ptr] = current_line;
176     column_stack[include_stack_ptr] = current_column;
177     shortfilename_stack[include_stack_ptr] = current_filename_short;
178     filename_stack[include_stack_ptr] = current_filename;
179     includedir_stack[include_stack_ptr] = current_include_dirs;
180     char*dir = get_path(filename);
181     add_include_dir(dir);
182     free(dir);
183     include_stack_ptr++;
184     
185     dbg("entering file %s", filename);
186
187     current_line=1;
188     current_column=0;
189     current_filename = strdup(filename);
190     current_filename_short = strdup(name);
191 }
192
193 FILE*enter_file2(const char*name, const char*filename, void*state)
194 {
195     enter_file(name, filename, state);
196     FILE*fi = fopen(filename, "rb");
197     if(!fi) {
198         as3_error("Couldn't find file %s: %s", filename, strerror(errno));
199     }
200     return fi;
201 }
202
203 void* leave_file()
204 {
205     dbg("leaving file %s", current_filename);
206     if(--include_stack_ptr<=0) {
207         return 0;
208     } else {
209         free(current_filename);current_filename = filename_stack[include_stack_ptr];
210         free(current_filename_short);current_filename_short = shortfilename_stack[include_stack_ptr];
211         current_column = column_stack[include_stack_ptr];
212         current_line = line_stack[include_stack_ptr];
213         del_include_dirs(includedir_stack[include_stack_ptr], current_include_dirs);
214         current_include_dirs = includedir_stack[include_stack_ptr];
215         return include_stack[include_stack_ptr];
216     }
217 }