source: cpp/frams/param/multiparamload.cpp @ 339

Last change on this file since 339 was 333, checked in by Maciej Komosinski, 10 years ago
  • use source/code mapping for line number and file information in vm error messages
  • enum ExtValue::CompareResult? instead of int
  • Property svn:eol-style set to native
File size: 4.7 KB
Line 
1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
4
5#include "multiparamload.h"
6#include <frams/util/sstringutils.h>
7#include "common/framsg.h"
8#include <ctype.h>
9
10void MultiParamLoader::init()
11{
12file=0; ownfile=0;
13status=0;
14reset();
15}
16
17void MultiParamLoader::reset()
18{
19status=0;
20breakcond=OnError;
21aborting=false;
22emptyparam.setParamTab(empty_paramtab);
23linenum=0;
24}
25
26int MultiParamLoader::findObject(const ExtObject &o)
27{
28for(int i=0;i<objects.size();i++)
29        if ((*objects(i))==o)
30                return i;
31return -1;
32}
33
34void MultiParamLoader::removeObject(const ExtObject &o)
35{
36int i=findObject(o);
37if (i>=0)
38        {
39        delete objects(i);
40        objects-=i;
41        }
42}
43
44void MultiParamLoader::clearObjects()
45{
46FOREACH(ExtObject*,o,objects)
47        delete o;
48objects.clear();
49}
50
51void MultiParamLoader::load()
52{
53clearstack();
54if (!file)
55        {
56        lasterror="can't open file";
57        status=OnError;
58        return;
59        }
60status=Loading;
61aborting=false;
62}
63
64void MultiParamLoader::abort()
65{
66if (file && ownfile)
67        {
68        fclose(file);
69        file=0;
70        }
71clearstack();
72status=Finished;
73aborting=true;
74}
75
76void MultiParamLoader::load(VirtFILE *f)
77{
78abort();
79ownfile=0;
80file=f;
81load();
82}
83
84void MultiParamLoader::load(const char* filename)
85{
86abort();
87ownfile=1;
88file=Vfopen(filename,FOPEN_READ_BINARY);
89load();
90}
91
92int MultiParamLoader::go()
93{
94SString buf;
95if (status==OnError) return status;
96while (!finished())
97        {
98        if ((status==BeforeObject) || ((status==BeforeUnknown) && !lastobject.isEmpty()))
99                {
100                Param tmp_param;
101                ParamInterface *pi=lastobject.getParamInterface(tmp_param);
102                pi->load(file,true,&aborting,&linenum);
103                if ((status!=Finished) && maybeBreak(AfterObject))
104                        break;
105                continue;
106                }
107        else if (status==BeforeUnknown)
108                {
109                FMprintf("MultiParamLoader","go",FMLV_WARN,"Skipping object '%s'",(const char*)lastunknown);
110                loadObjectNow(&emptyparam,false);
111                continue;
112                }
113        if (!loadSStringLine(file,buf))
114                {
115                if (!returnFromIncluded())
116                        {
117                        abort();
118                        break;
119                        }
120                else
121                        continue;
122                }
123        linenum++;
124        if (buf[0]=='#')
125                {
126                if (buf.startsWith("#include"))
127                        {
128                        const char* t=strchr((const char*)buf,'\"'),*t2=0;
129                        if (t)
130                                t2=strchr(t+1,'\"');
131                        if (t2)
132                                {
133                                SString filename(t+1,t2-t-1);
134                                includeFile(filename);
135                                }
136                        else
137                                {
138                                const char* thisfilename=file->VgetPath();
139                                FMprintf("MultiParamLoader","go",FMLV_WARN,"invalid \"%s\"%s%s",(const char*)buf,
140                                         (thisfilename?" in ":""),(thisfilename?thisfilename:""));
141                                }
142                        continue;
143                        }
144                else if ((status!=Finished) && maybeBreak(OnComment))
145                        {
146                        lastcomment=buf.substr(1);
147                        break;
148                        }
149                continue;
150                }
151        buf=trim(buf);
152        if ((buf.len()>1)&&(buf[buf.len()-1]==':'))
153                {
154                lastunknown=0;
155                lastunknown=buf.substr(0,buf.len()-1);
156                lastobject.setEmpty();
157                FOREACH(ExtObject*,o,objects)
158                        {
159                        if (!strcmp(o->interfaceName(),lastunknown)) {lastobject=*o; break;}
160                        }
161                        if (!lastobject.isEmpty())
162                                {
163                                if (maybeBreak(BeforeObject))
164                                        break;
165                                }
166                        else
167                                {
168                                if (maybeBreak(BeforeUnknown))
169                                        break;
170                                }
171               
172                }
173        }
174return status;
175}
176
177bool MultiParamLoader::alreadyIncluded(const char* filename)
178{
179int i;
180const char* t;
181for(i=0;i<filestack.size();i++)
182        {
183        t=filestack(i)->VgetPath();
184        if (!t) continue;
185        if (!strcmp(filename,t)) return true;
186        }
187return false;
188}
189
190void MultiParamLoader::includeFile(SString& filename)
191{
192const char* thisfilename=file->VgetPath();
193SString newfilename;
194const char* t=thisfilename?strrchr(thisfilename,PATH_SEPARATOR_CHAR):0;
195
196if (thisfilename && t)
197        {
198        newfilename.append(thisfilename,t-thisfilename+1);
199        newfilename+=filename;
200        }
201else
202        newfilename=filename;
203
204if (alreadyIncluded(newfilename))
205        {
206        FMprintf("MultiParamLoader","include",FMLV_WARN,"circular reference ignored (\"%s\")",
207                    (const char*)filename);
208        return;
209        }
210
211VirtFILE *f=Vfopen(newfilename,FOPEN_READ_BINARY);
212if (!f)
213        {
214        FMprintf("MultiParamLoader","include",FMLV_WARN,"\"%s\" not found",(const char*)newfilename);
215        }
216else
217        {
218        filestack+=file;
219        file=f;
220        }
221}
222
223VirtFILE* MultiParamLoader::popstack()
224{
225if (!filestack.size()) return 0;
226VirtFILE* f=filestack(filestack.size()-1);
227filestack.remove(filestack.size()-1);
228return f;
229}
230
231void MultiParamLoader::clearstack()
232{
233VirtFILE *f;
234while(f=popstack()) fclose(f);
235}
236
237bool MultiParamLoader::returnFromIncluded()
238{
239if (!filestack.size()) return false;
240if (file) fclose(file);
241file=popstack();
242return true;
243}
244
245int MultiParamLoader::loadObjectNow(const ExtObject& o,bool warn_unknown_fields)
246{
247Param tmp_param;
248ParamInterface *pi=o.getParamInterface(tmp_param);
249pi->load(file,warn_unknown_fields,&aborting,&linenum);
250status=AfterObject;
251return 0;
252}
253
254int MultiParamLoader::run()
255{
256int stat;
257breakOn(OnError);
258while(stat=go())
259        if (stat==OnError)
260                {
261                abort();
262                return 0;
263                }
264return 1;
265}
Note: See TracBrowser for help on using the repository browser.