Require {DECLARE,DEFAULT}_DEBUG_CHANNEL statements to end in a ;
[wine] / msdos / dosconf.c
1 /*
2  * DOS CONFIG.SYS parser
3  *
4  * Copyright 1998 Andreas Mohr 
5  *
6  */
7
8 #include <stdio.h>
9 #include <unistd.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <ctype.h>
13 #include "winbase.h"
14 #include "msdos.h"
15 #include "debugtools.h"
16 #include "options.h"
17 #include "file.h"
18
19 DEFAULT_DEBUG_CHANNEL(profile);
20
21
22 static int DOSCONF_Device(char **confline);
23 static int DOSCONF_Dos(char **confline);
24 static int DOSCONF_Fcbs(char **confline);
25 static int DOSCONF_Break(char **confline);
26 static int DOSCONF_Files(char **confline);
27 static int DOSCONF_Install(char **confline);
28 static int DOSCONF_Lastdrive(char **confline);
29 static int DOSCONF_Menu(char **confline);
30 static int DOSCONF_Include(char **confline);
31 static int DOSCONF_Country(char **confline);
32 static int DOSCONF_Numlock(char **confline);
33 static int DOSCONF_Switches(char **confline);
34 static int DOSCONF_Shell(char **confline);
35 static int DOSCONF_Stacks(char **confline);
36 static int DOSCONF_Buffers(char **confline);
37 static void DOSCONF_Parse(char *menuname);
38
39 DOSCONF DOSCONF_config = 
40 {
41     'E',  /* lastdrive */
42     0,    /* brk_flag */
43     8,    /* files */
44     9,    /* stacks_nr */
45     256,  /* stacks_sz */
46     15,   /* buf */
47     1,    /* buf2 */
48     4,    /* fcbs */
49     0,    /* flags */
50     NULL, /* shell */
51     NULL  /* country */
52 };
53
54 typedef struct {
55     const char *tag_name;
56     int (*tag_handler)(char **p);
57 } TAG_ENTRY;
58
59
60 /*
61  * see
62  * http://egeria.cm.cf.ac.uk/User/P.L.Poulain/project/internal/allinter.htm
63  * or
64  * http://www.csulb.edu/~murdock/dosindex.html
65  */
66
67 static const TAG_ENTRY tag_entries[] =
68 {
69     { ";", NULL },
70     { "REM ", NULL },
71     { "DEVICE", DOSCONF_Device },
72     { "[", DOSCONF_Menu },
73     { "SUBMENU", NULL },
74     { "MENUDEFAULT", DOSCONF_Menu },
75     { "INCLUDE", DOSCONF_Include },
76
77     { "INSTALL", DOSCONF_Install },
78     { "DOS", DOSCONF_Dos },
79     { "FCBS", DOSCONF_Fcbs },
80     { "BREAK", DOSCONF_Break },
81     { "FILES", DOSCONF_Files },
82     { "SHELL", DOSCONF_Shell },    
83     { "STACKS", DOSCONF_Stacks },
84     { "BUFFERS", DOSCONF_Buffers },
85     { "COUNTRY", DOSCONF_Country },
86     { "NUMLOCK", DOSCONF_Numlock },
87     { "SWITCHES", DOSCONF_Switches },
88     { "LASTDRIVE", DOSCONF_Lastdrive }
89 };
90
91 static FILE *cfg_fd;
92
93 static char *menu_default = NULL;
94 static int menu_in_listing = 0;         /* we are in the [menu] section */
95 static int menu_skip = 0;                               /* the current menu gets skipped */
96
97
98 static void DOSCONF_skip(char **pconfline)
99 {
100     char *p;
101     
102     p = *pconfline;
103     while ( (*p == ' ') || (*p == '\t') ) p++;
104     *pconfline = p;
105 }
106                 
107 static int DOSCONF_JumpToEntry(char **pconfline, char separator)
108 {
109     char *p;
110     
111     p = *pconfline;
112     while ( (*p != separator) && (*p != '\0') ) p++;
113
114     if (*p != separator)
115         return 0;
116     else p++;
117
118     while ( (*p == ' ') || (*p == '\t') ) p++;
119     *pconfline = p;
120     return 1;
121 }
122
123 static int DOSCONF_Device(char **confline)
124 {
125     int loadhigh = 0;
126
127     *confline += 6; /* strlen("DEVICE") */
128     if (!(strncasecmp(*confline, "HIGH", 4)))
129     {
130         loadhigh = 1;
131         *confline += 4;
132         /* FIXME: get DEVICEHIGH parameters if avail ? */
133     }
134     if (!(DOSCONF_JumpToEntry(confline, '='))) return 0;
135     TRACE("Loading device '%s'\n", *confline);
136 #if 0
137     DOSMOD_LoadDevice(*confline, loadhigh);
138 #endif
139     return 1;
140 }
141
142 static int DOSCONF_Dos(char **confline)
143 {
144     *confline += 3; /* strlen("DOS") */
145     if (!(DOSCONF_JumpToEntry(confline, '='))) return 0;
146     while (**confline != '\0')
147     {
148         if (!(strncasecmp(*confline, "HIGH", 4)))
149         {
150             DOSCONF_config.flags |= DOSCONF_MEM_HIGH;
151             *confline += 4;
152         }
153         else
154         if (!(strncasecmp(*confline, "UMB", 3)))
155         {
156             DOSCONF_config.flags |= DOSCONF_MEM_UMB;
157             *confline += 3;
158         }
159         else (*confline)++;
160         DOSCONF_JumpToEntry(confline, ',');
161     }
162     TRACE("DOSCONF_Dos: HIGH is %d, UMB is %d\n",
163         (DOSCONF_config.flags & DOSCONF_MEM_HIGH) != 0, (DOSCONF_config.flags & DOSCONF_MEM_UMB) != 0);
164     return 1;
165 }
166
167 static int DOSCONF_Fcbs(char **confline)
168 {
169     *confline += 4; /* strlen("FCBS") */
170     if (!(DOSCONF_JumpToEntry(confline, '='))) return 0;
171     DOSCONF_config.fcbs = atoi(*confline);
172     if (DOSCONF_config.fcbs > 255)
173     {
174                 MESSAGE("The FCBS value in the config.sys file is too high ! Setting to 255.\n");
175                 DOSCONF_config.fcbs = 255;
176     }
177     TRACE("DOSCONF_Fcbs returning %d\n", DOSCONF_config.fcbs);
178     return 1;
179 }
180
181 static int DOSCONF_Break(char **confline)
182 {
183     *confline += 5; /* strlen("BREAK") */
184     if (!(DOSCONF_JumpToEntry(confline, '='))) return 0;
185     if (!(strcasecmp(*confline, "ON")))
186         DOSCONF_config.brk_flag = 1;
187     TRACE("BREAK is %d\n", DOSCONF_config.brk_flag);
188     return 1;
189 }
190
191 static int DOSCONF_Files(char **confline)
192 {
193     *confline += 5; /* strlen("FILES") */
194     if (!(DOSCONF_JumpToEntry(confline, '='))) return 0;
195     DOSCONF_config.files = atoi(*confline);
196     if (DOSCONF_config.files > 255)
197     {
198         MESSAGE("The FILES value in the config.sys file is too high ! Setting to 255.\n");
199         DOSCONF_config.files = 255;
200     }
201     if (DOSCONF_config.files < 8)
202     {
203         MESSAGE("The FILES value in the config.sys file is too low ! Setting to 8.\n");
204         DOSCONF_config.files = 8;
205     }
206     TRACE("DOSCONF_Files returning %d\n", DOSCONF_config.files);
207     return 1;
208 }
209
210 static int DOSCONF_Install(char **confline)
211 {
212 #if 0
213     int loadhigh = 0;
214 #endif
215
216     *confline += 7; /* strlen("INSTALL") */
217     if (!(DOSCONF_JumpToEntry(confline, '='))) return 0;
218     TRACE("Installing '%s'\n", *confline);
219 #if 0
220     DOSMOD_Install(*confline, loadhigh);
221 #endif
222     return 1;
223 }
224
225 static int DOSCONF_Lastdrive(char **confline)
226 {
227     *confline += 9; /* strlen("LASTDRIVE") */
228     if (!(DOSCONF_JumpToEntry(confline, '='))) return 0;
229     DOSCONF_config.lastdrive = toupper(**confline);
230     TRACE("Lastdrive %c\n", DOSCONF_config.lastdrive);
231     return 1;
232 }
233
234 static int DOSCONF_Country(char **confline)
235 {
236     *confline += 7; /* strlen("COUNTRY") */
237     if (!(DOSCONF_JumpToEntry(confline, '='))) return 0;
238     TRACE("Country '%s'\n", *confline);
239     if (DOSCONF_config.country == NULL)
240                 DOSCONF_config.country = malloc(strlen(*confline) + 1);
241     strcpy(DOSCONF_config.country, *confline);
242     return 1;
243 }
244
245 static int DOSCONF_Numlock(char **confline)
246 {
247     *confline += 7; /* strlen("NUMLOCK") */
248     if (!(DOSCONF_JumpToEntry(confline, '='))) return 0;
249     if (!(strcasecmp(*confline, "ON")))
250         DOSCONF_config.flags |= DOSCONF_NUMLOCK;
251     TRACE("NUMLOCK is %d\n", (DOSCONF_config.flags & DOSCONF_NUMLOCK) != 0);
252     return 1;
253 }
254
255 static int DOSCONF_Switches(char **confline)
256 {
257     char *p;
258
259     *confline += 8; /* strlen("SWITCHES") */
260     if (!(DOSCONF_JumpToEntry(confline, '='))) return 0;
261     p = strtok(*confline, "/");
262     do
263     {
264         if ( toupper(*p) == 'K')
265             DOSCONF_config.flags |= DOSCONF_KEYB_CONV;
266     }
267     while ((p = strtok(NULL, "/")));
268     TRACE("'Force conventional keyboard' is %d\n",
269                 (DOSCONF_config.flags & DOSCONF_KEYB_CONV) != 0);
270     return 1;
271 }
272
273 static int DOSCONF_Shell(char **confline)
274 {
275     *confline += 5; /* strlen("SHELL") */
276     if (!(DOSCONF_JumpToEntry(confline, '='))) return 0;
277     TRACE("Shell '%s'\n", *confline);
278     if (DOSCONF_config.shell == NULL)
279                 DOSCONF_config.shell = malloc(strlen(*confline) + 1);
280     strcpy(DOSCONF_config.shell, *confline);
281     return 1;
282 }
283
284 static int DOSCONF_Stacks(char **confline)
285 {
286
287     *confline += 6; /* strlen("STACKS") */
288     if (!(DOSCONF_JumpToEntry(confline, '='))) return 0;
289     DOSCONF_config.stacks_nr = atoi(strtok(*confline, ","));
290     DOSCONF_config.stacks_sz = atoi((strtok(NULL, ",")));
291     TRACE("%d stacks of size %d\n",
292           DOSCONF_config.stacks_nr, DOSCONF_config.stacks_sz);
293     return 1;
294 }
295
296 static int DOSCONF_Buffers(char **confline)
297 {
298     char *p;
299
300     *confline += 7; /* strlen("BUFFERS") */
301     if (!(DOSCONF_JumpToEntry(confline, '='))) return 0;
302     p = strtok(*confline, ",");
303     DOSCONF_config.buf = atoi(p);
304     if ((p = strtok(NULL, ",")))
305         DOSCONF_config.buf2 = atoi(p);
306     TRACE("%d primary buffers, %d secondary buffers\n",
307           DOSCONF_config.buf, DOSCONF_config.buf2);
308     return 1;
309 }
310
311 static int DOSCONF_Menu(char **confline)
312 {
313     if (!(strncasecmp(*confline, "[MENU]", 6)))
314         menu_in_listing = 1;
315     else
316     if ((!(strncasecmp(*confline, "[COMMON]", 8)))
317     || (!(strncasecmp(*confline, "[WINE]", 6))))
318         menu_skip = 0;
319     else
320     if (**confline == '[')
321     {
322         (*confline)++;
323         if ((menu_default)
324         && (!(strncasecmp(*confline, menu_default, strlen(menu_default)))))
325     {
326                 free(menu_default);
327                 menu_default = NULL;
328             menu_skip = 0;
329     }
330         else
331             menu_skip = 1;
332         menu_in_listing = 0;
333     }
334     else
335     if (!(strncasecmp(*confline, "menudefault", 11)) && (menu_in_listing))
336     {
337         if (!(DOSCONF_JumpToEntry(confline, '='))) return 0;
338     *confline = strtok(*confline, ",");
339     menu_default = malloc(strlen(*confline) + 1);
340         strcpy(menu_default, *confline);
341     }
342     return 1;
343 }
344
345 static int DOSCONF_Include(char **confline)
346 {
347     fpos_t oldpos;
348     char *temp;
349     
350     *confline += 7; /* strlen("INCLUDE") */
351     if (!(DOSCONF_JumpToEntry(confline, '='))) return 0;
352     fgetpos(cfg_fd, &oldpos);
353     fseek(cfg_fd, 0, SEEK_SET);
354     TRACE("Including menu '%s'\n", *confline);
355     temp = malloc(strlen(*confline) + 1);
356     strcpy(temp, *confline);
357     DOSCONF_Parse(temp);
358         free(temp);
359     fsetpos(cfg_fd, &oldpos);
360     return 1;
361 }
362
363 static void DOSCONF_Parse(char *menuname)
364 {
365    char confline[256];
366    char *p, *trail;
367    int i;
368     
369     if (menuname != NULL) /* we need to jump to a certain sub menu */
370     {
371         while (fgets(confline, 255, cfg_fd))
372         {
373              p = confline;
374              DOSCONF_skip(&p);
375              if (*p == '[')
376              {
377                 p++;
378                 if (!(trail = strrchr(p, ']')))
379                     return;
380                 if (!(strncasecmp(p, menuname, (int)trail - (int)p)))
381                     break;
382              }
383         }
384     }
385
386     while (fgets(confline, 255, cfg_fd))
387     {
388         p = confline;
389         DOSCONF_skip(&p);
390
391         if ((menuname) && (*p == '['))
392             /* we were handling a specific sub menu, but now next menu begins */
393             break;
394
395         if ((trail = strrchr(confline, '\n')))
396                 *trail = '\0';
397         if ((trail = strrchr(confline, '\r')))
398                 *trail = '\0';
399         if (!(menu_skip))
400         {
401             for (i = 0; i < sizeof(tag_entries) / sizeof(TAG_ENTRY); i++)
402                 if (!(strncasecmp(p, tag_entries[i].tag_name,
403                    strlen(tag_entries[i].tag_name))))
404                 {
405                     TRACE("tag '%s'\n", tag_entries[i].tag_name);
406                     if (tag_entries[i].tag_handler != NULL)
407                             tag_entries[i].tag_handler(&p);
408                         break;
409                 }
410         }
411         else /* the current menu gets skipped */
412         DOSCONF_Menu(&p);
413     }
414 }
415
416 int DOSCONF_ReadConfig(void)
417 {
418     char buffer[256];
419     DOS_FULL_NAME fullname;
420     char *filename, *menuname;
421     int ret = 1;
422
423     PROFILE_GetWineIniString( "wine", "config.sys", "", buffer, sizeof(buffer) );
424     filename = strtok(buffer, ",");
425     menuname = strtok(NULL,   ",");
426     if (!filename) return ret;
427
428     DOSFS_GetFullName(filename, FALSE, &fullname);
429     if (menuname) menu_default = strdup(menuname);
430     if ((cfg_fd = fopen(fullname.long_name, "r")))
431     {
432         DOSCONF_Parse(NULL);
433         fclose(cfg_fd);
434     }
435     else
436     {
437         MESSAGE("Couldn't open config.sys file given as \"%s\" in" \
438             " wine.conf or .winerc, section [wine] !\n", filename);
439         ret = 0;
440     }
441     if (menu_default) free(menu_default);
442     return ret;
443 }