Subversion Repositories spk

Rev

Rev 1 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1 Rev 114
Line 3... Line 3...
3
 
3
 
4
#include <stdio.h>
4
#include <stdio.h>
5
#include <windows.h>
5
#include <windows.h>
6
 
6
 
7
static Settings *g_settings;
7
static Settings *g_settings;
8
//---------------------------------------------------------------------------------
-
 
9
#ifdef X2BC_USE_INI_FORMATS 
-
 
10
bool settings_parse_pair_const(const char *pszSectionName, Settings::conststringpair &p)
-
 
11
{
-
 
12
	return g_settings->parseConstant(pszSectionName, p);
-
 
13
}
-
 
14
//---------------------------------------------------------------------------------
-
 
15
bool settings_parse_pair_format(const char *pszSectionName, Settings::conststringpair &p)
-
 
16
{
-
 
17
	return g_settings->parseFormat(pszSectionName, p);
-
 
18
}
-
 
19
//---------------------------------------------------------------------------------
-
 
20
int CompareStatFormats(const void *a, const void *b)
-
 
21
{
-
 
22
	int ida, idb;
-
 
23
	ida=((Settings::StatFormat*)a)->id;
-
 
24
	idb=((Settings::StatFormat*)b)->id;
-
 
25
	
-
 
26
	return ((Settings::StatFormat*)a)->id - ((Settings::StatFormat*)b)->id;
-
 
27
}
-
 
28
#endif // defined(X2BC_USE_INI_FORMATS )
-
 
29
//---------------------------------------------------------------------------------
8
//---------------------------------------------------------------------------------
30
bool Settings::loadINI(const char *pszFileName)
9
bool Settings::loadINI(const char *pszFileName)
31
{
10
{
32
	bool bRes;
-
 
33
	char szSectionName[50];
11
	char szSectionName[50];
34
	
12
	
35
	g_settings=this;
13
	g_settings=this;
36
	clearErrors();
14
	clearErrors();
37
	
15
	
38
	GetPrivateProfileString(L"library", L"WriteWarnings", L"off", (LPWSTR)szSectionName, sizeof(szSectionName), (LPCWSTR)pszFileName);
16
	GetPrivateProfileStringA("library", "WriteWarnings", "off", szSectionName, sizeof(szSectionName), pszFileName);
39
	m_bOutputWarnings=(_stricmp(szSectionName, "on")==0);
17
	m_bOutputWarnings = (_stricmp(szSectionName, "on")==0);
40
	
18
	
41
	GetPrivateProfileString(L"library", L"Convert", L"on", (LPWSTR)szSectionName, sizeof(szSectionName), (LPCWSTR)pszFileName);
19
	GetPrivateProfileStringA("library", "Convert", "on", szSectionName, sizeof(szSectionName), pszFileName);
42
	m_bConvert=(_stricmp(szSectionName, "on")==0);
20
	m_bRawMode =! (_stricmp(szSectionName, "on")==0);
43
	
-
 
44
	GetPrivateProfileString(L"library", L"FrameWarnings", L"on", (LPWSTR)szSectionName, sizeof(szSectionName), (LPCWSTR)pszFileName);
-
 
45
	m_bStatFormatWarnings=(_stricmp(szSectionName, "on")==0);
-
 
46
	
21
	
47
	GetPrivateProfileString(L"library", L"XtraPointInfo", L"on", (LPWSTR)szSectionName, sizeof(szSectionName), (LPCWSTR)pszFileName);
22
	GetPrivateProfileStringA("library", "XtraPointInfo", "on", szSectionName, sizeof(szSectionName), pszFileName);
48
	m_bXtraPntInfo=(_stricmp(szSectionName, "on")==0);
23
	m_bXtraPntInfo = (_stricmp(szSectionName, "on")==0);
49
	
24
	
50
	GetPrivateProfileString(L"library", L"XtraX3BobInfo", L"off", (LPWSTR)szSectionName, sizeof(szSectionName), (LPCWSTR)pszFileName);
25
	GetPrivateProfileStringA("library", "WriteX3Data", "on", szSectionName, sizeof(szSectionName), pszFileName);
51
	m_bXtraX3BobInfo=(_stricmp(szSectionName, "on")==0);
26
	m_bWriteX3Data = (_stricmp(szSectionName, "on")==0);
52
	
-
 
53
#ifdef X2BC_USE_INI_FORMATS
-
 
54
	size_t size;
-
 
55
	
-
 
56
	GetPrivateProfileString("library", "Constants", "Const", szSectionName, sizeof(szSectionName), pszFileName);
-
 
57
	
-
 
58
	char *pszConstants=readSection(szSectionName, pszFileName, &size);
-
 
59
	if(size==0){
-
 
60
		error(Error, E_SectionEmpty, "Section with constants '%s' not defined or empty.", szSectionName);
-
 
61
		bRes=false;
-
 
62
	}
-
 
63
	else
-
 
64
		bRes=parseLines(szSectionName, pszConstants, size, settings_parse_pair_const);
-
 
65
		
-
 
66
	delete[] pszConstants;
-
 
67
	
27
	
68
	if(bRes){
-
 
69
		GetPrivateProfileString("library", "Default", "Format", szSectionName, sizeof(szSectionName), pszFileName);
-
 
70
		char *pszFormat=readSection(szSectionName, pszFileName, &size);
-
 
71
		if(size==0){
-
 
72
			error(Error, E_SectionEmpty, "Section with frame formats '%s' not defined or empty.", szSectionName);
-
 
73
			bRes=false;
-
 
74
		}
-
 
75
		else
-
 
76
			bRes=parseLines(szSectionName, pszFormat, size, settings_parse_pair_format);
-
 
77
 
-
 
78
		delete[] pszFormat;
-
 
79
	}
-
 
80
#else
-
 
81
	bRes=true;
-
 
82
#endif // !defined(X2BC_USE_INI_FORMATS)
-
 
83
	return bRes;
28
	return true;
84
}
29
}
85
//---------------------------------------------------------------------------------
30
//---------------------------------------------------------------------------------
86
void Settings::error(ErrorType type, ErrorCodes code, const char *format, ...)
31
void Settings::error(ErrorType type, ErrorCodes code, const char *format, ...)
87
{
32
{
88
	va_list ap;
33
	va_list ap;
89
	va_start(ap, format);
34
	va_start(ap, format);
90
	
35
	
Line 96... Line 41...
96
	va_end(ap);
41
	va_end(ap);
97
	
42
	
98
	errors.push_back(e);
43
	errors.push_back(e);
99
}
44
}
100
//---------------------------------------------------------------------------------
45
//---------------------------------------------------------------------------------
101
 
