Cube  Check-in [acc50da079]

Overview
Comment:Make execute() take an OFString
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: acc50da079501c3c301f3a742f14cdfe7ac4b6fd56a6ee46acb32cfbaa059dcf
User & Date: js on 2025-03-07 22:44:37
Other Links: manifest | tags
Context
2025-03-07
23:29
Clean up argument passing of commands check-in: 22520cd0d9 user: js tags: trunk
22:44
Make execute() take an OFString check-in: acc50da079 user: js tags: trunk
22:30
Migrate strings for all commands check-in: 11889bf242 user: js tags: trunk
Changes

Modified src/Command.mm from [91c3da5caf] to [b83be0b4d8].

74
75
76
77
78
79
80
81

82
83
84
85
86

87
88
89
90
91
92
93
74
75
76
77
78
79
80

81
82
83
84
85

86
87
88
89
90
91
92
93







-
+




-
+







	case ARG_DWN1:
		((void(__cdecl *)(bool, OFString *))_function)(
		    isDown, @(arguments[1]));
		break;
	case ARG_1EXP:
		if (isDown)
			return ((int(__cdecl *)(int))_function)(
			    execute(arguments[1]));
			    execute(@(arguments[1])));
		break;
	case ARG_2EXP:
		if (isDown)
			return ((int(__cdecl *)(int, int))_function)(
			    execute(arguments[1]), execute(arguments[2]));
			    execute(@(arguments[1])), execute(@(arguments[2])));
		break;
	case ARG_1EST:
		if (isDown)
			return ((int(__cdecl *)(OFString *))_function)(
			    @(arguments[1]));
		break;
	case ARG_2EST:

Modified src/clientgame.mm from [33b9c3010f] to [e005695b56].

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


5
6
7
8
9
10
11




-
-







// clientgame.cpp: core game related stuff

#include "cube.h"

#include <memory>

int nextmode = 0; // nextmode becomes gamemode after next map load
VAR(gamemode, 1, 0, 0);

void
mode(int n)
{
	addmsg(1, 2, SV_GAMEMODE, nextmode = n);
243
244
245
246
247
248
249
250
251
252
253

254
255
256
257
258
259
260
261
262
263
264
265
266
267
268

269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287


288
289

290
291
292
293
294
295
296
241
242
243
244
245
246
247




248

249
250
251
252
253
254
255
256
257
258
259
260
261

262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279


280
281
282

283
284
285
286
287
288
289
290







-
-
-
-
+
-













-
+

















-
-
+
+

-
+







void
updateworld(int millis) // main game update loop
{
	if (lastmillis) {
		curtime = millis - lastmillis;
		if (sleepwait && lastmillis > sleepwait) {
			sleepwait = 0;
			@autoreleasepool {
				std::unique_ptr<char> cmd(
				    strdup(sleepcmd.UTF8String));
				execute(cmd.get());
			execute(sleepcmd);
			}
		}
		physicsframe();
		checkquad(curtime);
		if (m_arena)
			arenarespawn();
		moveprojectiles((float)curtime);
		demoplaybackstep();
		if (!demoplayback) {
			if (getclientnum() >= 0)
				shoot(player1, worldpos); // only shoot when
				                          // connected to server
			gets2c(); // do this first, so we have most accurate
			          // information when our player moves
		};
		}
		otherplayers();
		if (!demoplayback) {
			monsterthink();
			if (player1->state == CS_DEAD) {
				if (lastmillis - player1->lastaction < 2000) {
					player1->move = player1->strafe = 0;
					moveplayer(player1, 10, false);
				} else if (!m_arena && !m_sp &&
				           lastmillis - player1->lastaction >
				               10000)
					respawn();
			} else if (!intermission) {
				moveplayer(player1, 20, true);
				checkitems();
			};
			c2sinfo(player1); // do this last, to reduce the
			                  // effective frame lag
		};
	};
		}
	}
	lastmillis = millis;
};
}

void
entinmap(dynent *
        d) // brute force but effective way to find a free spawn spot in the map
{
	loopi(100) // try max 100 times
	{

Modified src/commands.mm from [f53c401a17] to [f1b5888486].

131
132
133
134
135
136
137
138
139
140




141
142
143
144
145
146
147
131
132
133
134
135
136
137



138
139
140
141
142
143
144
145
146
147
148







-
-
-
+
+
+
+







			conoutf(@"missing \"%c\"", right);
			return NULL;
		}
	}
	char *s = newstring(word, p - word - 1);
	if (left == '(') {
		string t;
		itoa(t,
		    execute(
		        s)); // evaluate () exps directly, and substitute result
		// evaluate () exps directly, and substitute result
		@autoreleasepool {
			itoa(t, execute(@(s)));
		}
		s = exchangestr(s, t);
	}
	return s;
}

