comparison dmd2/inifile.c @ 758:f04dde6e882c

Added initial D2 support, D2 frontend and changes to codegen to make things compile.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Tue, 11 Nov 2008 01:38:48 +0100
parents
children 2667e3a145be
comparison
equal deleted inserted replaced
757:2c730d530c98 758:f04dde6e882c
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 #ifdef __MINGW32__
17 #include <malloc.h>
18 #endif
19
20 #define LOG 0
21
22 char *skipspace(const char *p);
23
24 #if __GNUC__
25 char *strupr(char *s)
26 {
27 char *t = s;
28
29 while (*s)
30 {
31 *s = toupper(*s);
32 s++;
33 }
34
35 return t;
36 }
37 #endif /* unix */
38
39 /*****************************
40 * Read and analyze .ini file.
41 * Input:
42 * argv0 program name (argv[0])
43 * inifile .ini file name
44 */
45
46 void inifile(const char *argv0x, const char *inifilex)
47 {
48 char *argv0 = (char *)argv0x;
49 char *inifile = (char *)inifilex; // do const-correct later
50 char *path; // need path for @P macro
51 char *filename;
52 OutBuffer buf;
53 int i;
54 int k;
55 int envsection = 0;
56
57 #if LOG
58 printf("inifile(argv0 = '%s', inifile = '%s')\n", argv0, inifile);
59 #endif
60 if (FileName::absolute(inifile))
61 {
62 filename = inifile;
63 }
64 else
65 {
66 /* Look for inifile in the following sequence of places:
67 * o current directory
68 * o home directory
69 * o directory off of argv0
70 * o /etc/
71 */
72 if (FileName::exists(inifile))
73 {
74 filename = inifile;
75 }
76 else
77 {
78 filename = FileName::combine(getenv("HOME"), inifile);
79 if (!FileName::exists(filename))
80 {
81 filename = FileName::replaceName(argv0, inifile);
82 if (!FileName::exists(filename))
83 {
84 #if POSIX
85
86 #if 0
87 #if __GLIBC__ // This fix by Thomas Kuehne
88 /* argv0 might be a symbolic link,
89 * so try again looking past it to the real path
90 */
91 char* real_argv0 = realpath(argv0, NULL);
92 if (real_argv0)
93 {
94 filename = FileName::replaceName(real_argv0, inifile);
95 free(real_argv0);
96 if (FileName::exists(filename))
97 goto Ldone;
98 }
99 #else
100 #error use of glibc non-standard extension realpath(char*, NULL)
101 #endif
102 #endif
103
104 // old way; problem is that argv0 might not be on the PATH at all
105 // and some other instance might be found
106
107 // Search PATH for argv0
108 const char *p = getenv("PATH");
109 Array *paths = FileName::splitPath(p);
110 filename = FileName::searchPath(paths, argv0, 0);
111 if (!filename)
112 goto Letc; // argv0 not found on path
113 filename = FileName::replaceName(filename, inifile);
114 if (FileName::exists(filename))
115 goto Ldone;
116 #endif
117
118 // Search /etc/ for inifile
119 Letc:
120 filename = FileName::combine((char *)"/etc/", inifile);
121
122 Ldone:
123 ;
124 }
125 }
126 }
127 }
128 path = FileName::path(filename);
129 #if LOG
130 printf("\tpath = '%s', filename = '%s'\n", path, filename);
131 #endif
132
133 File file(filename);
134
135 if (file.read())
136 return; // error reading file
137
138 // Parse into lines
139 int eof = 0;
140 for (i = 0; i < file.len && !eof; i++)
141 {
142 int linestart = i;
143
144 for (; i < file.len; i++)
145 {
146 switch (file.buffer[i])
147 {
148 case '\r':
149 break;
150
151 case '\n':
152 // Skip if it was preceded by '\r'
153 if (i && file.buffer[i - 1] == '\r')
154 goto Lskip;
155 break;
156
157 case 0:
158 case 0x1A:
159 eof = 1;
160 break;
161
162 default:
163 continue;
164 }
165 break;
166 }
167
168 // The line is file.buffer[linestart..i]
169 char *line;
170 int len;
171 char *p;
172 char *pn;
173
174 line = (char *)&file.buffer[linestart];
175 len = i - linestart;
176
177 buf.reset();
178
179 // First, expand the macros.
180 // Macros are bracketed by % characters.
181
182 for (k = 0; k < len; k++)
183 {
184 if (line[k] == '%')
185 {
186 int j;
187
188 for (j = k + 1; j < len; j++)
189 {
190 if (line[j] == '%')
191 {
192 if (j - k == 3 && memicmp(&line[k + 1], "@P", 2) == 0)
193 {
194 // %@P% is special meaning the path to the .ini file
195 p = path;
196 if (!*p)
197 p = (char *)".";
198 }
199 else
200 { int len = j - k;
201 char tmp[10]; // big enough most of the time
202
203 if (len <= sizeof(tmp))
204 p = tmp;
205 else
206 p = (char *)alloca(len);
207 len--;
208 memcpy(p, &line[k + 1], len);
209 p[len] = 0;
210 strupr(p);
211 p = getenv(p);
212 if (!p)
213 p = (char *)"";
214 }
215 buf.writestring(p);
216 k = j;
217 goto L1;
218 }
219 }
220 }
221 buf.writeByte(line[k]);
222 L1:
223 ;
224 }
225
226 // Remove trailing spaces
227 while (buf.offset && isspace(buf.data[buf.offset - 1]))
228 buf.offset--;
229
230 p = buf.toChars();
231
232 // The expanded line is in p.
233 // Now parse it for meaning.
234
235 p = skipspace(p);
236 switch (*p)
237 {
238 case ';': // comment
239 case 0: // blank
240 break;
241
242 case '[': // look for [Environment]
243 p = skipspace(p + 1);
244 for (pn = p; isalnum(*pn); pn++)
245 ;
246 if (pn - p == 11 &&
247 memicmp(p, "Environment", 11) == 0 &&
248 *skipspace(pn) == ']'
249 )
250 envsection = 1;
251 else
252 envsection = 0;
253 break;
254
255 default:
256 if (envsection)
257 {
258 pn = p;
259
260 // Convert name to upper case;
261 // remove spaces bracketing =
262 for (p = pn; *p; p++)
263 { if (islower(*p))
264 *p &= ~0x20;
265 else if (isspace(*p))
266 memmove(p, p + 1, strlen(p));
267 else if (*p == '=')
268 {
269 p++;
270 while (isspace(*p))
271 memmove(p, p + 1, strlen(p));
272 break;
273 }
274 }
275
276 putenv(strdup(pn));
277 #if LOG
278 printf("\tputenv('%s')\n", pn);
279 //printf("getenv(\"TEST\") = '%s'\n",getenv("TEST"));
280 #endif
281 }
282 break;
283 }
284
285 Lskip:
286 ;
287 }
288 }
289
290 /********************
291 * Skip spaces.
292 */
293
294 char *skipspace(const char *p)
295 {
296 while (isspace(*p))
297 p++;
298 return (char *)p;
299 }
300