10e5de6e04a75ff96f797a1c02758b58943e341b
[swftools.git] / 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     while(i) {
135         char*p = concat_paths(i->path, filename);
136         fi = fopen(p, "rb");
137         if(fi) {
138             fclose(fi);
139             return p;
140         }
141         i = i->next;
142     }
143     return 0;
144 }
145
146 char*enter_file(char*filename, void*state)
147 {
148     if(include_stack_ptr >= MAX_INCLUDE_DEPTH) {
149         syntaxerror("Includes nested too deeply");
150         exit(1);
151     }
152     char*fullfilename = find_file(filename);
153     if(!fullfilename) {
154         syntaxerror("Couldn't find file %s", filename);
155         include_dir_t*i = current_include_dirs;
156         while(i) {
157             fprintf(stderr, "include dir: %s\n", i->path);
158             i = i->next;
159         }
160         exit(1);
161     }
162     include_stack[include_stack_ptr] = state;
163     line_stack[include_stack_ptr] = current_line;
164     column_stack[include_stack_ptr] = current_column;
165     shortfilename_stack[include_stack_ptr] = current_filename_short = strdup(filename);
166     filename_stack[include_stack_ptr] = current_filename;
167     includedir_stack[include_stack_ptr] = current_include_dirs;
168     add_include_dir(get_path(fullfilename));
169     include_stack_ptr++;
170     
171     dbg("entering file %s", fullfilename);
172
173     current_line=1;
174     current_column=0;
175     current_filename=fullfilename;
176     return fullfilename;
177 }
178
179 void* leave_file()
180 {
181     dbg("leaving file %s", current_filename);
182     if(--include_stack_ptr<0) {
183         return 0;
184     } else {
185         current_column = column_stack[include_stack_ptr];
186         current_line = line_stack[include_stack_ptr];
187         free(current_filename);current_filename = filename_stack[include_stack_ptr];
188         free(current_filename_short);current_filename_short = shortfilename_stack[include_stack_ptr];
189         current_include_dirs = includedir_stack[include_stack_ptr];
190         return include_stack[include_stack_ptr];
191     }
192 }