char *
parseword(char *&p) // parse single argument, including expressions
184
185
186
187
188
189
190

191

192



193
194
195
196




197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212


















213
214

215
216
217
218
219
220
221









222
223
224
225
226
227
228
229
230
231
232
233
234
235



236
237
238
239
240
241
242
185
186
187
188
189
190
191
192

193
194
195
196
197




198
199
200
201
















202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220

221







222
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







+
-
+

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

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

-

-







-
-
-
+
+
+







	}

	conoutf(@"unknown alias lookup: %s", n + 1);
	return n;
}

int
execute(
execute(char *p, bool isdown) // all evaluation happens here, recursively
    OFString *string, bool isdown) // all evaluation happens here, recursively
{
	@autoreleasepool {
		std::unique_ptr<char> copy(strdup(string.UTF8String));
		char *p = copy.get();
	const int MAXWORDS = 25; // limit, remove
	char *w[MAXWORDS];
	int val = 0;
	for (bool cont = true; cont;) // for each ; seperated statement
		const int MAXWORDS = 25; // limit, remove
		char *w[MAXWORDS];
		int val = 0;
		for (bool cont = true; cont;) {
	{
		int numargs = MAXWORDS;
		loopi(MAXWORDS) // collect all argument values
		{
			w[i] = "";
			if (i > numargs)
				continue;
			char *s = parseword(p); // parse and evaluate exps
			if (!s) {
				numargs = i;
				s = "";
			}
			if (*s == '$')
				s = lookup(s); // substitute variables
			w[i] = s;
		}
			// 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);
				if (!s) {
					numargs = i;
					s = "";
				}
				if (*s == '$')
					s = lookup(s); // substitute variables
				w[i] = s;
			}

		p += strcspn(p, ";\n\0");
			p += strcspn(p, ";\n\0");
		cont = *p++ !=
		       0; // more statements if this isn't the end of the string
		char *c = w[0];
		if (*c == '/')
			c++; // strip irc-style command prefix
		if (!*c)
			continue; // empty statement
			// more statements if this isn't the end of the string
			cont = *p++ != 0;
			char *c = w[0];
			// strip irc-style command prefix
			if (*c == '/')
				c++;
			// empty statement
			if (!*c)
				continue;

		@autoreleasepool {
			__kindof Identifier *identifier = identifiers[@(c)];

			if (identifier == nil) {
				val = ATOI(c);
				if (!val && *c != '0')
					conoutf(@"unknown command: %s", c);
			} else {
				if ([identifier
				        isKindOfClass:[Command class]]) {
					// game defined commands
					// use very ad-hoc function signature,
					// and just call it
					// game defined commands use very
					// ad-hoc function signature, and just
					// call it
					val = [identifier
					    callWithArguments:w
					         numArguments:numargs
					               isDown:isdown];
				} else if ([identifier
				               isKindOfClass:[Variable
				                                 class]]) {
263
264
265
266
267
268
269
270
271
272
273


274
275
276
277
278
279


280
281


282
283
284
285
286
287
288
270
271
272
273
274
275
276




277
278
279
280
281



282
283
284

285
286
287
288
289
290
291
292
293







-
-
-
-
+
+



-
-
-
+
+

-
+
+







							    stringWithFormat:
							        @"arg%d", i];
							alias(t, @(w[i]));
						}
					}
					// create new string here because alias
					// could rebind itself
					char *action = newstring(
					    [identifier action].UTF8String);
					val = execute(action, isdown);
					gp()->deallocstr(action);
					val = execute(
					    [[identifier action] copy], isdown);
					break;
				}
			}
		}
		loopj(numargs) gp()->deallocstr(w[j]);
	}
			loopj(numargs) gp()->deallocstr(w[j]);
		}

	return val;
		return val;
	}
}

// tab-completion of all identifiers

int completesize = 0, completeidx = 0;

void
341
342
343
344
345
346
347
348

349
350
351
352
353
354
355
346
347
348
349
350
351
352

353
354
355
356
357
358
359
360







-
+







		} @catch (id e) {
			return false;
		}

		// Ensure \0 termination.
		[data addItem:""];

		execute((char *)data.mutableItems);
		execute(@((char *)data.mutableItems));
		return true;
	}
}

