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