-
 
102
#ifdef X2BC_USE_INI_FORMATS
-
 
103
char * Settings::readSection(const char *pszSection, const char *pszFileName, size_t *size)
-
 
104
{
-
 
105
	char *data;
-
 
106
	int _size=0, res;
-
 
107
	
-
 
108
	do{
-
 
109
		_size+=1500;
-
 
110
		data=new char[_size];
-
 
111
		if(data==NULL) break;
-
 
112
		res=GetPrivateProfileSection(pszSection, data, _size, pszFileName);
-
 
113
		if(res==_size - 2){
-
 
114
			delete[] data;
-
 
115
		}
-
 
116
	}
-
 
117
	while(res==_size - 2);
-
 
118
	if(size) *size=res;
-
 
119
	return data;
-
 
120
}
-
 
121
//---------------------------------------------------------------------------------
-
 
122
bool Settings::parseLines(const char *pszSectionName, char *pszData, size_t size, ParsePairCallback *callback)
-
 
123
{
-
 
124
	size_t count;
-
 
125
	char **lines=lineexplode(pszData, size, &count);
-
 
126
	bool bRes=true;
-
 
127
	
-
 
128
	for(size_t i=0; i < count; i++){
-
 
129
		char *line=lines[i];
-
 
130
	
-
 
131
		int j=0;
-
 
132
		bool bComment=false;
-
 
133
		char *equal, *left, *right;
-
 
134
		
-
 
135
		left=right=equal=0;
-
 
136
		
-
 
137
		while(line[j]!=0){
-
 
138
			switch(line[j]){
-
 
139
				case '=':
-
 
140
					line[j]=0;
-
 
141
					equal=line + j;
-
 
142
					left=line;
-
 
143
					break;
-
 
144
				case ';':
-
 
145
					line[j]=0;
-
 
146
					j--; // so the main while(...) will encouter this added 0 and terminate
-
 
147
					break;
-
 
148
			}
-
 
149
			j++;
-
 
150
		}
-
 
151
		if(equal){
-
 
152
			right=equal + 1;
-
 
153
		
-
 
154
			conststringpair p=parsePair(left, right);
-
 
155
			if(callback(pszSectionName, p)==false) {
-
 
156
				bRes=false;
-
 
157
				break; // break if parsing fails
-
 
158
			}
-
 
159
		}
-
 
160
		else
-
 
161
			error(Warning, W_LineIgnored, "Section \"%s\": line '%s' ignored.", pszSectionName, line);
-
 
162
	}
-
 
163
	
-
 
164
	delete[] lines;
-
 
165
	return bRes;
-
 
166
}
-
 
