source: cpp/gdk/multiparamload.cpp @ 97

Last change on this file since 97 was 81, checked in by Maciej Komosinski, 12 years ago

improved parsing of properties (e.g. in f0 genotypes)

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