Mercurial > projects > ldc
comparison dmd/inifile.c @ 1:c53b6e3fe49a trunk
[svn r5] Initial commit. Most things are very rough.
author | lindquist |
---|---|
date | Sat, 01 Sep 2007 21:43:27 +0200 |
parents | |
children | 3cfcb944304e |
comparison
equal
deleted
inserted
replaced
0:a9e71648e74d | 1:c53b6e3fe49a |
---|---|
1 | |
2 // Copyright (c) 1999-2006 by Digital Mars | |
3 // All Rights Reserved | |
4 // written by Walter Bright | |
5 // http://www.digitalmars.com | |
6 | |
7 | |
8 #include <stdio.h> | |
9 #include <string.h> | |
10 #include <stdlib.h> | |
11 #include <ctype.h> | |
12 | |
13 #include "root.h" | |
14 #include "mem.h" | |
15 | |
16 #define LOG 0 | |
17 | |
18 char *skipspace(const char *p); | |
19 | |
20 #if __GNUC__ | |
21 char *strupr(char *s) | |
22 { | |
23 char *t = s; | |
24 | |
25 while (*s) | |
26 { | |
27 *s = toupper(*s); | |
28 s++; | |
29 } | |
30 | |
31 return t; | |
32 } | |
33 #endif /* unix */ | |
34 | |
35 /***************************** | |
36 * Read and analyze .ini file. | |
37 * Input: | |
38 * argv0 program name (argv[0]) | |
39 * inifile .ini file name | |
40 */ | |
41 | |
42 void inifile(char *argv0, char *inifile) | |
43 { | |
44 char *path; // need path for @P macro | |
45 char *filename; | |
46 OutBuffer buf; | |
47 int i; | |
48 int k; | |
49 int envsection = 0; | |
50 | |
51 #if LOG | |
52 printf("inifile(argv0 = '%s', inifile = '%s')\n", argv0, inifile); | |
53 #endif | |
54 if (FileName::absolute(inifile)) | |
55 { | |
56 filename = inifile; | |
57 } | |
58 else | |
59 { | |
60 /* Look for inifile in the following sequence of places: | |
61 * o current directory | |
62 * o home directory | |
63 * o directory off of argv0 | |
64 * o /etc/ | |
65 */ | |
66 if (FileName::exists(inifile)) | |
67 { | |
68 filename = inifile; | |
69 } | |
70 else | |
71 { | |
72 filename = FileName::combine(getenv("HOME"), inifile); | |
73 if (!FileName::exists(filename)) | |
74 { | |
75 filename = FileName::replaceName(argv0, inifile); | |
76 if (!FileName::exists(filename)) | |
77 { | |
78 #if linux | |
79 // Search PATH for argv0 | |
80 const char *p = getenv("PATH"); | |
81 Array *paths = FileName::splitPath(p); | |
82 filename = FileName::searchPath(paths, argv0, 0); | |
83 if (!filename) | |
84 goto Letc; // argv0 not found on path | |
85 filename = FileName::replaceName(filename, inifile); | |
86 if (FileName::exists(filename)) | |
87 goto Ldone; | |
88 #endif | |
89 | |
90 // Search /etc/ for inifile | |
91 Letc: | |
92 filename = FileName::combine("/etc/", inifile); | |
93 | |
94 Ldone: | |
95 ; | |
96 } | |
97 } | |
98 } | |
99 } | |
100 path = FileName::path(filename); | |
101 #if LOG | |
102 printf("\tpath = '%s', filename = '%s'\n", path, filename); | |
103 #endif | |
104 | |
105 File file(filename); | |
106 | |
107 if (file.read()) | |
108 return; // error reading file | |
109 | |
110 // Parse into lines | |
111 int eof = 0; | |
112 for (i = 0; i < file.len && !eof; i++) | |
113 { | |
114 int linestart = i; | |
115 | |
116 for (; i < file.len; i++) | |
117 { | |
118 switch (file.buffer[i]) | |
119 { | |
120 case '\r': | |
121 break; | |
122 | |
123 case '\n': | |
124 // Skip if it was preceded by '\r' | |
125 if (i && file.buffer[i - 1] == '\r') | |
126 goto Lskip; | |
127 break; | |
128 | |
129 case 0: | |
130 case 0x1A: | |
131 eof = 1; | |
132 break; | |
133 | |
134 default: | |
135 continue; | |
136 } | |
137 break; | |
138 } | |
139 | |
140 // The line is file.buffer[linestart..i] | |
141 char *line; | |
142 int len; | |
143 char *p; | |
144 char *pn; | |
145 | |
146 line = (char *)&file.buffer[linestart]; | |
147 len = i - linestart; | |
148 | |
149 buf.reset(); | |
150 | |
151 // First, expand the macros. | |
152 // Macros are bracketed by % characters. | |
153 | |
154 for (k = 0; k < len; k++) | |
155 { | |
156 if (line[k] == '%') | |
157 { | |
158 int j; | |
159 | |
160 for (j = k + 1; j < len; j++) | |
161 { | |
162 if (line[j] == '%') | |
163 { | |
164 if (j - k == 3 && memicmp(&line[k + 1], "@P", 2) == 0) | |
165 { | |
166 // %@P% is special meaning the path to the .ini file | |
167 p = path; | |
168 if (!*p) | |
169 p = "."; | |
170 } | |
171 else | |
172 { int len = j - k; | |
173 char tmp[10]; // big enough most of the time | |
174 | |
175 if (len <= sizeof(tmp)) | |
176 p = tmp; | |
177 else | |
178 p = (char *)alloca(len); | |
179 len--; | |
180 memcpy(p, &line[k + 1], len); | |
181 p[len] = 0; | |
182 strupr(p); | |
183 p = getenv(p); | |
184 if (!p) | |
185 p = ""; | |
186 } | |
187 buf.writestring(p); | |
188 k = j; | |
189 goto L1; | |
190 } | |
191 } | |
192 } | |
193 buf.writeByte(line[k]); | |
194 L1: | |
195 ; | |
196 } | |
197 | |
198 // Remove trailing spaces | |
199 while (buf.offset && isspace(buf.data[buf.offset - 1])) | |
200 buf.offset--; | |
201 | |
202 p = buf.toChars(); | |
203 | |
204 // The expanded line is in p. | |
205 // Now parse it for meaning. | |
206 | |
207 p = skipspace(p); | |
208 switch (*p) | |
209 { | |
210 case ';': // comment | |
211 case 0: // blank | |
212 break; | |
213 | |
214 case '[': // look for [Environment] | |
215 p = skipspace(p + 1); | |
216 for (pn = p; isalnum(*pn); pn++) | |
217 ; | |
218 if (pn - p == 11 && | |
219 memicmp(p, "Environment", 11) == 0 && | |
220 *skipspace(pn) == ']' | |
221 ) | |
222 envsection = 1; | |
223 else | |
224 envsection = 0; | |
225 break; | |
226 | |
227 default: | |
228 if (envsection) | |
229 { | |
230 pn = p; | |
231 | |
232 // Convert name to upper case; | |
233 // remove spaces bracketing = | |
234 for (p = pn; *p; p++) | |
235 { if (islower(*p)) | |
236 *p &= ~0x20; | |
237 else if (isspace(*p)) | |
238 memmove(p, p + 1, strlen(p)); | |
239 else if (*p == '=') | |
240 { | |
241 p++; | |
242 while (isspace(*p)) | |
243 memmove(p, p + 1, strlen(p)); | |
244 break; | |
245 } | |
246 } | |
247 | |
248 putenv(strdup(pn)); | |
249 #if LOG | |
250 printf("\tputenv('%s')\n", pn); | |
251 //printf("getenv(\"TEST\") = '%s'\n",getenv("TEST")); | |
252 #endif | |
253 } | |
254 break; | |
255 } | |
256 | |
257 Lskip: | |
258 ; | |
259 } | |
260 } | |
261 | |
262 /******************** | |
263 * Skip spaces. | |
264 */ | |
265 | |
266 char *skipspace(const char *p) | |
267 { | |
268 while (isspace(*p)) | |
269 p++; | |
270 return (char *)p; | |
271 } | |
272 |