167
//---------------------------------------------------------------------------------
-
 
168
// trim white spaces from left and right
-
 
169
Settings::conststringpair Settings::parsePair(const char *left, const char *right)
-
 
170
{
-
 
171
	conststringpair p;
-
 
172
	p.left=trim((char*)left);
-
 
173
	p.right=trim((char*)right);
-
 
174
	return p;
-
 
175
}
-
 
176
//---------------------------------------------------------------------------------
-
 
177
bool Settings::parseConstant(const char *pszSectionName, Settings::conststringpair &p)
-
 
178
{
-
 
179
	bool res=true;
-
 
180
	NumberFormat *f=new NumberFormat();
-
 
181
	const char *pszMultiplier=0, *pszFormat=0;
-
 
182
	char *left, *right;
-
 
183
	
-
 
184
	// backup the original strings for error reporting
-
 
185
	size_t len=strlen(p.left);
-
 
186
	left=new char[len + 1];
-
 
187
	memcpy(left, p.left, len + 1);
-
 
188
	len=strlen(p.right);
-
 
189
	right=new char[len + 1];
-
 
190
	memcpy(right, p.right, len + 1);
-
 
191
	
-
 
192
	// the left operand (constant name)
-
 
193
	if(*p.left==0){
-
 
194
		error(ErrorType::Error, E_BadConstantDeclaration, "Section \"%s\": line: '%s = %s':\nMissing constant name.", pszSectionName, left, right);
-
 
195
		res=false;
-
 
196
	}
-
 
197
	else if(strlen(p.left) > 1){
-
 
198
		error(ErrorType::Error, E_BadConstantDeclaration, "Section \"%s\": line: '%s = %s':\nConstant name must be exactly 1 character.", pszSectionName, left, right);
-
 
199
		res=false;
-
 
200
	}
-
 
201
	else if(!((*p.left | 0x20) > 'a') && ((*p.left | 0x20) < 'z')){
-
 
202
		error(Error, E_BadConstantDeclaration, "Section \"%s\": Constant \"%c\": constant name must be a upper or lowercase character (A - Z).", pszSectionName, *p.left);
-
 
203
		res=false;
-
 
204
	}
-
 
205
	if(res==false){
-
 
206
		delete[] left; delete[] right;
-
 
207
		return res;
-
 
208
	}
-
 
209
	f->type=*p.left;
-
 
210
	
-
 
211
	// the right operand (constant multiplier and format)
-
 
212
	pszMultiplier=p.right;
-
 
213
	char *pos=strchr(p.right, ',');
-
 
214
	if(pos){
-
 
215
		*pos=0;
-
 
216
		pszFormat=trim(++pos);
-
 
217
	}	
-
 
218
	if(pszMultiplier==0 || *pszMultiplier==0){
-
 
219
		error(ErrorType::Error, E_BadConstantDeclaration, "Section \"%s\": line: '%s = %s':\nMissing constant multiplier.", pszSectionName, left, right);
-
 
220
		res=false;
-
 
221
	}
-
 
222
	else if(pszFormat==0 || *pszFormat==0){	
-
 
223
		error(ErrorType::Error, E_BadConstantDeclaration, "Section \"%s\": line: '%s = %s':\nMissing output format specifier.", pszSectionName, left, right);
-
 
224
		res=false;
-
 
225
	}
-
 
226
	else{
-
 
227
		f->multiplier=atof(pszMultiplier);
-
 
228
		if(f->multiplier==0){
-
 
229
			error(ErrorType::Warning, W_ConstantAlwaysZero, "Section \"%s\": line: '%s = %s':\nMultiplier is 0. Result will be always zero. Is this the intent?", pszSectionName, left, right);
-
 
230
		}
-
 
231
	}
-
 
232
	if(res==true){
-
 
233
		if(stricmp(pszFormat, "integer")==0)
-
 
234
			f->outformat=NumberFormat::Integer;
-
 
235
		else if(stricmp(pszFormat, "float")==0)
-
 
236
			f->outformat=NumberFormat::Float;
-
 
237
		else{
-
 
238
			error(ErrorType::Error, E_BadConstantDeclaration, "Section \"%s\": line: '%s = %s':\nUnknown output format '%s'.", pszSectionName, left, right, pszFormat);
-
 
239
			res=false;
-
 
240
		}
-
 
241
	}
-
 
242
	delete[] left;
-
 
243
	delete[] right;
-
 
244
	
-
 
245
	if(res)
-
 
246
		m_constants.push_back(f);
-
 
247
	
-
 
248
	return res;
-
 
249
}
-
 
