don't assert if a struct-type symbol hasn't been defined
[xorcyst.git] / RCS / script.c,v
blobb2380044f82004f1d1e323fbc1178af7892adc0a
1 head    1.3;
2 access;
3 symbols;
4 locks; strict;
5 comment @ * @;
8 1.3
9 date    2007.07.22.13.33.26;    author khansen; state Exp;
10 branches;
11 next    1.2;
13 1.2
14 date    2004.12.18.16.59.50;    author kenth;   state Exp;
15 branches;
16 next    1.1;
18 1.1
19 date    2004.06.30.07.55.53;    author kenth;   state Exp;
20 branches;
21 next    ;
24 desc
28 1.3
29 log
30 @convert tabs to whitespaces
32 text
33 @/*
34  * $Id: script.c,v 1.2 2004/12/18 16:59:50 kenth Exp $
35  * $Log: script.c,v $
36  * Revision 1.2  2004/12/18 16:59:50  kenth
37  * fixed command parser bug
38  *
39  * Revision 1.1  2004/06/30 07:55:53  kenth
40  * Initial revision
41  *
42  */
44 /**
45  *    (C) 2004 Kent Hansen
46  *
47  *    The XORcyst is free software; you can redistribute it and/or modify
48  *    it under the terms of the GNU General Public License as published by
49  *    the Free Software Foundation; either version 2 of the License, or
50  *    (at your option) any later version.
51  *
52  *    The XORcyst is distributed in the hope that it will be useful,
53  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
54  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
55  *    GNU General Public License for more details.
56  *
57  *    You should have received a copy of the GNU General Public License
58  *    along with The XORcyst; if not, write to the Free Software
59  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
60  */
62 /**
63  * This file contains functions to parse, manage, process and query XORcyst
64  * linker scripts and their commands.
65  * Such a script is just a text file with a series of commands of the following
66  * form:
67  * command_name{arg_name=value, arg_name=value, ...}
68  */
70 #include <stdio.h>
71 #include <stdlib.h>
72 #include <stdarg.h>
73 #include <string.h>
74 #include "script.h"
76 #define SAFE_FREE(a) if (a) { free(a); a = NULL; }
78 /*---------------------------------------------------------------------------*/
80 /** Describes a mapping from string to command type */
81 struct tag_string_to_command_type_mapping {
82     char *string;
83     command_type type;
86 typedef struct tag_string_to_command_type_mapping string_to_command_type_mapping;
88 /**
89  * Attempts to map a string to a script command type.
90  * @@param s String representation of command
91  * @@return The corresponding command
92  */
93 static command_type string_to_command_type(char *s) {
94     int i;
95     /* Table of mappings */
96     static string_to_command_type_mapping map[] = {
97         { "ram", RAM_COMMAND },
98         { "output", OUTPUT_COMMAND },
99         { "copy", COPY_COMMAND },
100         { "bank", BANK_COMMAND },
101         { "link", LINK_COMMAND },
102         { "options", OPTIONS_COMMAND },
103         { "pad", PAD_COMMAND},
104         { NULL, -1}
105     };
106     /* Try all the mappings */
107     for (i=0; map[i].string != NULL; i++) {
108         if (strcmp(s, map[i].string) == 0) {
109             /* Found it */
110             return map[i].type;
111         }
112     }
113     /* Not in map table */
114     return BAD_COMMAND;
117 /** Describes the arguments that a command should acknowledge */
118 struct tag_valid_command_args
120     command_type type;
121     char **args;
124 typedef struct tag_valid_command_args valid_command_args;
127  * Tests if the given command argument name is valid.
128  */
129 static int is_valid_command_arg(command_type type, const char *candidate_arg)
131     int i;
132     int j;
133     char **args;
134     /* Lists of valid args for each command */
135     static char *ram_args[] =   { "end", "start", NULL };
136     static char *output_args[] =    { "file", NULL };
137     static char *copy_args[] =  { "file", NULL };
138     static char *bank_args[] =  { "size", "origin", NULL };
139     static char *link_args[] =  { "file", "origin", NULL };
140     static char *pad_args[] =   { "size", "origin", "offset", NULL };
141     /* Table of valid args */
142     static valid_command_args ok_args[] = {
143         { RAM_COMMAND,      ram_args },
144         { OUTPUT_COMMAND,   output_args },
145         { COPY_COMMAND,     copy_args },
146         { BANK_COMMAND,     bank_args },
147         { LINK_COMMAND,     link_args },
148         { PAD_COMMAND,      pad_args }
149     };
150     /* Find arg array for command */
151     for (i=0; ok_args[i].type != -1; i++) {
152         if (ok_args[i].type == type) {
153             /* Now go through array of valid args for command */
154             args = ok_args[i].args;
155             for (j=0; args[j] != NULL; j++) {
156                 if (strcmp(args[j], candidate_arg) == 0) {
157                     /* Found it. Valid. */
158                     return 1;
159                 }
160             }
161             /* Didn't find it. Invalid. */
162             return 0;
163         }
164     }
165     /* Not valid argument */
166     return 0;
169 /*---------------------------------------------------------------------------*/
171 #define IS_SPACE(c) ( ((c) == '\t') || ((c) == ' ') )
174  * Eats whitespace.
175  * @@param s String with whitespace (possibly)
176  * @@param i Start index in string, will be incremented beyond whitespace
177  */
178 static void eat_ws(char *s, int *i)
180     while (IS_SPACE(s[*i])) (*i)++;
184  * Tests if a character is in a set of delimiters.
185  */
186 static int is_delim(unsigned char c, char *delim)
188     int i;
189     /* Compare to all delimiters */
190     for (i=0; i<strlen(delim)+1; i++) {
191         if (delim[i] == c) return 1;
192     }
193     /* Not a delimiter */
194     return 0;
198  * Gets a token.
199  * @@param s String containing token
200  * @@param i Start index in string, will be incremented beyond token
201  * @@param delim Set of delimiters which may mark end of token
202  * @@param dest Where to store the grabbed token
203  */
204 static void get_token(char *s, int *i, char *delim, char *dest)
206     unsigned char c;
207     int j = 0;
208     dest[0] = '\0';
209     while (1) {
210         /* Get next character */
211         c = s[*i];
212         /* Test if token delimiter */
213         if (is_delim(c, delim)) {
214             /* End token */
215             dest[j] = '\0';
216             return;
217         }
218         else {
219             /* check if escape character */
220             if (c == '\\') {
221                 /* Increase i */
222                 (*i)++;
223                 /* Get next character */
224                 c = s[*i];
225                 /* Convert to C escape char if applicable */
226                 switch (c) {
227                     case '0':   c = '\0';   break;
228                     case 'a':   c = '\a';   break;
229                     case 'b':   c = '\b';   break;
230                     case 't':   c = '\t';   break;
231                     case 'f':   c = '\f';   break;
232                     case 'n':   c = '\n';   break;
233                     case 'r':   c = '\r';   break;
234                 }
235             }
236             /* Copy to dest */
237             dest[j++] = c;
238             /* Increase i */
239             (*i)++;
240         }
241     }
244 /*---------------------------------------------------------------------------*/
247  * Displays an error message generated during script parsing.
248  * @@param filename Name of file where error was found
249  * @@param line Line of file
250  * @@param fmt printf-style format string
251  */
252 static void err(char *filename, int line, char *fmt, ...)
254     va_list ap;
255     va_start(ap, fmt);
257     /* Print error message w/ location info */
258     fprintf(stderr, "error: %s:%d: ", filename, line);
259     vfprintf(stderr, fmt, ap);
260     fprintf(stderr, "\n");
262     va_end(ap);
265 /*---------------------------------------------------------------------------*/
268  * Adds an argument to script command.
269  * @@param cmd Command
270  * @@param arg Argument to add
271  */
272 static void add_arg(script_command *cmd, command_arg *arg)
274     command_arg *a;
275     if (cmd->first_arg == NULL) {
276         /* Start list */
277         cmd->first_arg = arg;
278     }
279     else {
280         /* Add to end of list */
281         for (a = cmd->first_arg; a->next != NULL; a = a->next) ;
282         a->next = arg;
283     }
284     arg->next = NULL;
288  * Adds a command to script.
289  * @@param sc Script
290  * @@param cmd Command to add
291  */
292 static void add_command(script *sc, script_command *cmd)
294     script_command *c;
295     if (sc->first_command == NULL) {
296         /* Start list */
297         sc->first_command = cmd;
298     }
299     else {
300         /* Add to end of list */
301         for (c = sc->first_command; c->next != NULL; c = c->next) ;
302         c->next = cmd;
303     }
304     cmd->next = NULL;
308  * Finalizes a script command.
309  * @@param cmd Command
310  */
311 static void finalize_command(script_command *cmd)
313     command_arg *a;
314     command_arg *t;
315     /* Finalize all arguments */
316     for(a = cmd->first_arg; a != NULL; a = t) {
317         t = a->next;
318         SAFE_FREE(a->key);
319         SAFE_FREE(a->value);
320         SAFE_FREE(a);
321     }
322     SAFE_FREE(cmd);
326  * Gets the processor function for a script command type from a map.
327  * @@param type The command type
328  * @@param map A mapping from command types to processor functions
329  */
330 static script_commandproc command_type_to_proc(command_type type, script_commandprocmap *map)
332     for (; map->proc != NULL; map += 1) {
333         if (map->type == type) {
334             return map->proc;
335         }
336     }
337     return NULL;
340 /*---------------------------------------------------------------------------*/
343  * Parses a script from a file to a script struct.
344  * @@param filename File to parse
345  * @@param sc Destination script
346  * @@return 0 if fail, 1 if OK
347  */
348 int script_parse(char *filename, script *sc)
350     FILE *fp;
351     command_arg *arg;
352     script_command *cmd;
353     command_type type;
354     int i;
355     char line[1024];
356     char cmdname[256];
357     char argname[256];
358     char argvalue[256];
359     static int lineno = 0;
360     sc->name = filename;
361     sc->first_command = NULL;
362     /* Attempt to open script */
363     fp = fopen(filename, "rt");
364     if (fp == NULL) {
365         fprintf(stderr, "error: could not open `%s' for reading\n", filename);
366         return 0;
367     }
368     /* Read commands */
369     while (fgets(line, 1023, fp) != NULL) {
370         /* Increase line number */
371         lineno++;
372         /* Skip white space */
373         i = 0;
374         eat_ws(line, &i);
375         /* Skip line if comment or end */
376         if ( (line[i] == '#') || (line[i] == '\0') || (line[i] == '\n') ) continue;
377         /* Get command name */
378         get_token(line, &i, " \t{", cmdname);
379         /* Check that it's a valid command */
380         if (strlen(cmdname) == 0) {
381             err(filename, lineno, "command expected");
382             continue;
383         }
384         else {
385             /* Convert from string to command type */
386             type = string_to_command_type(cmdname);
387             if (type == BAD_COMMAND) {
388                 err(filename, lineno, "unknown command `%s'", cmdname);
389                 continue;
390             }
391             else {
392                 /* Allocate space for command */
393                 cmd = (script_command *)malloc( sizeof(script_command) );
394                 if (cmd != NULL) {
395                     /* Set the type */
396                     cmd->type = type;
397                     /* No arguments (yet) */
398                     cmd->first_arg = NULL;
399                     /* Store line number */
400                     cmd->line = lineno;
401                     /* Add command to script */
402                     add_command(sc, cmd);
403                 }
404             }
405         }
406         /* Skip white space */
407         eat_ws(line, &i);
408         /* Next token should be '{' */
409         if (line[i] != '{') {
410             err(filename, lineno, "{ expected");
411             continue;
412         }
413         i++;    /* Eat '{' */
414         /* Get argument(s) */
415         while (line[i] != '}') {
416             if (line[i] == '\0') {
417                 break;
418             }
419             /* */
420             if (cmd->first_arg != NULL) {
421                 /* Skip white space */
422                 eat_ws(line, &i);
423                 /* Next token should be , */
424                 if (line[i] != ',') {
425                     err(filename, lineno, ", expected");
426                     continue;
427                 }
428                 i++;    /* Eat , */
429             }
430             /* Skip white space */
431             eat_ws(line, &i);
432             /* Get argument name */
433             get_token(line, &i, " \t=", argname);
434             if (strlen(argname) == 0) {
435                 err(filename, lineno, "argument name expected");
436                 continue;
437             }
438             /* Skip white space */
439             eat_ws(line, &i);
440             /* Next token should be '=' */
441             if (line[i] != '=') {
442                 err(filename, lineno, "= expected");
443                 continue;
444             }
445             i++;    /* Eat '=' */
446             /* Skip white space */
447             eat_ws(line, &i);
448             /* Get value */
449             get_token(line, &i, " \t},", argvalue);
450             if (strlen(argvalue) == 0) {
451                 err(filename, lineno, "value expected for argument `%s'", argname);
452                 continue;
453             }
454             // Check if the argument name is valid for this command */
455             if (is_valid_command_arg(cmd->type, argname) ) {
456                 /* Create argument struct */
457                 arg = (command_arg *)malloc( sizeof(command_arg) );
458                 if (arg != NULL) {
459                     arg->key = (char *)malloc( strlen(argname)+1 );
460                     arg->value = (char *)malloc( strlen(argvalue)+1 );
461                     /* Copy fields */
462                     strcpy(arg->key, argname);
463                     strcpy(arg->value, argvalue);
464                     /* Store argument in list */
465                     add_arg(cmd, arg);
466                 }
467             }
468             else {
469                 /* Not valid argument name */
470                 err(filename, lineno, "invalid argument `%s'", argname);
471                 continue;
472             }
473             /* Skip white space */
474             eat_ws(line, &i);
475         }
476     }
477     /* Close script */
478     fclose(fp);
479     /* Success */
480     return 1;
484  * Finalizes a script.
485  * @@param sc Script
486  */
487 void script_finalize(script *sc)
489     script_command *c;
490     script_command *t;
491     if (sc == NULL) { return; }
492     for(c = sc->first_command; c != NULL; c = t) {
493         t = c->next;
494         finalize_command(c);
495     }
499  * Gets the length (that is, number of commands) of a script.
500  * @@param sc Script
501  * @@return Number of commands in script
502  */
503 int script_length(script *sc)
505     script_command *c;
506     int i;
507     if (sc == NULL) { return 0; }
508     for (i=0, c=sc->first_command; c != NULL; i++, c = c->next) ;
509     return i;
513  * Gets a command from a script.
514  * @@param sc Script
515  * @@param index Command index
516  */
517 script_command *script_get_command(script *sc, int index)
519     script_command *c;
520     int i;
521     if (sc == NULL) { return NULL; }
522     for (i=0, c=sc->first_command; (c != NULL) && (i != index); i++, c = c->next) ;
523     return c;
527  * Processes commands in script.
528  * @@param sc Script
529  * @@param map Map from command to processor function
530  */
531 void script_walk(script *sc, script_commandprocmap *map, void *arg)
533     script_command *c;
534     script_commandproc p;
535     if (sc == NULL) { return; }
536     /* Walk all the commands */
537     for (c=sc->first_command; c != NULL; c = c->next) {
538         /* Process this command if it has a processor function */
539         p = command_type_to_proc(c->type, map);
540         if (p != NULL) {
541             p(sc, c, arg);
542         }
543     }
547  * Gets value of argument for script command.
548  * @@param c Command
549  * @@param key Key (argument name)
550  */
551 char *script_get_command_arg(script_command *c, char *key)
553     command_arg *a;
554     if (c == NULL) { return NULL; }
555     /* Go through all args */
556     for (a = c->first_arg; a != NULL; a = a->next) {
557         if (strcmp(key, a->key) == 0) {
558             /* Found it, return its value */
559             return a->value;
560         }
561     }
562     /* Not found */
563     return NULL;
567  * Gets the string representation of a command type.
568  * @@param type Command type
569  */
570 char *script_command_type_to_string(command_type type)
572     switch (type) {
573         case RAM_COMMAND:   return "ram";
574         case OUTPUT_COMMAND:    return "output";
575         case COPY_COMMAND:  return "copy";
576         case BANK_COMMAND:  return "bank";
577         case LINK_COMMAND:  return "link";
578         case OPTIONS_COMMAND:   return "options";
579         case PAD_COMMAND:   return "pad";
580         default:
581         /* Invalid command */
582         break;
583     }
584     return "Invalid command!";
588  * Counts the number of commands of the given type in a script.
589  * @@param sc Script
590  * @@param type Command type
591  */
592 int script_count_command_type(script *sc, command_type type)
594     script_command *c;
595     int count;
596     if (sc == NULL) { return 0; }
597     for (count=0, c=sc->first_command; c != NULL; c = c->next) {
598         if (c->type == type) {
599             count++;
600         }
601     }
602     return count;
609 @fixed command parser bug
611 text
612 @d2 1
613 a2 1
614  * $Id: script.c,v 1.1 2004/06/30 07:55:53 kenth Exp kenth $
615 d4 3
616 d50 2
617 a51 2
618         char *string;
619         command_type type;
620 d62 21
621 a82 21
622         int i;
623         /* Table of mappings */
624         static string_to_command_type_mapping map[] = {
625                 { "ram", RAM_COMMAND },
626                 { "output", OUTPUT_COMMAND },
627                 { "copy", COPY_COMMAND },
628                 { "bank", BANK_COMMAND },
629                 { "link", LINK_COMMAND },
630                 { "options", OPTIONS_COMMAND },
631                 { "pad", PAD_COMMAND},
632                 { NULL, -1}
633         };
634         /* Try all the mappings */
635         for (i=0; map[i].string != NULL; i++) {
636                 if (strcmp(s, map[i].string) == 0) {
637                         /* Found it */
638                         return map[i].type;
639                 }
640         }
641         /* Not in map table */
642         return BAD_COMMAND;
643 d88 2
644 a89 2
645         command_type type;
646         char **args;
647 d99 36
648 a134 36
649         int i;
650         int j;
651         char **args;
652         /* Lists of valid args for each command */
653         static char *ram_args[] =       { "end", "start", NULL };
654         static char *output_args[] =    { "file", NULL };
655         static char *copy_args[] =      { "file", NULL };
656         static char *bank_args[] =      { "size", "origin", NULL };
657         static char *link_args[] =      { "file", "origin", NULL };
658         static char *pad_args[] =       { "size", "origin", "offset", NULL };
659         /* Table of valid args */
660         static valid_command_args ok_args[] = {
661                 { RAM_COMMAND,          ram_args },
662                 { OUTPUT_COMMAND,       output_args },
663                 { COPY_COMMAND,         copy_args },
664                 { BANK_COMMAND,         bank_args },
665                 { LINK_COMMAND,         link_args },
666                 { PAD_COMMAND,          pad_args }
667         };
668         /* Find arg array for command */
669         for (i=0; ok_args[i].type != -1; i++) {
670                 if (ok_args[i].type == type) {
671                         /* Now go through array of valid args for command */
672                         args = ok_args[i].args;
673                         for (j=0; args[j] != NULL; j++) {
674                                 if (strcmp(args[j], candidate_arg) == 0) {
675                                         /* Found it. Valid. */
676                                         return 1;
677                                 }
678                         }
679                         /* Didn't find it. Invalid. */
680                         return 0;
681                 }
682         }
683         /* Not valid argument */
684         return 0;
685 d148 1
686 a148 1
687         while (IS_SPACE(s[*i])) (*i)++;
688 d156 7
689 a162 7
690         int i;
691         /* Compare to all delimiters */
692         for (i=0; i<strlen(delim)+1; i++) {
693                 if (delim[i] == c) return 1;
694         }
695         /* Not a delimiter */
696         return 0;
697 d174 36
698 a209 36
699         unsigned char c;
700         int j = 0;
701         dest[0] = '\0';
702         while (1) {
703                 /* Get next character */
704                 c = s[*i];
705                 /* Test if token delimiter */
706                 if (is_delim(c, delim)) {
707                         /* End token */
708                         dest[j] = '\0';
709                         return;
710                 }
711                 else {
712                         /* check if escape character */
713                         if (c == '\\') {
714                                 /* Increase i */
715                                 (*i)++;
716                                 /* Get next character */
717                                 c = s[*i];
718                                 /* Convert to C escape char if applicable */
719                                 switch (c) {
720                                         case '0':       c = '\0';       break;
721                                         case 'a':       c = '\a';       break;
722                                         case 'b':       c = '\b';       break;
723                                         case 't':       c = '\t';       break;
724                                         case 'f':       c = '\f';       break;
725                                         case 'n':       c = '\n';       break;
726                                         case 'r':       c = '\r';       break;
727                                 }
728                         }
729                         /* Copy to dest */
730                         dest[j++] = c;
731                         /* Increase i */
732                         (*i)++;
733                 }
734         }
735 d222 2
736 a223 2
737         va_list ap;
738         va_start(ap, fmt);
739 d225 4
740 a228 4
741         /* Print error message w/ location info */
742         fprintf(stderr, "error: %s:%d: ", filename, line);
743         vfprintf(stderr, fmt, ap);
744         fprintf(stderr, "\n");
745 d230 1
746 a230 1
747         va_end(ap);
748 d242 11
749 a252 11
750         command_arg *a;
751         if (cmd->first_arg == NULL) {
752                 /* Start list */
753                 cmd->first_arg = arg;
754         }
755         else {
756                 /* Add to end of list */
757                 for (a = cmd->first_arg; a->next != NULL; a = a->next) ;
758                 a->next = arg;
759         }
760         arg->next = NULL;
761 d262 11
762 a272 11
763         script_command *c;
764         if (sc->first_command == NULL) {
765                 /* Start list */
766                 sc->first_command = cmd;
767         }
768         else {
769                 /* Add to end of list */
770                 for (c = sc->first_command; c->next != NULL; c = c->next) ;
771                 c->next = cmd;
772         }
773         cmd->next = NULL;
774 d281 10
775 a290 10
776         command_arg *a;
777         command_arg *t;
778         /* Finalize all arguments */
779         for(a = cmd->first_arg; a != NULL; a = t) {
780                 t = a->next;
781                 SAFE_FREE(a->key);
782                 SAFE_FREE(a->value);
783                 SAFE_FREE(a);
784         }
785         SAFE_FREE(cmd);
786 d300 6
787 a305 6
788         for (; map->proc != NULL; map += 1) {
789                 if (map->type == type) {
790                         return map->proc;
791                 }
792         }
793         return NULL;
794 d318 131
795 a448 131
796         FILE *fp;
797         command_arg *arg;
798         script_command *cmd;
799         command_type type;
800         int i;
801         char line[1024];
802         char cmdname[256];
803         char argname[256];
804         char argvalue[256];
805         static int lineno = 0;
806         sc->name = filename;
807         sc->first_command = NULL;
808         /* Attempt to open script */
809         fp = fopen(filename, "rt");
810         if (fp == NULL) {
811                 fprintf(stderr, "error: could not open `%s' for reading\n", filename);
812                 return 0;
813         }
814         /* Read commands */
815         while (fgets(line, 1023, fp) != NULL) {
816                 /* Increase line number */
817                 lineno++;
818                 /* Skip white space */
819                 i = 0;
820                 eat_ws(line, &i);
821                 /* Skip line if comment or end */
822                 if ( (line[i] == '#') || (line[i] == '\0') || (line[i] == '\n') ) continue;
823                 /* Get command name */
824                 get_token(line, &i, " \t{", cmdname);
825                 /* Check that it's a valid command */
826                 if (strlen(cmdname) == 0) {
827                         err(filename, lineno, "command expected");
828                         continue;
829                 }
830                 else {
831                         /* Convert from string to command type */
832                         type = string_to_command_type(cmdname);
833                         if (type == BAD_COMMAND) {
834                                 err(filename, lineno, "unknown command `%s'", cmdname);
835                                 continue;
836                         }
837                         else {
838                                 /* Allocate space for command */
839                                 cmd = (script_command *)malloc( sizeof(script_command) );
840                                 if (cmd != NULL) {
841                                         /* Set the type */
842                                         cmd->type = type;
843                                         /* No arguments (yet) */
844                                         cmd->first_arg = NULL;
845                                         /* Store line number */
846                                         cmd->line = lineno;
847                                         /* Add command to script */
848                                         add_command(sc, cmd);
849                                 }
850                         }
851                 }
852                 /* Skip white space */
853                 eat_ws(line, &i);
854                 /* Next token should be '{' */
855                 if (line[i] != '{') {
856                         err(filename, lineno, "{ expected");
857                         continue;
858                 }
859                 i++;    /* Eat '{' */
860                 /* Get argument(s) */
861                 while (line[i] != '}') {
862                         if (line[i] == '\0') {
863                                 break;
864                         }
865                         /* */
866                         if (cmd->first_arg != NULL) {
867                                 /* Skip white space */
868                                 eat_ws(line, &i);
869                                 /* Next token should be , */
870                                 if (line[i] != ',') {
871                                         err(filename, lineno, ", expected");
872                                         continue;
873                                 }
874                                 i++;    /* Eat , */
875                         }
876                         /* Skip white space */
877                         eat_ws(line, &i);
878                         /* Get argument name */
879                         get_token(line, &i, " \t=", argname);
880                         if (strlen(argname) == 0) {
881                                 err(filename, lineno, "argument name expected");
882                                 continue;
883                         }
884                         /* Skip white space */
885                         eat_ws(line, &i);
886                         /* Next token should be '=' */
887                         if (line[i] != '=') {
888                                 err(filename, lineno, "= expected");
889                                 continue;
890                         }
891                         i++;    /* Eat '=' */
892                         /* Skip white space */
893                         eat_ws(line, &i);
894                         /* Get value */
895                         get_token(line, &i, " \t},", argvalue);
896                         if (strlen(argvalue) == 0) {
897                                 err(filename, lineno, "value expected for argument `%s'", argname);
898                                 continue;
899                         }
900                         // Check if the argument name is valid for this command */
901                         if (is_valid_command_arg(cmd->type, argname) ) {
902                                 /* Create argument struct */
903                                 arg = (command_arg *)malloc( sizeof(command_arg) );
904                                 if (arg != NULL) {
905                                         arg->key = (char *)malloc( strlen(argname)+1 );
906                                         arg->value = (char *)malloc( strlen(argvalue)+1 );
907                                         /* Copy fields */
908                                         strcpy(arg->key, argname);
909                                         strcpy(arg->value, argvalue);
910                                         /* Store argument in list */
911                                         add_arg(cmd, arg);
912                                 }
913                         }
914                         else {
915                                 /* Not valid argument name */
916                                 err(filename, lineno, "invalid argument `%s'", argname);
917                                 continue;
918                         }
919                         /* Skip white space */
920                         eat_ws(line, &i);
921                 }
922         }
923         /* Close script */
924         fclose(fp);
925         /* Success */
926         return 1;
927 d457 7
928 a463 7
929         script_command *c;
930         script_command *t;
931         if (sc == NULL) { return; }
932         for(c = sc->first_command; c != NULL; c = t) {
933                 t = c->next;
934                 finalize_command(c);
935         }
936 d473 5
937 a477 5
938         script_command *c;
939         int i;
940         if (sc == NULL) { return 0; }
941         for (i=0, c=sc->first_command; c != NULL; i++, c = c->next) ;
942         return i;
943 d487 5
944 a491 5
945         script_command *c;
946         int i;
947         if (sc == NULL) { return NULL; }
948         for (i=0, c=sc->first_command; (c != NULL) && (i != index); i++, c = c->next) ;
949         return c;
950 d501 11
951 a511 11
952         script_command *c;
953         script_commandproc p;
954         if (sc == NULL) { return; }
955         /* Walk all the commands */
956         for (c=sc->first_command; c != NULL; c = c->next) {
957                 /* Process this command if it has a processor function */
958                 p = command_type_to_proc(c->type, map);
959                 if (p != NULL) {
960                         p(sc, c, arg);
961                 }
962         }
963 d521 11
964 a531 11
965         command_arg *a;
966         if (c == NULL) { return NULL; }
967         /* Go through all args */
968         for (a = c->first_arg; a != NULL; a = a->next) {
969                 if (strcmp(key, a->key) == 0) {
970                         /* Found it, return its value */
971                         return a->value;
972                 }
973         }
974         /* Not found */
975         return NULL;
976 d540 13
977 a552 13
978         switch (type) {
979                 case RAM_COMMAND:       return "ram";
980                 case OUTPUT_COMMAND:    return "output";
981                 case COPY_COMMAND:      return "copy";
982                 case BANK_COMMAND:      return "bank";
983                 case LINK_COMMAND:      return "link";
984                 case OPTIONS_COMMAND:   return "options";
985                 case PAD_COMMAND:       return "pad";
986                 default:
987                 /* Invalid command */
988                 break;
989         }
990         return "Invalid command!";
991 d562 9
992 a570 9
993         script_command *c;
994         int count;
995         if (sc == NULL) { return 0; }
996         for (count=0, c=sc->first_command; c != NULL; c = c->next) {
997                 if (c->type == type) {
998                         count++;
999                 }
1000         }
1001         return count;
1007 @Initial revision
1009 text
1010 @d2 5
1011 a6 2
1012  * $Id$
1013  * $Log$
1014 d381 3