void
exec(OFString *cfgfile)
{
423
424
425
426
427
428
429
430
431
432
433

434
435
436


437
438
439

440
441
442
443
444
445
446
447
448

449
450
451
452
453
454

455
456
457
458
459
460
461


462
463
464
465
466
467
468

469
470
471
472



473
474
475
476
477
478

479
480
481
482
483
484
485
486
428
429
430
431
432
433
434




435



436
437

438

439
440
441
442

443
444
445
446

447
448
449
450
451
452

453
454






455
456

457
458
459
460
461

462




463
464
465

466
467
468


469

470
471
472
473
474
475
476







-
-
-
-
+
-
-
-
+
+
-

-
+



-




-
+





-
+

-
-
-
-
-
-
+
+
-





-
+
-
-
-
-
+
+
+
-



-
-
+
-







		alias(name, [OFString stringWithFormat:@"%d", v]);
	}
}

void
ifthen(OFString *cond, OFString *thenp, OFString *elsep)
{
	@autoreleasepool {
		std::unique_ptr<char> cmd(strdup(
		    (cond.UTF8String[0] != '0' ? thenp : elsep).UTF8String));

	execute((![cond hasPrefix:@"0"] ? thenp : elsep));
		execute(cmd.get());
	}
}
}


void
loopa(OFString *times, OFString *body_)
loopa(OFString *times, OFString *body)
{
	@autoreleasepool {
		int t = (int)times.longLongValue;
		std::unique_ptr<char> body(strdup(body_.UTF8String));

		loopi(t)
		{
			intset(@"i", i);
			execute(body.get());
			execute(body);
		}
	}
}

void
whilea(OFString *cond_, OFString *body_)
whilea(OFString *cond, OFString *body)
{
	@autoreleasepool {
		std::unique_ptr<char> cond(strdup(cond_.UTF8String));
		std::unique_ptr<char> body(strdup(body_.UTF8String));

		while (execute(cond.get()))
			execute(body.get());
	while (execute(cond))
		execute(body);
	}
}

void
onrelease(bool on, OFString *body)
{
	if (!on) {
	if (!on)
		std::unique_ptr<char> copy(strdup(body.UTF8String));
		execute(copy.get());
	}
}
		execute(body);
}


void
concat(OFString *s)
{
	@autoreleasepool {
		alias(@"s", s);
	alias(@"s", s);
	}
}

void
concatword(OFString *s)
{
	// The original used this code which does nothing:
	// for (char *a = s, *b = s; *a = *b; b++)

Modified src/console.mm from [86266db4fd] to [2969d1193c].

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

6
7
8
9
10
11
12





-







// console.cpp: the console buffer, its display, and command line control

#include "cube.h"

#include <ctype.h>
#include <memory>

#import "KeyMapping.h"

struct cline {
	char *cref;
	int outtime;
};
169
170
171
172
173
174
175
176

177
178
179
180
181
182
183
184
185
168
169
170
171
172
173
174

175


176
177
178
179
180
181
182







-
+
-
-







void
history(int n)
{
	static bool rec = false;

	if (!rec && n >= 0 && n < vhistory.count) {
		rec = true;
		OFString *cmd = vhistory[vhistory.count - n - 1];
		execute(vhistory[vhistory.count - n - 1]);
		std::unique_ptr<char> copy(strdup(cmd.UTF8String));
		execute(copy.get());
		rec = false;
	}
}
COMMAND(history, ARG_1INT)

void
keypress(int code, bool isdown, int cooked)
245
246
247
248
249
250
251
252

253
254
255

256
257

258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273

274
275
276
277
278
279
280
281
242
243
244
245
246
247
248

249



250


251
252
253
254
255
256
257
258
259
260
261
262
263
264
265


266

267
268
269
270
271
272
273







-
+
-
-
-
+
-
-
+














-
-
+
-







							[vhistory
							    addObject:
							        [commandbuf
							            copy]];
						}
					}
					histpos = vhistory.count;
					if ([commandbuf hasPrefix:@"/"]) {
					if ([commandbuf hasPrefix:@"/"])
						std::unique_ptr<char> copy(
						    strdup(
						        commandbuf.UTF8String));
						execute(commandbuf, true);
						execute(copy.get(), true);
					} else
					else
						toserver(commandbuf);
				}
				saycommand(NULL);
			} else if (code == SDLK_ESCAPE) {
				saycommand(NULL);
			}
		}
	} else if (!menukey(code, isdown)) {
		// keystrokes go to menu

		for (KeyMapping *mapping in keyMappings) {
			if (mapping.code == code) {
				// keystrokes go to game, lookup in keymap and
				// execute
				string temp;
				strcpy_s(temp, mapping.action.UTF8String);
				execute(mapping.action, isdown);
				execute(temp, isdown);
				return;
			}
		}
	}
}