250
//---------------------------------------------------------------------------------
-
 
251
bool Settings::parseFormat(const char *pszSectionName, conststringpair &p)
-
 
252
{
-
 
253
	bool bRes;
-
 
254
	switch(p.left[0]){
-
 
255
		case 0:
-
 
256
			error(ErrorType::Error, E_BadFormatDeclaration, "Section \"%s\": invalid line format: '%s = %s':\nID expected.", pszSectionName, p.left, p.right);
-
 
257
			bRes=false;
-
 
258
			break;
-
 
259
		case '$':
-
 
260
			bRes=parseStatFormat(pszSectionName, p);
-
 
261
			break;
-
 
262
		case 'N': // don't read the N constants - we use algorithm instead if INI
-
 
263
			bRes=true;
-
 
264
			break;
-
 
265
		default:
-
 
266
			error(Warning, W_LineIgnored, "Section \"%s\": ignoring line '%s = %s':\nUnknown ID type.", pszSectionName, p.left, p.right);
-
 
267
			bRes=true;
-
 
268
		
-
 
269
	}
-
 
270
	return bRes;
-
 
271
}
-
 
272
//---------------------------------------------------------------------------------
-
 
273
bool Settings::parseStatFormat(const char *pszSectionName, conststringpair &p)
-
 
274
{
-
 
275
	char *left, *right;
-
 
276
	bool bRes=true;
-
 
277
	// backup the original strings for error reporting
-
 
278
	size_t len=strlen(p.left);
-
 
279
	left=new char[len + 1];
-
 
280
	memcpy(left, p.left, len + 1);
-
 
281
	len=strlen(p.right);
-
 
282
	right=new char[len + 1];
-
 
283
	memcpy(right, p.right, len + 1);
-
 
284
	
-
 
285
	StatFormat *f=new StatFormat();
-
 
286
	
-
 
287
	if(p.left[0]==0){
-
 
288
		error(ErrorType::Error, E_BadFormatDeclaration, "Section \"%s\": line '%s = %s':\nMissing ID.", pszSectionName, left, right);
-
 
289
		bRes=false;
-
 
290
	}
-
 
291
	else{
-
 
292
		if(p.left[0]=='$') p.left++;
-
 
293
		f->id=hextoi(p.left);
-
 
294
	}
-
 
295
	if(bRes){
-
 
296
		char *ch=(char*)p.right;
-
 
297
		if(*ch!='"'){
-
 
298
			error(ErrorType::Error, E_BadFormatDeclaration, "Section \"%s\": line '%s = %s':\nExpected begining of string after \"%s =\".", pszSectionName, left, right, left);
-
 
299
			bRes=false;
-
 
300
		}
-
 
301
		else{
-
 
302
			ch++;
-
 
303
			while(*ch!=0 && *ch!='"') ch++;
-
 
304
			if(*ch==0){
-
 
305
				error(ErrorType::Error, E_BadFormatDeclaration, "Section \"%s\": line '%s = %s':\nExpected end of string after \"%s\".", pszSectionName, left, right, right);
-
 
306
				bRes=false;
-
 
307
			}
-
 
308
			else{
-
 
309
				*ch=0;
-
 
310
				bRes=parseFormatString(pszSectionName, f, (char*)p.right + 1);
-
 
311
				if(bRes) formats.push_back(f);
-
 
312
			}
-
 
313
		}
-
 
314
	}
-
 
315
	
-
 
316
	return bRes;
-
 
317
}
-
 
