Cube  Diff

Differences From Artifact [b377b2846b]:

To Artifact [5ae3539b0c]:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15






16
17
18
19
20
21
22
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





-
-








+
+
+
+
+
+







// command.cpp: implements the parsing and execution of a tiny script language
// which is largely backwards compatible with the quake console language.

#include "cube.h"

#include <memory>

#import "Alias.h"
#import "Command.h"
#import "Identifier.h"
#import "OFString+Cube.h"
#import "Variable.h"

// contains ALL vars/commands/aliases
static OFMutableDictionary<OFString *, __kindof Identifier *> *identifiers;

static void
cleanup(char **string)
{
	free(*string);
}

void
alias(OFString *name, OFString *action)
{
	Alias *alias = identifiers[name];

	if (alias == nil) {
96
97
98
99
100
101
102
103
104


105
106
107


108
109

110
111

112
113
114
115
116
117

118
119
120
121
122

123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138


139
140
141
142
143
144
145
146
147
148
149










150
151
152

153
154

155
156
157
158



159
160

161
162
163
164
165
166
167
100
101
102
103
104
105
106


107
108
109


110
111
112

113
114

115
116
117
118
119
120

121
122
123
124
125

126
127
128
129
130
131
132
133
134
135
136
137
138
139
140


141
142
143










144
145
146
147
148
149
150
151
152
153
154
155

156
157

158
159



160
161
162
163

164
165
166
167
168
169
170
171







-
-
+
+

-
-
+
+

-
+

-
+





-
+




-
+














-
-
+
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+


-
+

-
+

-
-
-
+
+
+

-
+








	identifiers[name] = command;

	return false;
}

// parse any nested set of () or []
char *
parseexp(char *&p, int right)
static char *
parseexp(char **p, int right)
{
	int left = *p++;
	char *word = p;
	int left = *(*p)++;
	char *word = *p;
	for (int brak = 1; brak;) {
		int c = *p++;
		int c = *(*p)++;
		if (c == '\r')
			*(p - 1) = ' '; // hack
			*(*p - 1) = ' '; // hack
		if (c == left)
			brak++;
		else if (c == right)
			brak--;
		else if (!c) {
			p--;
			(*p)--;
			conoutf(@"missing \"%c\"", right);
			return NULL;
		}
	}
	char *s = strndup(word, p - word - 1);
	char *s = strndup(word, *p - word - 1);
	if (left == '(') {
		OFString *t;
		@try {
			t = [OFString
			    stringWithFormat:@"%d", execute(@(s), true)];
		} @finally {
			free(s);
		}
		s = strdup(t.UTF8String);
	}
	return s;
}

// parse single argument, including expressions
char *
parseword(char *&p)
static char *
parseword(char **p)
{
	p += strspn(p, " \t\r");
	if (p[0] == '/' && p[1] == '/')
		p += strcspn(p, "\n\0");
	if (*p == '\"') {
		p++;
		char *word = p;
		p += strcspn(p, "\"\r\n\0");
		char *s = strndup(word, p - word);
		if (*p == '\"')
			p++;
	(*p) += strspn(*p, " \t\r");
	if ((*p)[0] == '/' && (*p)[1] == '/')
		*p += strcspn(*p, "\n\0");
	if (**p == '\"') {
		(*p)++;
		char *word = *p;
		*p += strcspn(*p, "\"\r\n\0");
		char *s = strndup(word, *p - word);
		if (**p == '\"')
			(*p)++;
		return s;
	}
	if (*p == '(')
	if (**p == '(')
		return parseexp(p, ')');
	if (*p == '[')
	if (**p == '[')
		return parseexp(p, ']');
	char *word = p;
	p += strcspn(p, "; \t\r\n\0");
	if (p - word == 0)
	char *word = *p;
	*p += strcspn(*p, "; \t\r\n\0");
	if (*p - word == 0)
		return NULL;
	return strndup(word, p - word);
	return strndup(word, *p - word);
}

// find value of ident referenced with $ in exp
OFString *
lookup(OFString *n)
{
	__kindof Identifier *identifier = identifiers[[n substringFromIndex:1]];
223
224
225
226
227
228
229

230
231


232
233
234
235
236
237
238
239
240
241
242
243
244
245

246
247
248
249
250
251
252
227
228
229
230
231
232
233
234


235
236
237
238
239
240
241
242
243
244
245
246
247
248
249

250
251
252
253
254
255
256
257







+
-
-
+
+













-
+







	return 0;
}

// all evaluation happens here, recursively
int
execute(OFString *string, bool isDown)
{
	char *copy __attribute__((__cleanup__(cleanup))) =
	std::unique_ptr<char> copy(strdup(string.UTF8String));
	char *p = copy.get();
	    strdup(string.UTF8String);
	char *p = copy;
	const int MAXWORDS = 25; // limit, remove
	OFString *w[MAXWORDS];
	int val = 0;
	for (bool cont = true; cont;) {
		// for each ; seperated statement
		int numargs = MAXWORDS;
		loopi(MAXWORDS)
		{
			// collect all argument values
			w[i] = @"";
			if (i > numargs)
				continue;
			// parse and evaluate exps
			char *s = parseword(p);
			char *s = parseword(&p);
			if (!s) {
				numargs = i;
				s = strdup("");
			}
			@try {
				if (*s == '$')
					// substitute variables
465
466
467
468
469
470
471

472
473
474







475
476
477
478
479
480
481
470
471
472
473
474
475
476
477



478
479
480
481
482
483
484
485
486
487
488
489
490
491







+
-
-
-
+
+
+
+
+
+
+







	return n + 1;
}

void
at(OFString *s_, OFString *pos)
{
	int n = pos.cube_intValue;
	char *copy __attribute__((__cleanup__(cleanup))) =
	std::unique_ptr<char> copy(strdup(s_.UTF8String));
	char *s = copy.get();
	loopi(n) s += strspn(s += strcspn(s, " \0"), " ");
	    strdup(s_.UTF8String);
	char *s = copy;
	loopi(n)
	{
		s += strcspn(s, " \0");
		s += strspn(s, " ");
	}
	s[strcspn(s, " \0")] = 0;
	concat(@(s));
}

COMMANDN(loop, loopa, ARG_2STR)
COMMANDN(while, whilea, ARG_2STR)
COMMANDN(if, ifthen, ARG_3STR)