summaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1995-08-28 21:19:02 +0000
committerRoland McGrath <roland@gnu.org>1995-08-28 21:19:02 +0000
commitf9e0131559b629c913d55b9a7b3b72369cbd06c3 (patch)
tree9c0f786ea0ebf1a37c1512d1d07affee9590acf8 /boot
parentf3815078c0c3d297d65405ee136e6d53bb453d79 (diff)
Updated by Shantanu Goel, to accept action keywords only inside $(...) and
only variable values inside ${...}.
Diffstat (limited to 'boot')
-rw-r--r--boot/boot_script.c229
-rw-r--r--boot/boot_script.h29
2 files changed, 118 insertions, 140 deletions
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 <mach/mach_types.h>
#include <mach/message.h>
@@ -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 <mach.h>
#include <stdio.h>
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);