2007-01-03 03:11:53 +00:00
|
|
|
/*! \file unparse.cpp
|
|
|
|
|
* \brief Produces human-readable key info from boolexps.
|
|
|
|
|
*
|
|
|
|
|
*/
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
#include "copyright.h"
|
|
|
|
|
#include "autoconf.h"
|
|
|
|
|
#include "config.h"
|
|
|
|
|
#include "externs.h"
|
|
|
|
|
|
|
|
|
|
// Boolexp decompile formats
|
|
|
|
|
//
|
|
|
|
|
#define F_EXAMINE 1 // Normal
|
|
|
|
|
#define F_QUIET 2 // Binary for db dumps
|
|
|
|
|
#define F_DECOMPILE 3 // @decompile output
|
|
|
|
|
#define F_FUNCTION 4 // [lock()] output
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Take a dbref (loc) and generate a string. -1, -3, or (#loc) Note, this
|
|
|
|
|
* will give players object numbers of stuff they don't control, but it's
|
|
|
|
|
* only internal currently, so it's not a problem.
|
|
|
|
|
*/
|
|
|
|
|
|
2007-03-14 00:55:08 +00:00
|
|
|
static UTF8 *unparse_object_quiet(dbref player, dbref loc)
|
2006-09-01 22:59:23 +00:00
|
|
|
{
|
|
|
|
|
UNUSED_PARAMETER(player);
|
|
|
|
|
|
Convert all static scratch buffers to thread_local
43 static scratch-buffer arrays across 21 files (5 in mux/src, 38 in
mux/modules/) changed from `static` to `thread_local`. Under the
current single-threaded evaluator this is a zero-behavior-change swap
— `thread_local` storage has the same lifetime and zero-allocation
properties as `static` — but each thread gets its own copy, which
makes these functions safe for a future multi-threaded evaluator
without any locking.
Read-only constant tables (`aRadix64`, `aRadixPenn36`,
`aRadixPenn64`, `Empty`) left as `static` because they are immutable
shared data.
Affected areas:
net.cpp — queue_string co_buf, trimmed_site, dump_users NameField
signals.cpp — signal_desc
stubslave.cpp — Stub_PipePump
attrcache.cpp — sqlite_attr_buf
boolexp.cpp — parsestore
command.cpp — preserve_cmd, SpaceCompressCommand, LowerCaseCommand
comsys.cpp — NewTitle, Buffer, temp
db.cpp — tbuff, Buffer (x2)
flags.cpp — buff
funceval.cpp — textbuff
functions.cpp — TimeBuffer64, TimeBuffer80, Buffer
help.cpp — Line, Buffer
mail.cpp — aFolders, Buffer, res, szFittedMailAliasDesc
match.cpp — buffer
player.cpp — szSalt, buf (x2), buff
plusemail.cpp — buf
predicates.cpp — Buf (x2), pName
session.cpp — szFittedDoing
set.cpp — pRestrictedKeyText
unparse.cpp — buf, boolexp_buf
mail_mod.cpp — result, res, buf
All 21 files verified with g++ -std=c++17 -fsyntax-only.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 17:21:14 -06:00
|
|
|
thread_local UTF8 buf[SBUF_SIZE];
|
2006-09-01 22:59:23 +00:00
|
|
|
|
2008-12-27 18:37:01 -08:00
|
|
|
mux_sprintf(buf, SBUF_SIZE, T("(#%d)"), loc);
|
2007-03-14 22:33:04 +00:00
|
|
|
return buf;
|
2006-09-01 22:59:23 +00:00
|
|
|
}
|
|
|
|
|
|
Convert all static scratch buffers to thread_local
43 static scratch-buffer arrays across 21 files (5 in mux/src, 38 in
mux/modules/) changed from `static` to `thread_local`. Under the
current single-threaded evaluator this is a zero-behavior-change swap
— `thread_local` storage has the same lifetime and zero-allocation
properties as `static` — but each thread gets its own copy, which
makes these functions safe for a future multi-threaded evaluator
without any locking.
Read-only constant tables (`aRadix64`, `aRadixPenn36`,
`aRadixPenn64`, `Empty`) left as `static` because they are immutable
shared data.
Affected areas:
net.cpp — queue_string co_buf, trimmed_site, dump_users NameField
signals.cpp — signal_desc
stubslave.cpp — Stub_PipePump
attrcache.cpp — sqlite_attr_buf
boolexp.cpp — parsestore
command.cpp — preserve_cmd, SpaceCompressCommand, LowerCaseCommand
comsys.cpp — NewTitle, Buffer, temp
db.cpp — tbuff, Buffer (x2)
flags.cpp — buff
funceval.cpp — textbuff
functions.cpp — TimeBuffer64, TimeBuffer80, Buffer
help.cpp — Line, Buffer
mail.cpp — aFolders, Buffer, res, szFittedMailAliasDesc
match.cpp — buffer
player.cpp — szSalt, buf (x2), buff
plusemail.cpp — buf
predicates.cpp — Buf (x2), pName
session.cpp — szFittedDoing
set.cpp — pRestrictedKeyText
unparse.cpp — buf, boolexp_buf
mail_mod.cpp — result, res, buf
All 21 files verified with g++ -std=c++17 -fsyntax-only.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 17:21:14 -06:00
|
|
|
thread_local UTF8 boolexp_buf[LBUF_SIZE];
|
2007-03-14 00:55:08 +00:00
|
|
|
static UTF8 *buftop;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
2007-03-14 00:55:08 +00:00
|
|
|
static void unparse_boolexp1(dbref player, BOOLEXP *b, UTF8 outer_type, int format)
|
2006-09-01 22:59:23 +00:00
|
|
|
{
|
2013-09-10 20:07:52 -06:00
|
|
|
if (TRUE_BOOLEXP == b)
|
2006-09-01 22:59:23 +00:00
|
|
|
{
|
|
|
|
|
if (format == F_EXAMINE)
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
safe_str(T("*UNLOCKED*"), boolexp_buf, &buftop);
|
2006-09-01 22:59:23 +00:00
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
switch (b->type)
|
|
|
|
|
{
|
|
|
|
|
case BOOLEXP_AND:
|
|
|
|
|
if (outer_type == BOOLEXP_NOT)
|
|
|
|
|
{
|
|
|
|
|
safe_chr('(', boolexp_buf, &buftop);
|
|
|
|
|
}
|
|
|
|
|
unparse_boolexp1(player, b->sub1, b->type, format);
|
|
|
|
|
safe_chr(AND_TOKEN, boolexp_buf, &buftop);
|
|
|
|
|
unparse_boolexp1(player, b->sub2, b->type, format);
|
|
|
|
|
if (outer_type == BOOLEXP_NOT)
|
|
|
|
|
{
|
|
|
|
|
safe_chr(')', boolexp_buf, &buftop);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case BOOLEXP_OR:
|
|
|
|
|
if (outer_type == BOOLEXP_NOT || outer_type == BOOLEXP_AND)
|
|
|
|
|
{
|
|
|
|
|
safe_chr('(', boolexp_buf, &buftop);
|
|
|
|
|
}
|
|
|
|
|
unparse_boolexp1(player, b->sub1, b->type, format);
|
|
|
|
|
safe_chr(OR_TOKEN, boolexp_buf, &buftop);
|
|
|
|
|
unparse_boolexp1(player, b->sub2, b->type, format);
|
|
|
|
|
if (outer_type == BOOLEXP_NOT || outer_type == BOOLEXP_AND)
|
|
|
|
|
{
|
|
|
|
|
safe_chr(')', boolexp_buf, &buftop);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case BOOLEXP_NOT:
|
|
|
|
|
safe_chr('!', boolexp_buf, &buftop);
|
|
|
|
|
unparse_boolexp1(player, b->sub1, b->type, format);
|
|
|
|
|
break;
|
|
|
|
|
case BOOLEXP_INDIR:
|
|
|
|
|
safe_chr(INDIR_TOKEN, boolexp_buf, &buftop);
|
|
|
|
|
unparse_boolexp1(player, b->sub1, b->type, format);
|
2026-03-03 19:24:03 -07:00
|
|
|
if (b->thing != A_LOCK)
|
|
|
|
|
{
|
|
|
|
|
// Reverse-lookup lock name from lock_sw[].
|
|
|
|
|
//
|
|
|
|
|
for (NAMETAB *nt = lock_sw; nt->name; nt++)
|
|
|
|
|
{
|
|
|
|
|
if (nt->flag == static_cast<unsigned int>(b->thing))
|
|
|
|
|
{
|
|
|
|
|
safe_chr('/', boolexp_buf, &buftop);
|
|
|
|
|
safe_str(nt->name, boolexp_buf, &buftop);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
break;
|
|
|
|
|
case BOOLEXP_IS:
|
|
|
|
|
safe_chr(IS_TOKEN, boolexp_buf, &buftop);
|
|
|
|
|
unparse_boolexp1(player, b->sub1, b->type, format);
|
|
|
|
|
break;
|
|
|
|
|
case BOOLEXP_CARRY:
|
|
|
|
|
safe_chr(CARRY_TOKEN, boolexp_buf, &buftop);
|
|
|
|
|
unparse_boolexp1(player, b->sub1, b->type, format);
|
|
|
|
|
break;
|
|
|
|
|
case BOOLEXP_OWNER:
|
|
|
|
|
safe_chr(OWNER_TOKEN, boolexp_buf, &buftop);
|
|
|
|
|
unparse_boolexp1(player, b->sub1, b->type, format);
|
|
|
|
|
break;
|
|
|
|
|
case BOOLEXP_CONST:
|
|
|
|
|
|
|
|
|
|
if (mudstate.bStandAlone)
|
|
|
|
|
{
|
|
|
|
|
safe_str(unparse_object_quiet(player, b->thing),
|
|
|
|
|
boolexp_buf, &buftop);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
switch (format)
|
|
|
|
|
{
|
|
|
|
|
case F_QUIET:
|
|
|
|
|
|
|
|
|
|
// Quiet output - for dumps and internal use. Always #Num.
|
|
|
|
|
//
|
|
|
|
|
safe_str(unparse_object_quiet(player, b->thing),
|
|
|
|
|
boolexp_buf, &buftop);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case F_EXAMINE:
|
|
|
|
|
|
|
|
|
|
// Examine output - informative. Name(#Num) or Name.
|
|
|
|
|
//
|
2007-03-14 00:55:08 +00:00
|
|
|
UTF8 *buff;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
buff = unparse_object(player, b->thing, false);
|
|
|
|
|
safe_str(buff, boolexp_buf, &buftop);
|
|
|
|
|
free_lbuf(buff);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case F_DECOMPILE:
|
|
|
|
|
|
|
|
|
|
// Decompile output - should be usable on other MUXes. Name if
|
|
|
|
|
// player, Name if thing, else #Num.
|
|
|
|
|
//
|
|
|
|
|
switch (Typeof(b->thing))
|
|
|
|
|
{
|
|
|
|
|
case TYPE_PLAYER:
|
|
|
|
|
|
|
|
|
|
safe_chr('*', boolexp_buf, &buftop);
|
|
|
|
|
|
|
|
|
|
case TYPE_THING:
|
|
|
|
|
|
|
|
|
|
safe_str(Name(b->thing), boolexp_buf, &buftop);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
2008-12-27 18:37:01 -08:00
|
|
|
safe_tprintf_str(boolexp_buf, &buftop, T("#%d"), b->thing);
|
2006-09-01 22:59:23 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case F_FUNCTION:
|
|
|
|
|
|
|
|
|
|
// Function output - must be usable by @lock cmd. Name if player,
|
|
|
|
|
// else #Num.
|
|
|
|
|
//
|
|
|
|
|
switch (Typeof(b->thing))
|
|
|
|
|
{
|
|
|
|
|
case TYPE_PLAYER:
|
|
|
|
|
|
|
|
|
|
safe_chr('*', boolexp_buf, &buftop);
|
|
|
|
|
safe_str(Name(b->thing), boolexp_buf, &buftop);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
2008-12-27 18:37:01 -08:00
|
|
|
safe_tprintf_str(boolexp_buf, &buftop, T("#%d"), b->thing);
|
2006-09-01 22:59:23 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BOOLEXP_ATR:
|
|
|
|
|
case BOOLEXP_EVAL:
|
|
|
|
|
ATTR *ap;
|
|
|
|
|
|
|
|
|
|
ap = atr_num(b->thing);
|
|
|
|
|
if (ap && ap->number)
|
|
|
|
|
{
|
|
|
|
|
// Use the attribute name if the attribute exists.
|
|
|
|
|
//
|
2007-03-14 00:55:08 +00:00
|
|
|
safe_str(ap->name, boolexp_buf, &buftop);
|
2006-09-01 22:59:23 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Otherwise use the attribute number.
|
|
|
|
|
//
|
|
|
|
|
// Only god or the db loader can create a new boolexp
|
|
|
|
|
// with an invalid attribute, but anyone may keep a lock
|
|
|
|
|
// whose attribute has subsequently disappeared.
|
|
|
|
|
//
|
|
|
|
|
safe_ltoa(b->thing, boolexp_buf, &buftop);
|
|
|
|
|
}
|
|
|
|
|
if (b->type == BOOLEXP_EVAL)
|
|
|
|
|
{
|
|
|
|
|
safe_chr('/', boolexp_buf, &buftop);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
safe_chr(':', boolexp_buf, &buftop);
|
|
|
|
|
}
|
2026-03-03 18:39:35 -07:00
|
|
|
safe_str(reinterpret_cast<UTF8 *>(b->sub1), boolexp_buf, &buftop);
|
2006-09-01 22:59:23 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
|
|
// Bad type.
|
|
|
|
|
//
|
2007-03-14 22:33:04 +00:00
|
|
|
Log.WriteString(T("ABORT! unparse.cpp, fell off the end of switch in unparse_boolexp1()" ENDLINE));
|
2006-09-01 22:59:23 +00:00
|
|
|
Log.Flush();
|
|
|
|
|
abort();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2007-03-14 00:55:08 +00:00
|
|
|
UTF8 *unparse_boolexp_quiet(dbref player, BOOLEXP *b)
|
2006-09-01 22:59:23 +00:00
|
|
|
{
|
|
|
|
|
buftop = boolexp_buf;
|
|
|
|
|
unparse_boolexp1(player, b, BOOLEXP_CONST, F_QUIET);
|
|
|
|
|
*buftop = '\0';
|
|
|
|
|
return boolexp_buf;
|
|
|
|
|
}
|
|
|
|
|
|
2007-03-14 00:55:08 +00:00
|
|
|
UTF8 *unparse_boolexp(dbref player, BOOLEXP *b)
|
2006-09-01 22:59:23 +00:00
|
|
|
{
|
|
|
|
|
buftop = boolexp_buf;
|
|
|
|
|
unparse_boolexp1(player, b, BOOLEXP_CONST, F_EXAMINE);
|
|
|
|
|
*buftop = '\0';
|
|
|
|
|
return boolexp_buf;
|
|
|
|
|
}
|
|
|
|
|
|
2007-03-14 00:55:08 +00:00
|
|
|
UTF8 *unparse_boolexp_decompile(dbref player, BOOLEXP *b)
|
2006-09-01 22:59:23 +00:00
|
|
|
{
|
|
|
|
|
buftop = boolexp_buf;
|
|
|
|
|
unparse_boolexp1(player, b, BOOLEXP_CONST, F_DECOMPILE);
|
|
|
|
|
*buftop = '\0';
|
|
|
|
|
return boolexp_buf;
|
|
|
|
|
}
|
|
|
|
|
|
2007-03-14 00:55:08 +00:00
|
|
|
UTF8 *unparse_boolexp_function(dbref player, BOOLEXP *b)
|
2006-09-01 22:59:23 +00:00
|
|
|
{
|
|
|
|
|
buftop = boolexp_buf;
|
|
|
|
|
unparse_boolexp1(player, b, BOOLEXP_CONST, F_FUNCTION);
|
|
|
|
|
*buftop = '\0';
|
|
|
|
|
return boolexp_buf;
|
|
|
|
|
}
|