Mercurial > projects > ldc
annotate dmd/inifile.c @ 86:fd32135dca3e trunk
[svn r90] Major updates to the gen directory. Redesigned the 'elem' struct. Much more... !!!
Lots of bugfixes.
Added support for special foreach on strings.
Added std.array, std.utf, std.ctype and std.uni to phobos.
Changed all the .c files in the gen dir to .cpp (it *is* C++ after all)
author | lindquist |
---|---|
date | Sat, 03 Nov 2007 14:44:58 +0100 |
parents | 3cfcb944304e |
children | 297690b5d4a5 |
rev | line source |
---|---|
1 | 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 | |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
79 |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
80 #if 0 |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
81 #if __GLIBC__ // This fix by Thomas Kuehne |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
82 /* argv0 might be a symbolic link, |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
83 * so try again looking past it to the real path |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
84 */ |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
85 char* real_argv0 = realpath(argv0, NULL); |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
86 if (real_argv0) |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
87 { |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
88 filename = FileName::replaceName(real_argv0, inifile); |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
89 free(real_argv0); |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
90 if (FileName::exists(filename)) |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
91 goto Ldone; |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
92 } |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
93 #else |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
94 #error use of glibc non-standard extension realpath(char*, NULL) |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
95 #endif |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
96 #endif |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
97 |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
98 // old way; problem is that argv0 might not be on the PATH at all |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
99 // and some other instance might be found |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
100 |
1 | 101 // Search PATH for argv0 |
102 const char *p = getenv("PATH"); | |
103 Array *paths = FileName::splitPath(p); | |
104 filename = FileName::searchPath(paths, argv0, 0); | |
105 if (!filename) | |
106 goto Letc; // argv0 not found on path | |
107 filename = FileName::replaceName(filename, inifile); | |
108 if (FileName::exists(filename)) | |
109 goto Ldone; | |
110 #endif | |
111 | |
112 // Search /etc/ for inifile | |
113 Letc: | |
114 filename = FileName::combine("/etc/", inifile); | |
115 | |
116 Ldone: | |
117 ; | |
118 } | |
119 } | |
120 } | |
121 } | |
122 path = FileName::path(filename); | |
123 #if LOG | |
124 printf("\tpath = '%s', filename = '%s'\n", path, filename); | |
125 #endif | |
126 | |
127 File file(filename); | |
128 | |
129 if (file.read()) | |
130 return; // error reading file | |
131 | |
132 // Parse into lines | |
133 int eof = 0; | |
134 for (i = 0; i < file.len && !eof; i++) | |
135 { | |
136 int linestart = i; | |
137 | |
138 for (; i < file.len; i++) | |
139 { | |
140 switch (file.buffer[i]) | |
141 { | |
142 case '\r': | |
143 break; | |
144 | |
145 case '\n': | |
146 // Skip if it was preceded by '\r' | |
147 if (i && file.buffer[i - 1] == '\r') | |
148 goto Lskip; | |
149 break; | |
150 | |
151 case 0: | |
152 case 0x1A: | |
153 eof = 1; | |
154 break; | |
155 | |
156 default: | |
157 continue; | |
158 } | |
159 break; | |
160 } | |
161 | |
162 // The line is file.buffer[linestart..i] | |
163 char *line; | |
164 int len; | |
165 char *p; | |
166 char *pn; | |
167 | |
168 line = (char *)&file.buffer[linestart]; | |
169 len = i - linestart; | |
170 | |
171 buf.reset(); | |
172 | |
173 // First, expand the macros. | |
174 // Macros are bracketed by % characters. | |
175 | |
176 for (k = 0; k < len; k++) | |
177 { | |
178 if (line[k] == '%') | |
179 { | |
180 int j; | |
181 | |
182 for (j = k + 1; j < len; j++) | |
183 { | |
184 if (line[j] == '%') | |
185 { | |
186 if (j - k == 3 && memicmp(&line[k + 1], "@P", 2) == 0) | |
187 { | |
188 // %@P% is special meaning the path to the .ini file | |
189 p = path; | |
190 if (!*p) | |
191 p = "."; | |
192 } | |
193 else | |
194 { int len = j - k; | |
195 char tmp[10]; // big enough most of the time | |
196 | |
197 if (len <= sizeof(tmp)) | |
198 p = tmp; | |
199 else | |
200 p = (char *)alloca(len); | |
201 len--; | |
202 memcpy(p, &line[k + 1], len); | |
203 p[len] = 0; | |
204 strupr(p); | |
205 p = getenv(p); | |
206 if (!p) | |
207 p = ""; | |
208 } | |
209 buf.writestring(p); | |
210 k = j; | |
211 goto L1; | |
212 } | |
213 } | |
214 } | |
215 buf.writeByte(line[k]); | |
216 L1: | |
217 ; | |
218 } | |
219 | |
220 // Remove trailing spaces | |
221 while (buf.offset && isspace(buf.data[buf.offset - 1])) | |
222 buf.offset--; | |
223 | |
224 p = buf.toChars(); | |
225 | |
226 // The expanded line is in p. | |
227 // Now parse it for meaning. | |
228 | |
229 p = skipspace(p); | |
230 switch (*p) | |
231 { | |
232 case ';': // comment | |
233 case 0: // blank | |
234 break; | |
235 | |
236 case '[': // look for [Environment] | |
237 p = skipspace(p + 1); | |
238 for (pn = p; isalnum(*pn); pn++) | |
239 ; | |
240 if (pn - p == 11 && | |
241 memicmp(p, "Environment", 11) == 0 && | |
242 *skipspace(pn) == ']' | |
243 ) | |
244 envsection = 1; | |
245 else | |
246 envsection = 0; | |
247 break; | |
248 | |
249 default: | |
250 if (envsection) | |
251 { | |
252 pn = p; | |
253 | |
254 // Convert name to upper case; | |
255 // remove spaces bracketing = | |
256 for (p = pn; *p; p++) | |
257 { if (islower(*p)) | |
258 *p &= ~0x20; | |
259 else if (isspace(*p)) | |
260 memmove(p, p + 1, strlen(p)); | |
261 else if (*p == '=') | |
262 { | |
263 p++; | |
264 while (isspace(*p)) | |
265 memmove(p, p + 1, strlen(p)); | |
266 break; | |
267 } | |
268 } | |
269 | |
270 putenv(strdup(pn)); | |
271 #if LOG | |
272 printf("\tputenv('%s')\n", pn); | |
273 //printf("getenv(\"TEST\") = '%s'\n",getenv("TEST")); | |
274 #endif | |
275 } | |
276 break; | |
277 } | |
278 | |
279 Lskip: | |
280 ; | |
281 } | |
282 } | |
283 | |
284 /******************** | |
285 * Skip spaces. | |
286 */ | |
287 | |
288 char *skipspace(const char *p) | |
289 { | |
290 while (isspace(*p)) | |
291 p++; | |
292 return (char *)p; | |
293 } | |
294 |