$Id$ changes
[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 "files.h"
27
28 static int verbose = 0;
29 static void dbg(const char*format, ...)
30 {
31     char buf[1024];
32     int l;
33     va_list arglist;
34     if(!verbose)
35         return;
36     va_start(arglist, format);
37     vsprintf(buf, format, arglist);
38     va_end(arglist);
39     l = strlen(buf);
40     while(l && buf[l-1]=='\n') {
41         buf[l-1] = 0;
42         l--;
43     }
44     printf("(includefilehandler) ");
45     printf("%s\n", buf);
46     fflush(stdout);
47 }
48
49
50 typedef struct _include_dir {
51     char*path;
52     struct _include_dir*next;
53 } include_dir_t;
54
55 int current_line=1;
56 int current_column=0;
57 char* current_filename=0;
58 char* current_filename_short=0;
59 include_dir_t* current_include_dirs=0;
60
61 #define MAX_INCLUDE_DEPTH 16
62
63 void*include_stack[MAX_INCLUDE_DEPTH];
64 int line_stack[MAX_INCLUDE_DEPTH];
65 int column_stack[MAX_INCLUDE_DEPTH];
66 char* filename_stack[MAX_INCLUDE_DEPTH];
67 char* shortfilename_stack[MAX_INCLUDE_DEPTH];
68 include_dir_t* includedir_stack[MAX_INCLUDE_DEPTH];
69 int include_stack_ptr = 0;
70
71 void add_include_dir(char*dir)
72 {
73     include_dir_t*d = malloc(sizeof(include_dir_t));
74     memset(d , 0, sizeof(include_dir_t));
75     d->path = dir;
76     d->next = current_include_dirs;
77     current_include_dirs = d;
78 }
79 char*get_path(char*file)
80 {
81     char*path = strdup(file);
82     char*r1 = strrchr(path, '/');
83     char*r2 = strrchr(path, '\\');
84     if(r1<r2) {
85         *r2=0;
86         return path;
87     } else if(r1>r2) {
88         *r1=0;
89         return path;
90     } else {
91         return strdup(".");
92     }
93 }
94 char* concat_paths(const char*base, const char*add)
95 {
96     int l1 = strlen(base);
97     int l2 = strlen(add);
98     int pos = 0;
99     char*n = 0;
100     while(l1 && base[l1-1] == '/')
101         l1--;
102     while(pos < l2 && add[pos] == '/')
103         pos++;
104     n = (char*)malloc(l1 + (l2-pos) + 2);
105     memcpy(n,base,l1);
106     n[l1]='/';
107     memcpy(&n[l1+1],&add[pos],l2-pos+1);
108     return n;
109 }
110 char is_absolute(char*filename) 
111 {
112     if(!filename || !filename[0])
113         return 0;
114     if(filename[0]=='/' || filename[0]=='\\')
115         return 1;
116     if(filename[1]==':' && filename[1]=='/')
117         return 1;
118     if(filename[1]==':' && filename[1]=='\\')
119         return 1;
120     return 0;
121 }
122 char*find_file(char*filename)
123 {
124     include_dir_t*i = current_include_dirs;
125     FILE*fi = 0;
126     if(is_absolute(filename)) {
127         FILE*fi = fopen(filename, "rb");
128         if(fi) {
129             fclose(fi);
130             return strdup(filename);
131         }
132         return 0;
133     }
134     if(!i) {
135         as3_warning("Include directory stack is empty, while looking for file %s", filename);
136     }
137     while(i) {
138         char*p = concat_paths(i->path, filename);
139         fi = fopen(p, "rb");
140         if(fi) {
141             fclose(fi);
142             return p;
143         }
144         i = i->next;
145     }
146     return 0;
147 }
148
149 char*enter_file(char*filename, void*state)
150 {
151     filename = strdup(filename);
152
153     if(include_stack_ptr >= MAX_INCLUDE_DEPTH) {
154         as3_error("Includes nested too deeply");
155         exit(1);
156     }
157     char*fullfilename = find_file(filename);
158     if(!fullfilename) {
159         as3_error("Couldn't find file %s", filename);
160         include_dir_t*i = current_include_dirs;
161         while(i) {
162             fprintf(stderr, "include dir: %s\n", i->path);
163             i = i->next;
164         }
165         exit(1);
166     }
167     include_stack[include_stack_ptr] = state;
168     line_stack[include_stack_ptr] = current_line;
169     column_stack[include_stack_ptr] = current_column;
170     shortfilename_stack[include_stack_ptr] = current_filename_short;
171     filename_stack[include_stack_ptr] = current_filename;
172     includedir_stack[include_stack_ptr] = current_include_dirs;
173     add_include_dir(get_path(fullfilename));
174     include_stack_ptr++;
175     
176     dbg("entering file %s", fullfilename);
177
178     current_line=1;
179     current_column=0;
180     current_filename = fullfilename;
181     current_filename_short = filename;
182     return fullfilename;
183 }
184
185 void* leave_file()
186 {
187     dbg("leaving file %s", current_filename);
188     if(--include_stack_ptr<=0) {
189         return 0;
190     } else {
191         free(current_filename);current_filename = filename_stack[include_stack_ptr];
192         free(current_filename_short);current_filename_short = shortfilename_stack[include_stack_ptr];
193         current_column = column_stack[include_stack_ptr];
194         current_line = line_stack[include_stack_ptr];
195         current_include_dirs = includedir_stack[include_stack_ptr];
196         return include_stack[include_stack_ptr];
197     }
198 }