From f9e0131559b629c913d55b9a7b3b72369cbd06c3 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Mon, 28 Aug 1995 21:19:02 +0000 Subject: Updated by Shantanu Goel, to accept action keywords only inside $(...) and only variable values inside ${...}. --- boot/boot_script.c | 229 ++++++++++++++++++++++++----------------------------- boot/boot_script.h | 29 +++---- 2 files changed, 118 insertions(+), 140 deletions(-) (limited to 'boot') diff --git a/boot/boot_script.c b/boot/boot_script.c index ca71ccc3..64548d4f 100644 --- a/boot/boot_script.c +++ b/boot/boot_script.c @@ -1,4 +1,6 @@ -/* Script parser for Mach. */ +/* Boot script parser for Mach. */ + +/* Written by Shantanu Goel (goel@cs.columbia.edu). */ #include #include @@ -36,11 +38,7 @@ struct cmd struct sym { /* Symbol name. */ - char *name; - - /* Pointer to function that returns symbol value. - The function should return 0 on success, non-zero otherwise. */ - int (*func) (struct cmd *cmd, int *val); + const char *name; /* Type of value returned by function. */ int type; @@ -48,22 +46,21 @@ struct sym /* Symbol value. */ int val; - /* If set, don't create an argument if the symbol - appears by itself in an expression. */ - int no_arg; + /* For function symbols; type of value returned by function. */ + int ret_type; - /* If set, execute function at the time of command execution, - not during parsing. A function with this field set must - also have `no_arg' set. Also, the function's `val' argument - will always be NULL. */ + /* For function symbols; if set, execute function at the time + of command execution, not during parsing. A function with + this field set must also have `no_arg' set. Also, the function's + `val' argument will always be NULL. */ int run_on_exec; }; -/* Type of values symbols can have. */ +/* Additional values symbols can take. + These are only used internally. */ #define VAL_NONE 0 /* none */ -#define VAL_STR 1 /* string */ -#define VAL_PORT 2 /* port */ #define VAL_SYM 3 /* symbol table entry */ +#define VAL_FUNC 4 /* function pointer */ /* This structure describes an argument. */ struct arg @@ -119,47 +116,11 @@ resume_task (struct cmd *cmd, int *val) return 0; } -/* Return a send right to the host port. */ -static int -get_host_port (struct cmd *cmd, int *val) -{ - *val = (int) boot_script_host_port; - return 0; -} - -/* Return a send right to the master device port. */ -static int -get_device_port (struct cmd *cmd, int *val) -{ - *val = (int) boot_script_device_port; - return 0; -} - -/* Return the root device name. */ -static int -get_root_device (struct cmd *cmd, int *val) -{ - *val = (int) boot_script_root_device; - return 0; -} - -/* Set the bootstrap port for a task. */ -static int -set_bootstrap_port (struct cmd *cmd, int *val) -{ - boot_script_set_bootstrap_port (cmd->task, boot_script_bootstrap_port); - return 0; -} - /* List of builtin symbols. */ static struct sym builtin_symbols[] = { - { "task-create", create_task, VAL_PORT, 0, 1, 0 }, - { "task-resume", resume_task, VAL_NONE, 0, 1, 1 }, - { "host-port", get_host_port, VAL_PORT, 0, 0, 0 }, - { "device-port", get_device_port, VAL_PORT, 0, 0, 0 }, - { "bootstrap-port", set_bootstrap_port, VAL_NONE, 0, 1, 0 }, - { "root-device", get_root_device, VAL_STR, 0, 0, 0 } + { "task-create", VAL_FUNC, (int) create_task, VAL_PORT, 0 }, + { "task-resume", VAL_FUNC, (int) resume_task, VAL_NONE, 1 } }; #define NUM_BUILTIN (sizeof (builtin_symbols) / sizeof (builtin_symbols[0])) @@ -266,7 +227,7 @@ add_arg (struct cmd *cmd, char *text, int type, int val) /* Search for the symbol NAME in the symbol table. */ static struct sym * -sym_lookup (char *name) +sym_lookup (const char *name) { int i; @@ -278,7 +239,7 @@ sym_lookup (char *name) /* Create an entry for symbol NAME in the symbol table. */ static struct sym * -sym_enter (char *name) +sym_enter (const char *name) { struct sym *sym; @@ -345,9 +306,9 @@ boot_script_parse_line (char *cmdline) } /* Look for a symbol. */ - if (arg || (*p == '$' && *(p + 1) == '{')) + if (arg || (*p == '$' && (*(p + 1) == '{' || *(p + 1) == '('))) { - int saw_assignment = 0; + char end_char = (*(p + 1) == '{') ? '}' : ')'; struct sym *sym = 0; for (p += 2;;) @@ -357,9 +318,10 @@ boot_script_parse_line (char *cmdline) struct sym *s; /* Parse symbol name. */ - for (q = p; *q && *q != '\n' && *q != '}' && *q != '='; q++) + for (q = p; *q && *q != '\n' && *q != end_char && *q != '='; q++) ; - if (p == q || ! *q || *q == '\n') + if (p == q || ! *q || *q == '\n' + || (end_char == '}' && *q != '}')) { error = BOOT_SCRIPT_SYNTAX_ERROR; goto bad; @@ -377,31 +339,51 @@ boot_script_parse_line (char *cmdline) is_builtin = 1; s = &builtin_symbols[i]; + /* Only values are allowed in ${...} constructs. */ + if (end_char == '}' && s->type == VAL_FUNC) + return BOOT_SCRIPT_INVALID_SYM; + /* Check that assignment is valid. */ - if (c != '}' || ((arg || sym) && s->type == VAL_NONE)) + if (end_char == ')' + && (c != end_char + || ((arg || sym) + && s->type == VAL_FUNC + && (s->run_on_exec + || s->ret_type == VAL_NONE)))) { error = BOOT_SCRIPT_INVALID_ASG; goto bad; } - if (! s->run_on_exec) + /* For function symbols, execute the function. */ + if (s->type == VAL_FUNC) { - error = (*s->func) (cmd, &val); - if (error) - goto bad; - type = s->type; + if (! s->run_on_exec) + { + (error + = ((*((int (*) (struct cmd *, int *)) s->val)) + (cmd, &val))); + if (error) + goto bad; + type = s->ret_type; + } + else + { + if (add_list (s, (void ***) &cmd->exec_funcs, + &cmd->exec_funcs_alloc, + &cmd->exec_funcs_index, 5)) + { + error = BOOT_SCRIPT_NOMEM; + goto bad; + } + type = VAL_NONE; + goto out; + } } else { - if (add_list (s, (void ***) &cmd->exec_funcs, - &cmd->exec_funcs_alloc, - &cmd->exec_funcs_index, 5)) - { - error = BOOT_SCRIPT_NOMEM; - goto bad; - } - type = VAL_NONE; - goto out; + type = s->type; + val = s->val; } } else @@ -435,26 +417,19 @@ boot_script_parse_line (char *cmdline) out: p = q + 1; - if (c == '}') + if (c == end_char) { /* Create an argument if necessary. We create an argument if the symbol appears - in the expression by itself, and it's `no_arg' - field is 0. + in the expression by itself. NOTE: This is temporary till the boot filesystem servers support arguments. When that happens, symbol values will only be printed if they're associated with an argument. */ - if (! arg && ! saw_assignment && ! s->no_arg) + if (! arg && end_char == '}') { - struct arg *a; - - if (is_builtin) - a = add_arg (cmd, 0, type, val); - else - a = add_arg (cmd, 0, VAL_SYM, (int) s); - if (! a) + if (! add_arg (cmd, 0, type, val)) { error = BOOT_SCRIPT_NOMEM; goto bad; @@ -463,8 +438,6 @@ boot_script_parse_line (char *cmdline) arg = 0; break; } - else - saw_assignment = 1; if (! is_builtin) sym = s; } @@ -473,7 +446,7 @@ boot_script_parse_line (char *cmdline) { char c; - /* Command argument. Just copy the text. */ + /* Command argument; just copy the text. */ for (q = p;; q++) { if (! *q || *q == ' ' || *q == '\t' || *q == '\n') @@ -560,7 +533,7 @@ boot_script_exec () memcpy (cmdline, cmd->path, cmdline_index); /* Allocate argument vector. */ - argv = boot_script_malloc (sizeof (char *) * (cmd->args_index + 1)); + argv = boot_script_malloc (sizeof (char *) * (cmd->args_index + 2)); if (! argv) { boot_script_free (cmdline, cmdline_alloc); @@ -591,8 +564,8 @@ boot_script_exec () /* Add value of any symbol associated with this argument. */ if (arg->type != VAL_NONE) { - char *p = 0, buf[50]; - int len = 0; + char *p, buf[50]; + int len; if (arg->type == VAL_SYM) { @@ -638,6 +611,10 @@ boot_script_exec () } while (i /= 10); break; + + default: + error = BOOT_SCRIPT_BAD_TYPE; + goto done; } len++; CHECK_CMDLINE_LEN (len); @@ -664,7 +641,7 @@ boot_script_exec () done: boot_script_free (cmdline, cmdline_alloc); - boot_script_free (argv, (cmd->args_index + 1) * sizeof (char *)); + boot_script_free (argv, (cmd->args_index + 2) * sizeof (char *)); if (error) { cleanup (1); @@ -682,7 +659,8 @@ boot_script_exec () for (i = 0; i < cmd->exec_funcs_index; i++) { struct sym *sym = cmd->exec_funcs[i]; - int error = (*sym->func) (cmd, 0); + int error = ((*((int (*) (struct cmd *, int *)) sym->val)) + (cmd, 0)); if (error) { cleanup (1); @@ -694,6 +672,21 @@ boot_script_exec () cleanup (0); return 0; } + +/* Create an entry for the variable NAME with TYPE and value VAL, + in the symbol table. */ +int +boot_script_set_variable (const char *name, int type, int val) +{ + struct sym *sym = sym_enter (name); + + if (sym) + { + sym->type = type; + sym->val = val; + } + return sym ? 0 : 1; +} /* Return a string describing ERR. */ char * @@ -718,22 +711,23 @@ boot_script_error_string (int err) case BOOT_SCRIPT_EXEC_ERROR: return "exec error"; + + case BOOT_SCRIPT_INVALID_SYM: + return "invalid variable in expression"; + + case BOOT_SCRIPT_BAD_TYPE: + return "invalid value type"; } return 0; } #ifdef BOOT_SCRIPT_TEST -#include #include extern void *malloc (int size); extern void free (void *ptr); -char *boot_script_root_device = "hd0a"; mach_port_t boot_script_task_port; -mach_port_t boot_script_host_port; -mach_port_t boot_script_device_port; -mach_port_t boot_script_bootstrap_port = MACH_PORT_NULL; void * boot_script_malloc (int size) @@ -750,32 +744,24 @@ boot_script_free (void *ptr, int size) mach_port_t boot_script_task_create () { - mach_port_t task; + static mach_port_t task = 10; - if (task_create (mach_task_self (), FALSE, &task)) - return 0; - return task; + return task++; } void boot_script_task_terminate (mach_port_t task) { - task_terminate (task); } void boot_script_task_suspend (mach_port_t task) { - task_suspend (task); } int boot_script_task_resume (mach_port_t task) { - mach_port_t bootport; - - task_get_bootstrap_port (task, &bootport); - printf ("bootstrap port %d\n", bootport); printf ("boot_script_task_resume()\n"); return 0; } @@ -783,30 +769,22 @@ boot_script_task_resume (mach_port_t task) void boot_script_port_deallocate (mach_port_t task, mach_port_t port) { - mach_port_deallocate (task, port); } int boot_script_port_insert_right (mach_port_t task, mach_port_t name, mach_port_t port, mach_msg_type_name_t right) { - if (mach_port_insert_right (task, name, port, right)) - return 1; return 0; } -void -boot_script_set_bootstrap_port (mach_port_t task, mach_port_t port) -{ - task_set_bootstrap_port (task, port); -} - int boot_script_exec_cmd (mach_port_t task, char *path, int argc, char **argv, char *strings, int stringlen) { int i; + printf ("port = %d: ", (int) task); for (i = 0; i < argc; i++) printf ("%s ", argv[i]); printf ("\n"); @@ -819,6 +797,7 @@ main (int argc, char **argv) char buf[500], *p; int len; FILE *fp; + mach_port_t host_port, device_port; if (argc < 2) { @@ -831,14 +810,12 @@ main (int argc, char **argv) fprintf (stderr, "Can't open %s\n", argv[1]); exit (1); } - boot_script_task_port = mach_task_self (); - boot_script_host_port = task_by_pid (-1); - boot_script_device_port = task_by_pid (-2); - if (! boot_script_host_port || ! boot_script_device_port) - { - fprintf (stderr, "Unable to get privileged ports\n"); - exit (1); - } + host_port = 1; + device_port = 2; + boot_script_set_variable ("host-port", VAL_PORT, (int) host_port); + boot_script_set_variable ("device-port", VAL_PORT, (int) device_port); + boot_script_set_variable ("root-device", VAL_STR, (int) "hd0a"); + boot_script_set_variable ("boot-args", VAL_STR, (int) "-ad"); p = buf; len = sizeof (buf); while (fgets (p, len, fp)) diff --git a/boot/boot_script.h b/boot/boot_script.h index 88a6bf49..1166232b 100644 --- a/boot/boot_script.h +++ b/boot/boot_script.h @@ -1,3 +1,7 @@ +/* Definitions for boot script parser for Mach. */ + +/* Written by Shantanu Goel (goel@cs.columbia.edu). */ + /* Error codes returned by boot_script_parse_line() and boot_script_exec_cmd(). */ #define BOOT_SCRIPT_NOMEM 1 @@ -6,25 +10,17 @@ #define BOOT_SCRIPT_MACH_ERROR 4 #define BOOT_SCRIPT_UNDEF_SYM 5 #define BOOT_SCRIPT_EXEC_ERROR 6 +#define BOOT_SCRIPT_INVALID_SYM 7 +#define BOOT_SCRIPT_BAD_TYPE 8 -/* The user must define this variable. The root device name. - This must be initialized prior to calling the parser. */ -extern char *boot_script_root_device; +/* Legal values for argument `type' to function + boot_script_set_variable(). */ +#define VAL_STR 1 /* string */ +#define VAL_PORT 2 /* port */ /* The user must define this variable. The task port of the program. */ extern mach_port_t boot_script_task_port; -/* The user must define this variable. Send right to the host port. */ -extern mach_port_t boot_script_host_port; - -/* The user must define this variable. Send right to the - master device port. */ -extern mach_port_t boot_script_device_port; - -/* The user must define this variable. Send right to the - the bootstrap port. */ -extern mach_port_t boot_script_bootstrap_port; - /* The user must define this function. Allocate SIZE bytes of memory and return a pointer to it. */ void *boot_script_malloc (int size); @@ -87,5 +83,10 @@ int boot_script_parse_line (char *cmdline); Returns 0 for success, non-zero otherwise. */ int boot_script_exec (void); +/* Create an entry in the symbol table for variable NAME, + whose type is TYPE and value is VAL. Returns 0 on success, + non-zero otherwise. */ +int boot_script_set_variable (const char *name, int type, int val); + /* Returns a string describing the error ERR. */ char *boot_script_error_string (int err); -- cgit v1.2.3