grub2: bring back build of aros-side grub2 tools
[AROS.git] / workbench / utilities / Installer / parse.c
blob6590fa84ee214a3f755e18641dd83d646818cc88
1 /*
2 Copyright © 1995-2003, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /* parse.c -- Here are all functions used to parse the input file */
8 #include "Installer.h"
9 #include "parse.h"
10 #include "cleanup.h"
11 #include "procedure.h"
12 #include "gui.h"
14 /* External variables */
15 extern char buffer[MAXARGSIZE];
16 extern BPTR inputfile;
17 extern InstallerPrefs preferences;
20 int line;
22 #ifdef DEBUG
24 * Print the sub-tree of ScriptArg *a
26 void printcode(ScriptArg *a, int x)
28 int i;
29 /* Don't produce a SegFault if pointer is non-NULL */
30 if ((long int)a > 1000)
32 for ( i = 0 ; i < x ; i++ )
33 printf(" ");
34 printf("%ld: %s , cmd=%ld, next=%ld, parent=%ld\n",(long int)a,a->arg,(long int)a->cmd,(long int)a->next,(long int)a->parent);
35 printcode(a->cmd, x+1);
36 printcode(a->next, x);
39 #endif /* DEBUG */
43 * Read in file and generate executable tree
45 void parse_file(ScriptArg *first)
47 ScriptArg *current;
48 int count, i, j, ready;
49 char **mclip;
51 ready = FALSE;
52 current = first;
55 count = Read(inputfile, &buffer[0], 1);
56 if (count == 0)
58 PrintFault(IoErr(), INSTALLER_NAME);
59 show_parseerror("End of File", line);
60 cleanup();
61 exit(-1);
63 if (!isspace(buffer[0]))
65 switch (buffer[0])
67 case SEMICOLON: /* A comment, ok - Go on with next line */
70 count = Read(inputfile, &buffer[0], 1);
71 } while (buffer[0] != LINEFEED && count != 0);
72 line++;
73 break;
75 case LBRACK: /* Open bracket: recurse into next level */
76 current->cmd = malloc(sizeof(ScriptArg));
77 if (current->cmd == NULL)
79 end_alloc();
81 /* Set initial values */
82 current->cmd->parent = current;
83 current->cmd->arg = NULL;
84 current->cmd->cmd = NULL;
85 current->cmd->next = NULL;
86 current->cmd->intval = 0;
87 current->cmd->ignore = 0;
88 parse_file(current->cmd);
89 current->next = malloc(sizeof(ScriptArg));
90 if (current->next == NULL)
92 end_alloc();
94 current->next->parent = current->parent;
95 /* Set initial values */
96 current = current->next;
97 current->arg = NULL;
98 current->cmd = NULL;
99 current->next = NULL;
100 current->intval = 0;
101 current->ignore = 0;
102 break;
104 case RBRACK: /* All args collected return to lower level */
105 /* We have allocated one ScriptArg too much */
106 current = current->parent->cmd;
107 if (current->next != NULL)
109 while (current->next->next != NULL)
111 current = current->next;
113 free(current->next);
114 current->next = NULL;
116 else
118 /* This is an empty bracket */
119 show_parseerror("There is an empty bracket.", line);
120 cleanup();
121 exit(-1);
123 ready = TRUE;
124 break;
126 default: /* This is the real string */
127 i = 0;
128 if (buffer[0] == DQUOTE || buffer[0] == SQUOTE)
130 int masquerade = FALSE;
133 if (masquerade == TRUE)
135 switch (buffer[i])
137 case 'n': /* NEWLINE */
138 buffer[i-1] = 0x0a;
139 break;
140 case 'r': /* RETURN */
141 buffer[i-1] = 0x0d;
142 break;
143 case 't': /* TAB */
144 buffer[i-1] = 0x09;
145 break;
146 case SQUOTE: /* SQUOTE */
147 buffer[i-1] = SQUOTE;
148 break;
149 case DQUOTE: /* DQUOTE */
150 buffer[i-1] = DQUOTE;
151 break;
152 case BACKSLASH: /* BACKSLASH */
153 buffer[i-1] = BACKSLASH;
154 break;
155 /* TODO: convert missing '\\' masqueraded symbols */
156 case 'h': /* H.TAB */
157 case 'v': /* V.TAB */
158 case 'b': /* BACKSPACE */
159 case 'f': /* FORMFEED */
160 case 'x': /* HEX number */
161 case 'o': /* \\ooo OCTAL number ('o' is just to remember) */
162 default:
163 i++;
164 break;
166 masquerade = FALSE;
168 else
170 if (buffer[i] == BACKSLASH)
171 masquerade = TRUE;
172 i++;
174 if (i == MAXARGSIZE)
176 show_parseerror("Argument length overflow!" ,line);
177 cleanup();
178 exit(-1);
180 count = Read(inputfile, &buffer[i], 1);
181 } while (masquerade || (buffer[i] != buffer[0] && count != 0));
182 current->arg = malloc(sizeof(char)*(i+2));
183 if (current->arg == NULL)
185 end_alloc();
187 buffer[i+1] = 0;
188 strncpy (current->arg, buffer, i+2);
190 else
194 i++;
195 count = Read(inputfile, &buffer[i], 1);
196 } while (!isspace(buffer[i]) && buffer[i]!=LBRACK && buffer[i]!=RBRACK && buffer[i]!=SEMICOLON && count != 0 && i < MAXARGSIZE);
197 if (buffer[i] == LINEFEED)
199 line++;
201 if (i == MAXARGSIZE)
203 show_parseerror("Argument length overflow!", line);
204 cleanup();
205 exit(-1);
207 if (buffer[i] == SEMICOLON)
211 count = Read(inputfile, &buffer[i], 1);
212 } while (buffer[i] != LINEFEED && count != 0);
213 line++;
215 if (buffer[i] == LBRACK || buffer[i] == RBRACK)
217 Seek(inputfile, -1 , OFFSET_CURRENT);
219 buffer[i] = 0;
220 switch (buffer[0])
222 case DOLLAR: /* HEX number */
223 current->intval = strtol(&buffer[1], NULL, 16);
224 break;
225 case PERCENT: /* binary number */
226 current->intval = strtol(&buffer[1], NULL, 2);
227 break;
228 default: /* number or variable */
229 if (isdigit(buffer[0]) || ((buffer[0] == PLUS || buffer[0] == MINUS) && isdigit(buffer[1])))
231 current->intval = atol(buffer);
233 else
235 current->arg = malloc(sizeof(char)*(i+1));
236 if (current->arg == NULL)
238 end_alloc();
240 strncpy(current->arg, buffer, i+1);
242 if (current == current->parent->cmd && strcasecmp(buffer, "procedure") == 0)
244 ScriptArg *proc, *uproc;
245 int finish;
246 /* Save procedure in ProcedureList */
247 proc = malloc(sizeof(ScriptArg));
248 if (proc == NULL)
250 end_alloc();
252 uproc = proc;
253 proc->parent = NULL;
254 proc->next = NULL;
255 proc->arg = NULL;
256 proc->intval = 0;
257 proc->ignore = 0;
258 proc->cmd = malloc(sizeof(ScriptArg));
259 if (proc->cmd == NULL)
261 end_alloc();
263 proc->cmd->parent = proc;
264 proc->cmd->next = NULL;
265 proc->cmd->arg = NULL;
266 proc->cmd->intval = 0;
267 proc->cmd->ignore = 0;
268 proc = proc->cmd;
269 proc->cmd = malloc(sizeof(ScriptArg));
270 if (proc->cmd == NULL)
272 end_alloc();
274 proc->cmd->parent = proc;
275 proc->cmd->next = NULL;
276 proc->cmd->arg = NULL;
277 proc->cmd->intval = 0;
278 proc->cmd->ignore = 0;
279 proc->cmd->cmd = NULL;
280 /* parse procedure name and args */
281 mclip = NULL;
282 j = 0;
283 finish = FALSE;
286 /* goto next argument */
289 count = Read(inputfile, &buffer[0], 1);
290 if (buffer[0] == LINEFEED)
292 line++;
294 if (buffer[0] == RBRACK)
296 if (j > 0)
298 show_parseerror("Procedure has no body!", line);
300 else
302 show_parseerror("Procedure has no name!", line);
304 cleanup();
305 exit(-1);
307 if (buffer[0] == SQUOTE || buffer[0] == DQUOTE)
309 show_parseerror("Procedure has a quoted argument!", line);
310 cleanup();
311 exit(-1);
313 if (buffer[0] == SEMICOLON && count != 0)
317 count = Read(inputfile, &buffer[0], 1);
318 } while (buffer[0] != LINEFEED && count != 0);
319 line++;
321 } while (isspace(buffer[0]) && count != 0);
323 if (buffer[0] != LBRACK)
325 i = 0;
326 /* read in string */
329 i++;
330 count = Read(inputfile, &buffer[i], 1);
331 } while (!isspace(buffer[i]) && buffer[i]!=LBRACK && buffer[i]!=RBRACK && buffer[i]!=SEMICOLON && count != 0 && i < MAXARGSIZE);
332 if (i == MAXARGSIZE)
334 show_parseerror("Argument length overflow!", line);
335 cleanup();
336 exit(-1);
338 if (buffer[i] == LINEFEED)
340 line++;
342 if (buffer[i] == LBRACK || buffer[i] == RBRACK || buffer[i] == SEMICOLON)
344 Seek(inputfile, -1 , OFFSET_CURRENT);
346 buffer[i] = 0;
347 j++;
348 mclip = realloc(mclip, sizeof(char *) * j);
349 if (mclip == NULL)
351 end_alloc();
353 mclip[j-1] = strdup(buffer);
354 if (mclip[j-1] == NULL)
356 end_alloc();
359 else
361 /* Exit if procedure has no name or name is string/digit or bracket follows */
362 if (j == 0)
364 show_parseerror("Argument to procedure is a command!\n", line);
365 cleanup();
366 exit(-1);
368 /* Next string is body-command */
369 finish = TRUE;
371 } while (!finish);
372 /* Procedure body */
373 parse_file(proc->cmd);
374 finish = FALSE;
379 count = Read(inputfile, &buffer[0], 1);
380 if (buffer[0] == LINEFEED)
382 line++;
384 } while (isspace(buffer[0]) && count != 0);
385 if (buffer[0] == SEMICOLON)
389 count = Read(inputfile, &buffer[0], 1);
390 } while (buffer[0] != LINEFEED && count != 0);
391 line++;
393 else if (buffer[0] == LBRACK)
395 proc->next = malloc(sizeof(ScriptArg));
396 if (proc->next == NULL)
398 end_alloc();
400 proc->next->parent = proc->parent;
401 proc->next->next = NULL;
402 proc->next->arg = NULL;
403 proc->next->intval = 0;
404 proc->next->ignore = 0;
405 proc = proc->next;
406 proc->cmd = malloc(sizeof(ScriptArg));
407 if (proc->cmd == NULL)
409 end_alloc();
411 proc->cmd->parent = proc;
412 proc->cmd->next = NULL;
413 proc->cmd->arg = NULL;
414 proc->cmd->intval = 0;
415 proc->cmd->ignore = 0;
416 proc->cmd->cmd = NULL;
417 parse_file(proc->cmd);
419 else if (buffer[0] == RBRACK)
421 finish = TRUE;
423 else
425 show_parseerror("Procedure has rubbish in its body!", line);
426 cleanup();
427 exit(-1);
429 } while (!finish);
430 current->next = malloc(sizeof(ScriptArg));
431 if (current->next == NULL)
433 end_alloc();
435 current->next->parent = current->parent;
436 current = current->next;
437 current->arg = mclip[0];
438 current->cmd = NULL;
439 current->next = NULL;
440 current->intval = set_procedure(mclip, j, uproc);
441 current->ignore = 0;
442 #ifdef DEBUG
443 printf("\n\n");
444 printcode(uproc, 0);
445 #endif /* DEBUG */
446 buffer[0] = 0;
447 ready = TRUE;
449 if (current->arg == current->parent->cmd->arg && strcasecmp(buffer, "welcome") == 0)
451 preferences.welcome = TRUE;
453 break;
456 current->next = malloc(sizeof(ScriptArg));
457 if (current->next == NULL)
459 end_alloc();
461 current->next->parent = current->parent;
462 current = current->next;
463 /* Set initial values */
464 current->arg = NULL;
465 current->cmd = NULL;
466 current->next = NULL;
467 current->intval = 0;
468 current->ignore = 0;
469 break;
472 else
474 if (buffer[0] == LINEFEED)
476 line++;
479 if (count == 0)
481 PrintFault(IoErr(), INSTALLER_NAME);
482 show_parseerror("End of File", line);
483 cleanup();
484 exit(-1);
486 } while (!ready);