1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
#include <pland/pcrt.h>
#include <knob/block.h>
#include <knob/task.h>
#include <knob/user.h>
#include "cmds.h"
#include "vars.h"
#define LINE_SIZE 4096
static char line[LINE_SIZE];
static void line_replace(const char *from) {
const char *fi = from;
char *ti = line;
while (*fi) {
if (ti == line + LINE_SIZE) {
tell_user_sz("Line too long.\n");
line[0] = '\0';
return;
}
if (*fi != '$') {
*ti = *fi;
++ti;
++fi;
continue;
}
const char *var_start = ++fi;
const char *var_end = var_start;
while (*var_end != '$')
if (!*var_end++) {
tell_user_sz("Unterminated variable name.\n");
line[0] = '\0';
return;
}
if (ti + (var_end - var_start) >= line + LINE_SIZE) {
tell_user_sz("Line too long.\n");
line[0] = '\0';
return;
}
struct no_null_sn vname = {
.data = var_start,
.length = var_end - var_start
};
const struct no_null_sn *vval = get_var(vname);
if (!vval)
vval = &vname;
blockcpy(ti, vval->data, vval->length);
ti += vval->length;
fi = var_end + 1;
}
*ti = '\0';
}
void run_line(const char *original_line) {
line_replace(original_line);
if (!*line)
return;
const char *space;
for (space = line; *space && (*space != ' '); ++space)
;
if (blockequ(line, "source ", 7))
source(space + 1);
else if (blockequ(line, "set ", 4))
set(space + 1);
else if (blockequ(line, "echo ", 5)) {
tell_user_sz(space + 1);
tell_user_sz("\n");
}
else if (blockequ(line, "vars", 5))
dump_vars();
else if (blockequ(line, "quit", 5))
__pcrt_quit();
else if (blockequ(line, "clear", 6))
_clear_screen();
else if (blockequ(line, "help", 5))
tell_user_sz("Highway is a command shell for Portland OS. It includes variables and a couple\n"
"of pseudo-commands. Variables are addressed by surrounding with \"$\". The\n"
"following list shows each of the pseudo-commands.\n\n"
" source FILE run each command in FILE\n"
" clear clear the screen\n"
" echo STRING print STRING\n"
" set VAR VALUE set $VAR$ to VALUE\n"
" vars dump variables\n"
" quit exit highway\n"
" help show this\n");
else if (!try_run_command_blocking(line)) {
struct no_null_sn arg = {
.data = "_path",
.length = 5
};
const struct no_null_sn *path = get_var(arg);
if (!path->length) {
tell_user_sz("Could not run command.\n");
return;
}
for (uint16_t to_i = LINE_SIZE - 1; to_i >= path->length; --to_i)
line[to_i] = line[to_i - path->length];
blockcpy(line, path->data, path->length);
if (!try_run_command_blocking(line)) {
tell_user_sz("Could not run command.\n");
return;
}
}
}
|