OFString *

Modified src/menus.mm from [1d03f1ff21] to [27b088d99d].

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


5
6
7
8
9
10
11




-
-







// menus.cpp: ingame menu system (also used for scores and serverlist)

#include "cube.h"

#include <memory>

#import "Menu.h"
#import "MenuItem.h"

static OFMutableArray<OFNumber *> *menuStack;
static OFMutableArray<Menu *> *menus;
static int vmenu = -1;

164
165
166
167
168
169
170
171
172

173
174
175
176
177
162
163
164
165
166
167
168


169
170
171
172
173
174







-
-
+






			if (menuStack == nil)
				menuStack = [[OFMutableArray alloc] init];

			[menuStack addObject:@(vmenu)];
			menuset(-1);

			std::unique_ptr<char> copy(strdup(action.UTF8String));
			execute(copy.get(), true);
			execute(action, true);
		}
	}

	return true;
}

Modified src/protos.h from [0b98b4aee6] to [cecc5f4a0e].

1
2
3
4
5
6
7
8
9
10

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

10
11
12
13
14
15
16
17









-
+







// protos for ALL external functions in cube...

// command
extern int variable(OFString *name, int min, int cur, int max, int *storage,
    void (*fun)(), bool persist);
extern void setvar(OFString *name, int i);
extern int getvar(OFString *name);
extern bool identexists(OFString *name);
extern bool addcommand(OFString *name, void (*fun)(), int narg);
extern int execute(char *p, bool down = true);
extern int execute(OFString *p, bool down = true);
extern void exec(OFString *cfgfile);
extern bool execfile(OFString *cfgfile);
extern void resetcomplete();
extern void complete(OFString *s);
extern void alias(OFString *name, OFString *action);
extern OFString *getalias(OFString *name);
extern void writecfg();

Modified src/serverbrowser.mm from [a2f42f1499] to [23e77d6100].

313
314
315
316
317
318
319

320

321


322
323
324
325
326
327
328
313
314
315
316
317
318
319
320

321

322
323
324
325
326
327
328
329
330







+
-
+
-
+
+







	uchar buf[MAXUPD];
	uchar *reply = retrieveservers(buf, MAXUPD);
	if (!*reply || strstr((char *)reply, "<html>") ||
	    strstr((char *)reply, "<HTML>"))
		conoutf(@"master server not replying");
	else {
		servers.setsize(0);
		@autoreleasepool {
		execute((char *)reply);
			execute(@((char *)reply));
	};
		}
	}
	servermenu();
}

COMMAND(addserver, ARG_1STR)
COMMAND(servermenu, ARG_NONE)
COMMAND(updatefrommaster, ARG_NONE)

Modified src/world.mm from [67fd387b5f] to [cee211ba17].

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


5
6
7
8
9
10
11




-
-







// world.cpp: core map management stuff

#include "cube.h"

#include <memory>

extern OFString *entnames[]; // lookup from map entities above to strings

sqr *world = NULL;
int sfactor, ssize, cubicsize, mipsize;

header hdr;

66
67
68
69
70
71
72
73

74
75

76
77
78
79
80
81
82
83
64
65
66
67
68
69
70

71


72

73
74
75
76
77
78
79







-
+
-
-
+
-







	if (!savegame && type != 3)
		playsound(S_RUMBLE);

	@autoreleasepool {
		OFString *aliasname =
		    [OFString stringWithFormat:@"level_trigger_%d", tag];

		if (identexists(aliasname)) {
		if (identexists(aliasname))
			std::unique_ptr<char> cmd(strdup(aliasname.UTF8String));
			execute(cmd.get());
			execute(aliasname);
		}
	}

	if (type == 2)
		endsp(false);
}
COMMAND(trigger, ARG_2INT)

498
499
500
501
502
503
504
505

506
507
508
509
510
511
512
494
495
496
497
498
499
500

501
502
503
504
505
506
507
508







-
+







	}

	calclight();
	startmap(@"base/unnamed");
	if (oldworld) {
		free(oldworld);
		toggleedit();
		execute("fullbright 1");
		execute(@"fullbright 1");
	}
}

void
mapenlarge()
{
	empty_world(-1, false);