several bugfixes
[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 include_dir_t* current_include_dirs=0;
59
60 #define MAX_INCLUDE_DEPTH 16
61
62 void*include_stack[MAX_INCLUDE_DEPTH];
63 int line_stack[MAX_INCLUDE_DEPTH];
64 int column_stack[MAX_INCLUDE_DEPTH];
65 char* filename_stack[MAX_INCLUDE_DEPTH];
66 include_dir_t* includedir_stack[MAX_INCLUDE_DEPTH];
67 int include_stack_ptr = 0;
68
69 void add_include_dir(char*dir)
70 {
71     include_dir_t*d = malloc(sizeof(include_dir_t));
72     memset(d , 0, sizeof(include_dir_t));
73     d->path = dir;
74     d->next = current_include_dirs;
75     current_include_dirs = d;
76 }
77 char*get_path(char*file)
78 {
79     char*path = strdup(file);
80     char*r1 = strrchr(path, '/');
81     char*r2 = strrchr(path, '\\');
82     if(r1<r2) {
83         *r2=0;
84         return path;
85     } else if(r1>r2) {
86         *r1=0;
87         return path;
88     } else {
89         return strdup(".");
90     }
91 }
92 char* concat_paths(const char*base, const char*add)
93 {
94     int l1 = strlen(base);
95     int l2 = strlen(add);
96     int pos = 0;
97     char*n = 0;
98     while(l1 && base[l1-1] == '/')
99         l1--;
100     while(pos < l2 && add[pos] == '/')
101         pos++;
102     n = (char*)malloc(l1 + (l2-pos) + 2);
103     memcpy(n,base,l1);
104     n[l1]='/';
105     memcpy(&n[l1+1],&add[pos],l2-pos+1);
106     return n;
107 }
108 char is_absolute(char*filename) 
109 {
110     if(!filename || !filename[0])
111         return 0;
112     if(filename[0]=='/' || filename[0]=='\\')
113         return 1;
114     if(filename[1]==':' && filename[1]=='/')
115         return 1;
116     if(filename[1]==':' && filename[1]=='\\')
117         return 1;
118     return 0;
119 }
120 char*find_file(char*filename)
121 {
122     include_dir_t*i = current_include_dirs;
123     FILE*fi = 0;
124     if(is_absolute(filename)) {
125         FILE*fi = fopen(filename, "rb");
126         if(fi) {
127             fclose(fi);
128             return strdup(filename);
129         }
130         return 0;
131     }
132     while(i) {
133         char*p = concat_paths(i->path, filename);
134         fi = fopen(p, "rb");
135         if(fi) {
136             fclose(fi);
137             return p;
138         }
139         i = i->next;
140     }
141     return 0;
142 }
143
144 char*enter_file(char*filename, void*state)
145 {
146     if(include_stack_ptr >= MAX_INCLUDE_DEPTH) {
147         syntaxerror("Includes nested too deeply");
148         exit(1);
149     }
150     char*fullfilename = find_file(filename);
151     if(!fullfilename) {
152         syntaxerror("Couldn't find file %s", filename);
153         include_dir_t*i = current_include_dirs;
154         while(i) {
155             fprintf(stderr, "include dir: %s\n", i->path);
156             i = i->next;
157         }
158         exit(1);
159     }
160     include_stack[include_stack_ptr] = state;
161     line_stack[include_stack_ptr] = current_line;
162     column_stack[include_stack_ptr] = current_column;
163     filename_stack[include_stack_ptr] = current_filename;
164     includedir_stack[include_stack_ptr] = current_include_dirs;
165     add_include_dir(get_path(fullfilename));
166     include_stack_ptr++;
167     
168     dbg("entering file %s", fullfilename);
169
170     current_line=1;
171     current_column=0;
172     current_filename=fullfilename;
173     return fullfilename;
174 }
175
176 void* leave_file()
177 {
178     dbg("leaving file %s", current_filename);
179     if(--include_stack_ptr<0) {
180         return 0;
181     } else {
182         current_column = column_stack[include_stack_ptr];
183         current_line = line_stack[include_stack_ptr];
184         free(current_filename);current_filename=0;
185         current_filename = filename_stack[include_stack_ptr];
186         current_include_dirs = includedir_stack[include_stack_ptr];
187         return include_stack[include_stack_ptr];
188     }
189 }