Mercurial > projects > ldc
annotate dmd/inifile.c @ 195:8baa9b0138e2 trunk
[svn r211] Added readme in phobos dir.
author | lindquist |
---|---|
date | Mon, 12 May 2008 19:08:22 +0200 |
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 |