318
//---------------------------------------------------------------------------------
-
 
319
bool isnum(char c)
-
 
320
{
-
 
321
	return (c >= '0' && c <= '9');
-
 
322
}
-
 
323
//---------------------------------------------------------------------------------
-
 
324
bool Settings::parseFormatString(const char *pszSectionName, Settings::StatFormat *f, char *format)
-
 
325
{
-
 
326
	bool bRes=true;
-
 
327
	
-
 
328
	char *ch, *start;
-
 
329
	start=format;
-
 
330
	
-
 
331
	// if format begins with - a warning will be issued if such format is used in bob file
-
 
332
	if(*start!=0 && *start=='-') {
-
 
333
		start++;
-
 
334
		f->issueWarning=true;
-
 
335
	}
-
 
336
	// skip any spaces after the '-'
-
 
337
	while(*start==' ') start++;
-
 
338
	
-
 
339
	while(*start!=0){
-
 
340
		ch=start;
-
 
341
		if(isnum(*ch)==false){
-
 
342
			error(Error, E_BadFormatDeclaration, "Section \"%s\": line id $%x:\nMissing number at start of '%s'.", pszSectionName, f->id, format);
-
 
343
			return false;
-
 
344
		}
-
 
345
		else{
-
 
346
			while(isnum(*ch)) ch++;
-
 
347
			if(*ch==0){
-
 
348
				error(Error, E_BadFormatDeclaration, "Section \"%s\": line id $%x:\nMissing constant after '%s'.", pszSectionName, f->id, ch);
-
 
349
				return false;
-
 
350
			}
-
 
351
			else{
-
 
352
				StatFormat::token *t=new StatFormat::token();
-
 
353
				char old=*ch;
-
 
354
				*ch=0;
-
 
355
				t->count=atoi(start);
-
 
356
				t->type=old;
-
 
357
				*ch=old;
-
 
358
				
-
 
359
				t->numFormat=findNumberFormat(t->type);
-
 
360
				if(t->numFormat==0){
-
 
361
					error(Error, E_BadFormatDeclaration, "Section \"%s\": line id $%x:\nConstant \"%c\" not defined in '%s'.", pszSectionName, f->id, t->type, format);
-
 
362
					delete t;
-
 
363
					return false;
-
 
364
				}
-
 
365
				f->tokens.push_back(t);
-
 
366
				// increase the cumulative count so it's easy to tell how many numbers is needed 
-
 
367
				// to match the format
-
 
368
				f->cumulativeTokenCount+=t->count; 
-
 
369
				
-
 
370
				start=ch+1;
-
 
371
				while(*ch!=0 && isnum(*ch)==false) ch++;
-
 
372
				old=*ch;
-
 
373
				*ch=0;
-
 
374
				size_t size=ch-start;
-
 
375
				if(size){
-
 
376
					t->data=new char[size + 1];
-
 
377
					memcpy(t->data, start, size + 1);
-
 
378
				}
-
 
379
				*ch=old;
-
 
380
				start=ch;
-
 
381
			}
-
 
382
		}
-
 
383
	}
-
 
384
	return bRes;
-
 
385
}
-
 
386
//---------------------------------------------------------------------------------
-
 
387
Settings::NumberFormat * Settings::findNumberFormat(char ch)
-
 
388
{
-
 
389
	char c;
-
 
390
	for(NumberFormatList::iterator &it=m_constants.begin(); it!=m_constants.end(); ++it){
-
 
391
		c=it->type;
-
 
392
		if(c==ch) return *it;
-
 
393
	}
-
 
394
	return NULL;
-
 
395
}
-
 
396
//---------------------------------------------------------------------------------
-
 
397
#endif // defined(X2BC_USE_INI_FORMATS)
-