1 /* $Id: parsefile.c,v 1.4 2002/03/02 21:02:21 sverrehu Exp $ */
2 /**************************************************************************
3 *
4 * FILE parsefile.c
5 * MODULE OF Card game.
6 *
7 * WRITTEN BY Sverre H. Huseby <shh@thathost.com>
8 *
9 **************************************************************************/
10
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <ctype.h>
15
16 #include <shhmsg.h>
17 #include <xalloc.h>
18
19 #include "parsefile.h"
20
21 /**************************************************************************
22 * *
23 * P R I V A T E D A T A *
24 * *
25 **************************************************************************/
26
27 static int lineNum;
28 static const char *fname;
29
30
31
32 /**************************************************************************
33 * *
34 * P R I V A T E F U N C T I O N S *
35 * *
36 **************************************************************************/
37
38 static void
fpFree(int argc,char ** argv)39 fpFree(int argc, char **argv)
40 {
41 int q;
42
43 for (q = 0; q < argc; q++)
44 free(argv[q]);
45 free(argv);
46 }
47
48 static int
isSplitChar(int c)49 isSplitChar(int c)
50 {
51 return (c == '=' || c == ':' || c == '#' || c == '"');
52 }
53
54 static int
fpSplitLine(const char * line,int * argc,char *** argv)55 fpSplitLine(const char *line, int *argc, char ***argv)
56 {
57 const char *from, *to;
58 char *token;
59 int tokenLen, addTo;
60
61 *argc = 0;
62 *argv = NULL;
63
64 from = to = line;
65 while (*from) {
66 addTo = 0;
67 while (isspace(*to))
68 ++to;
69 from = to;
70 if (*to == '#') {
71 break;
72 } else if (*to == '"') {
73 ++to;
74 from = to;
75 while (*to && *to != '"')
76 ++to;
77 if (!*to) {
78 msgError("unbalanced `\"' in `%s', line %d\n", fname, lineNum);
79 fpFree(*argc, *argv);
80 return -1;
81 }
82 addTo = 1;
83 } else if (isSplitChar(*to)) {
84 ++to;
85 } else
86 while (*to && !isspace(*to) && !isSplitChar(*to))
87 ++to;
88 tokenLen = to - from;
89 token = xmalloc(tokenLen + 1);
90 memcpy(token, from, tokenLen);
91 token[tokenLen] = '\0';
92 *argv = xrealloc(*argv, (*argc + 1) * sizeof(char *));
93 (*argv)[*argc] = token;
94 ++*argc;
95 to += addTo;
96 from = to;
97 }
98 return 0;
99 }
100
101 static int
pfReadLine(FILE * f,int (* func)(int argc,char * argv[]))102 pfReadLine(FILE *f, int (*func)(int argc, char *argv[]))
103 {
104 #define CHUNK_SIZE 10
105 int ret, c, len, argc;
106 char *line, **argv;
107
108 ++lineNum;
109 len = 0;
110 line = xmalloc(CHUNK_SIZE);
111 *line = '\0';
112 while ((c = getc(f)) != '\n' && c != EOF) {
113 if ((len + 1) % CHUNK_SIZE == 0)
114 line = xrealloc(line, len + 1 + CHUNK_SIZE);
115 line[len] = c;
116 line[++len] = '\0';
117 }
118 if (fpSplitLine(line, &argc, &argv) != 0) {
119 free(line);
120 return -1;
121 }
122 /* dont call handler function for empty lines */
123 ret = argc ? func(argc, argv) : 1;
124
125 free(line);
126 fpFree(argc, argv);
127
128 return ret;
129 }
130
131
132
133 /**************************************************************************
134 * *
135 * P U B L I C F U N C T I O N S *
136 * *
137 **************************************************************************/
138
139 /*-------------------------------------------------------------------------
140 *
141 * NAME pfParseFile
142 *
143 * FUNCTION
144 *
145 * SYNOPSIS #include ".h"
146 * void (void);
147 *
148 * INPUT
149 *
150 * OUTPUT
151 *
152 * RETURNS
153 *
154 * DESCRIPTION
155 *
156 */
157 int
pfParseFile(const char * filename,int (* func)(int argc,char * argv[]),int noFileOk)158 pfParseFile(const char *filename,
159 int (*func)(int argc, char *argv[]),
160 int noFileOk)
161 {
162 int ret = 0;
163 FILE *f;
164
165 if ((f = fopen(filename, "r")) == NULL) {
166 if (noFileOk)
167 return 0;
168 msgPerror(filename);
169 return -1;
170 }
171 msgVerbose(1, "reading `%s'\n", filename);
172 fname = filename;
173 lineNum = 0;
174 while (!feof(f))
175 if ((ret = pfReadLine(f, func)) <= 0)
176 break;
177 if (ret > 0)
178 ret = 0;
179 fclose(f);
180 return ret;
181 }
182
183 int
pfStrCaseCmp(const char * s1,const char * s2)184 pfStrCaseCmp(const char *s1, const char *s2)
185 {
186 int diff;
187
188 do {
189 diff = tolower(*s2++) - tolower(*s1);
190 } while (!diff && *s1++);
191 return diff;
192 }
193
194 int
pfGetCurrentLine(void)195 pfGetCurrentLine(void)
196 {
197 return lineNum;
198 }
199
200 const char *
pfGetCurrentFile(void)201 pfGetCurrentFile(void)
202 {
203 return fname;
204 }
205
206 int
pfGetBooleanValue(const char * s)207 pfGetBooleanValue(const char *s)
208 {
209 if (pfStrCaseCmp(s, "yes") == 0
210 || pfStrCaseCmp(s, "on") == 0
211 || pfStrCaseCmp(s, "true") == 0
212 || pfStrCaseCmp(s, "1") == 0)
213 return 1;
214 if (pfStrCaseCmp(s, "no") == 0
215 || pfStrCaseCmp(s, "off") == 0
216 || pfStrCaseCmp(s, "false") == 0
217 || pfStrCaseCmp(s, "0") == 0)
218 return 0;
219 msgError("illegal boolean value `%s' in `%s', line %d\n",
220 s, fname, lineNum);
221 return -1;
222 }
223
224