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

Last change on this file since 438 was 413, checked in by Maciej Komosinski, 9 years ago

Print messages when unexpected lines are encountered in param/multiparam loaders

  • Property svn:eol-style set to native
File size: 5.3 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/log.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;
96int unexpected_line = 0;
97while (!finished())
98        {
99        if ((status==BeforeObject) || ((status==BeforeUnknown) && !lastobject.isEmpty()))
100                {
101                Param tmp_param;
102                ParamInterface *pi=lastobject.getParamInterface(tmp_param);
103                pi->load(file,true,&aborting,&linenum);
104                if ((status!=Finished) && maybeBreak(AfterObject))
105                        break;
106                unexpected_line = 0;
107                continue;
108                }
109        else if (status==BeforeUnknown)
110                {
111                logPrintf("MultiParamLoader","go",LOG_WARN,"Skipping object '%s'",lastunknown.c_str());
112                loadObjectNow(&emptyparam,false);
113                continue;
114                }
115        if (!loadSStringLine(file,buf))
116                {
117                unexpected_line = 0;
118                if (!returnFromIncluded())
119                        {
120                        abort();
121                        break;
122                        }
123                else
124                        continue;
125                }
126        linenum++;
127        if (buf[0]=='#')
128                {
129                unexpected_line = 0;
130                if (buf.startsWith("#include"))
131                        {
132                        const char* t=strchr(buf.c_str(),'\"'),*t2=0;
133                        if (t)
134                                t2=strchr(t+1,'\"');
135                        if (t2)
136                                {
137                                SString filename(t+1,t2-t-1);
138                                includeFile(filename);
139                                }
140                        else
141                                {
142                                const char* thisfilename=file->VgetPath();
143                                logPrintf("MultiParamLoader","go",LOG_WARN,"invalid \"%s\"%s%s",buf.c_str(),
144                                         (thisfilename?" in ":""),(thisfilename?thisfilename:""));
145                                }
146                        continue;
147                        }
148                else if ((status!=Finished) && maybeBreak(OnComment))
149                        {
150                        lastcomment=buf.substr(1);
151                        break;
152                        }
153                continue;
154                }
155        buf=trim(buf);
156        if (buf.len()==0)
157                unexpected_line = 0;
158        else if ((buf.len()>1)&&(buf[buf.len()-1]==':'))
159                {
160                unexpected_line = 0;
161                lastunknown=0;
162                lastunknown=buf.substr(0,buf.len()-1);
163                lastobject.setEmpty();
164                FOREACH(ExtObject*,o,objects)
165                        {
166                        if (!strcmp(o->interfaceName(),lastunknown.c_str())) {lastobject=*o; break;}
167                        }
168                        if (!lastobject.isEmpty())
169                                {
170                                if (maybeBreak(BeforeObject))
171                                        break;
172                                }
173                        else
174                                {
175                                if (maybeBreak(BeforeUnknown))
176                                        break;
177                                }
178               
179                }
180        else
181                {
182                switch(unexpected_line)
183                        {
184                        case 0:
185                        {
186                        const char* thisfilename=file->VgetPath();
187                        logPrintf("MultiParamLoader","go", LOG_WARN, "Ignored unexpected line %d%s",
188                                  linenum,
189                                  thisfilename ? SString::sprintf(" while reading '%s'",thisfilename).c_str():"");
190                        }
191                        break;
192
193                        case 1:
194                        logPrintf("MultiParamLoader","go", LOG_WARN, "The following line(s) were also unexpected and were ignored");
195                        break;
196                        }
197                unexpected_line++;
198                }
199        }
200return status;
201}
202
203bool MultiParamLoader::alreadyIncluded(const char* filename)
204{
205int i;
206const char* t;
207for(i=0;i<filestack.size();i++)
208        {
209        t=filestack(i)->VgetPath();
210        if (!t) continue;
211        if (!strcmp(filename,t)) return true;
212        }
213return false;
214}
215
216void MultiParamLoader::includeFile(SString& filename)
217{
218const char* thisfilename=file->VgetPath();
219SString newfilename;
220const char* t=thisfilename?strrchr(thisfilename,PATH_SEPARATOR_CHAR):0;
221
222if (thisfilename && t)
223        {
224        newfilename.append(thisfilename,t-thisfilename+1);
225        newfilename+=filename;
226        }
227else
228        newfilename=filename;
229
230if (alreadyIncluded(newfilename.c_str()))
231        {
232        logPrintf("MultiParamLoader","include",LOG_WARN,"circular reference ignored (\"%s\")",
233                    filename.c_str());
234        return;
235        }
236
237VirtFILE *f=Vfopen(newfilename.c_str(),FOPEN_READ_BINARY);
238if (!f)
239        {
240        logPrintf("MultiParamLoader","include",LOG_WARN,"\"%s\" not found",newfilename.c_str());
241        }
242else
243        {
244        filestack+=file;
245        file=f;
246        }
247}
248
249VirtFILE* MultiParamLoader::popstack()
250{
251if (!filestack.size()) return 0;
252VirtFILE* f=filestack(filestack.size()-1);
253filestack.remove(filestack.size()-1);
254return f;
255}
256
257void MultiParamLoader::clearstack()
258{
259VirtFILE *f;
260while(f=popstack()) fclose(f);
261}
262
263bool MultiParamLoader::returnFromIncluded()
264{
265if (!filestack.size()) return false;
266if (file) fclose(file);
267file=popstack();
268return true;
269}
270
271int MultiParamLoader::loadObjectNow(const ExtObject& o,bool warn_unknown_fields)
272{
273Param tmp_param;
274ParamInterface *pi=o.getParamInterface(tmp_param);
275pi->load(file,warn_unknown_fields,&aborting,&linenum);
276status=AfterObject;
277return 0;
278}
279
280int MultiParamLoader::run()
281{
282int stat;
283breakOn(OnError);
284while(stat=go())
285        if (stat==OnError)
286                {
287                abort();
288                return 0;
289                }
290return 1;
291}
Note: See TracBrowser for help on using the repository browser.