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