/* 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; }
static void traverse_decl(ast_decl_t decl) { switch (decl->kind) { case AST_FUNCS_DECL: { list_t p = decl->u.funcs; for (; p; p = p->next) { ast_func_t func = p->data; list_t q; _depth++; sym_begin_scope(_env); for (q = func->params; q; q = q->next) { ast_field_t field = q->data; sym_enter(_env, field->name, escape_entry(_depth, &field->escape)); } traverse_expr(func->body); sym_end_scope(_env); _depth--; } break; } case AST_TYPES_DECL: break; case AST_VAR_DECL: sym_enter(_env, decl->u.var.var, escape_entry(_depth, &decl->u.var.escape)); traverse_expr(decl->u.var.init); break; } }
/* Define the function NAME, which will return type RET_TYPE. */ int boot_script_define_function (const char *name, int ret_type, int (*func) (const struct cmd *cmd, int *val)) { struct sym *sym = sym_enter (name); if (sym) { sym->type = VAL_FUNC; sym->val = (int) func; sym->ret_type = ret_type; sym->run_on_exec = ret_type == VAL_NONE; } return sym ? 0 : 1; }
static t_stat symset_cmd(int32 arg, CONST char* buf) { const char *name,*vstr; char gbuf[2*CBUFSIZE]; t_addr val; gbuf[sizeof(gbuf)-1] = '\0'; strncpy(gbuf, buf, sizeof(gbuf)-1); if ((name = strtok(gbuf, "= ")) == 0) return SCPE_2FARG; if ((vstr = strtok(NULL, " \t\n")) == 0) return SCPE_2FARG; val = strtol(vstr, 0, 16); if (!sym_enter(name, val)) printf("Name or value already exists\n"); return SCPE_OK; }
static void traverse_expr(ast_expr_t expr) { list_t p; switch (expr->kind) { case AST_NIL_EXPR: break; case AST_VAR_EXPR: traverse_var(expr->u.var); break; case AST_NUM_EXPR: case AST_STRING_EXPR: break; case AST_CALL_EXPR: for (p = expr->u.call.args; p; p = p->next) traverse_expr(p->data); break; case AST_OP_EXPR: traverse_expr(expr->u.op.left); traverse_expr(expr->u.op.right); break; case AST_RECORD_EXPR: for (p = expr->u.record.efields; p; p = p->next) traverse_expr(((ast_efield_t) p->data)->expr); break; case AST_ARRAY_EXPR: traverse_expr(expr->u.array.size); traverse_expr(expr->u.array.init); break; case AST_SEQ_EXPR: for (p = expr->u.seq; p; p = p->next) traverse_expr(p->data); break; case AST_IF_EXPR: traverse_expr(expr->u.if_.cond); traverse_expr(expr->u.if_.then); if (expr->u.if_.else_) traverse_expr(expr->u.if_.else_); break; case AST_WHILE_EXPR: traverse_expr(expr->u.while_.cond); traverse_expr(expr->u.while_.body); break; case AST_FOR_EXPR: traverse_expr(expr->u.for_.lo); traverse_expr(expr->u.for_.hi); sym_begin_scope(_env); sym_enter(_env, expr->u.for_.var, escape_entry(_depth, &expr->u.for_.escape)); traverse_expr(expr->u.for_.body); sym_end_scope(_env); break; case AST_BREAK_EXPR: break; case AST_LET_EXPR: sym_begin_scope(_env); for (p = expr->u.let.decls; p; p = p->next) traverse_decl(p->data); traverse_expr(expr->u.let.body); sym_end_scope(_env); break; case AST_ASSIGN_EXPR: traverse_var(expr->u.assign.var); traverse_expr(expr->u.assign.expr); break; } }
/* Parse the command line CMDLINE. */ int boot_script_parse_line (void *hook, char *cmdline) { char *p, *q; int error; struct cmd *cmd; struct arg *arg; /* Extract command name. Ignore line if it lacks a command. */ for (p = cmdline; *p == ' ' || *p == '\t'; p++) ; if (*p == '#') /* Ignore comment line. */ return 0; #if 0 if (*p && *p != ' ' && *p != '\t' && *p != '\n') { printf ("(bootstrap): %s\n", cmdline); } #endif for (q = p; *q && *q != ' ' && *q != '\t' && *q != '\n'; q++) ; if (p == q) return 0; *q = '\0'; /* Allocate a command structure. */ cmd = boot_script_malloc (sizeof (struct cmd)); if (! cmd) return BOOT_SCRIPT_NOMEM; memset (cmd, 0, sizeof (struct cmd)); cmd->hook = hook; cmd->path = p; p = q + 1; for (arg = 0;;) { if (! arg) { /* Skip whitespace. */ while (*p == ' ' || *p == '\t') p++; /* End of command line. */ if (! *p || *p == '\n') { /* Add command to list. */ if (add_list (cmd, (void ***) &cmds, &cmds_alloc, &cmds_index, 10)) { error = BOOT_SCRIPT_NOMEM; goto bad; } return 0; } } /* Look for a symbol. */ if (arg || (*p == '$' && (*(p + 1) == '{' || *(p + 1) == '('))) { char end_char = (*(p + 1) == '{') ? '}' : ')'; struct sym *sym = 0; for (p += 2;;) { char c; int i, val, type; struct sym *s; /* Parse symbol name. */ for (q = p; *q && *q != '\n' && *q != end_char && *q != '='; q++) ; if (p == q || ! *q || *q == '\n' || (end_char == '}' && *q != '}')) { error = BOOT_SCRIPT_SYNTAX_ERROR; goto bad; } c = *q; *q = '\0'; /* See if this is a builtin symbol. */ for (i = 0; i < NUM_BUILTIN; i++) if (! strcmp (p, builtin_symbols[i].name)) break; if (i < NUM_BUILTIN) s = &builtin_symbols[i]; else { /* Look up symbol in symbol table. If no entry exists, create one. */ s = sym_lookup (p); if (! s) { s = sym_enter (p); if (! s) { error = BOOT_SCRIPT_NOMEM; goto bad; } } } /* 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 == '=' && s->type == VAL_FUNC) { error = BOOT_SCRIPT_INVALID_ASG; goto bad; } /* For function symbols, execute the function. */ if (s->type == VAL_FUNC) { 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 (s->type == VAL_NONE) { type = VAL_SYM; val = (int) s; } else { type = s->type; val = s->val; } if (sym) { sym->type = type; sym->val = val; } else if (arg) { arg->type = type; arg->val = val; } out: p = q + 1; if (c == end_char) { /* Create an argument if necessary. We create an argument if the symbol appears 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 && end_char == '}') { if (! add_arg (cmd, 0, type, val)) { error = BOOT_SCRIPT_NOMEM; goto bad; } } arg = 0; break; } if (s->type != VAL_FUNC) sym = s; } } else { char c; /* Command argument; just copy the text. */ for (q = p;; q++) { if (! *q || *q == ' ' || *q == '\t' || *q == '\n') break; if (*q == '$' && *(q + 1) == '{') break; } c = *q; *q = '\0'; /* Add argument to list. */ arg = add_arg (cmd, p, VAL_NONE, 0); if (! arg) { error = BOOT_SCRIPT_NOMEM; goto bad; } if (c == '$') p = q; else { if (c) p = q + 1; else p = q; arg = 0; } } } bad: free_cmd (cmd, 1); cleanup (1); return error; }