new internal printf engine for progs, mostly thanks to Deek.

also a few cleanup bits
This commit is contained in:
Bill Currie 2004-01-04 07:42:43 +00:00
parent 538d669887
commit dfe7f263c7
8 changed files with 495 additions and 361 deletions

View File

@ -127,6 +127,7 @@ qboolean PR_EdictValid (progs_t *pr, int e);
#define G_EDICT(p,o) ((edict_t *)(PR_edicts (p) + G_INT (p, o)))
#define G_EDICTNUM(p,o) NUM_FOR_EDICT(p, G_EDICT (p, o))
#define G_GSTRING(p,o) PR_GetString (p, G_STRING (p, o))
#define G_DSTRING(p,o) PR_GetDString (p, G_STRING (p, o))
#define G_GPOINTER(p,o) PR_GetPointer (p, o)
#define G_STRUCT(p,t,o) (*(t *)G_GPOINTER (p, o))
@ -143,6 +144,7 @@ qboolean PR_EdictValid (progs_t *pr, int e);
#define P_EDICT(p,n) ((edict_t *)(PR_edicts (p) + P_INT (p, n)))
#define P_EDICTNUM(p,n) NUM_FOR_EDICT (p, P_EDICT (p, n))
#define P_GSTRING(p,n) PR_GetString (p, P_STRING (p, n))
#define P_DSTRING(p,n) PR_GetDString (p, P_STRING (p, n))
#define P_GPOINTER(p,n) PR_GetPointer (p, P_POINTER (p, n))
#define P_STRUCT(p,t,n) (*(t *)P_GPOINTER (p, n))
@ -172,12 +174,13 @@ qboolean PR_EdictValid (progs_t *pr, int e);
#define E_POINTER(p,o) E_var (p, o, pointer)
#define E_GSTRING(p,e,o) (PR_GetString (p, E_STRING (e, o)))
#define E_DSTRING(p,e,o) (PR_GetDString (p, E_STRING (e, o)))
typedef void (*builtin_proc) (progs_t *pr);
typedef struct {
const char *name;
builtin_proc proc;
int first_statement;
int binum;
} builtin_t;
ddef_t *PR_FindGlobal (progs_t *pr, const char *name);
@ -224,9 +227,12 @@ const char *PR_GetString(progs_t *pr, int num);
struct dstring_s *PR_GetDString(progs_t *pr, int num);
int PR_SetString(progs_t *pr, const char *s);
int PR_SetTempString(progs_t *pr, const char *s);
void PR_MakeTempString(progs_t *pr, int str);
int PR_NewString (progs_t *pr);
void PR_FreeString (progs_t *pr, int str);
void PR_FreeTempStrings (progs_t *pr);
void PR_Sprintf (progs_t *pr, struct dstring_s *result, const char *name,
const char *format, int count, pr_type_t **args);
//
// PR Resources stuff

View File

@ -43,13 +43,11 @@ static __attribute__ ((unused)) const char rcsid[] =
#include <stdlib.h>
#include "QF/clip_hull.h"
#include "QF/cmd.h"
#include "QF/cvar.h"
#include "QF/dstring.h"
#include "QF/mathlib.h"
#include "QF/progs.h"
#include "QF/sys.h"
#include "QF/va.h"
#include "QF/zone.h"
#include "compat.h"
@ -58,9 +56,6 @@ const char *pr_gametype = "";
/* BUILT-IN FUNCTIONS */
// FIXME: Hunk_TempAlloc, Sys_Printf, Cvar_*, PR_SetString, PR_RunError, ED_PrintEdicts, PF_traceon, PF_traceoff, ED_PrintNum, PR_FindBuiltin isn't threadsafe/reentrant
char *
PF_VarString (progs_t *pr, int first)
{
@ -77,9 +72,7 @@ PF_VarString (progs_t *pr, int first)
}
/*
PF_normalize
vector normalize(vector)
vector (vector v) normalize
*/
static void
PF_normalize (progs_t *pr)
@ -107,9 +100,7 @@ PF_normalize (progs_t *pr)
}
/*
PF_vlen
scalar vlen(vector)
float (vector v) vlen
*/
static void
PF_vlen (progs_t *pr)
@ -127,9 +118,7 @@ PF_vlen (progs_t *pr)
}
/*
PF_vectoyaw
float vectoyaw(vector)
float (vector v) vectoyaw
*/
static void
PF_vectoyaw (progs_t *pr)
@ -151,9 +140,7 @@ PF_vectoyaw (progs_t *pr)
}
/*
PF_vectoangles
vector vectoangles(vector)
vector (vector v) vectoangles
*/
static void
PF_vectoangles (progs_t *pr)
@ -186,11 +173,9 @@ PF_vectoangles (progs_t *pr)
}
/*
PF_Random
float () random
Returns a number from 0<= num < 1
random()
*/
static void
PF_random (progs_t *pr)
@ -203,23 +188,17 @@ PF_random (progs_t *pr)
}
/*
PF_break
break()
void () break
*/
static void
PF_break (progs_t *pr)
{
Sys_Printf ("break statement\n");
//*(int *) -4 = 0; // dump to debugger
PR_DumpState (pr);
// PR_RunError (pr, "break statement");
}
/*
PF_cvar
float cvar (string)
float (string s) cvar
*/
static void
PF_cvar (progs_t *pr)
@ -232,9 +211,7 @@ PF_cvar (progs_t *pr)
}
/*
PF_cvar_set
float cvar (string)
void (string var, string val) cvar_set
*/
static void
PF_cvar_set (progs_t *pr)
@ -255,6 +232,9 @@ PF_cvar_set (progs_t *pr)
Cvar_Set (var, val);
}
/*
float (float f) fabs
*/
static void
PF_fabs (progs_t *pr)
{
@ -264,12 +244,14 @@ PF_fabs (progs_t *pr)
R_FLOAT (pr) = fabs (v);
}
// entity (entity start, .string field, string match) find = #5;
/*
entity (entity start, .(...) fld, ... match) find
*/
static void
PF_Find (progs_t *pr)
{
const char *s = 0, *t; // ev_string
int i; // ev_vector
const char *s = 0, *t; // ev_string
int i; // ev_vector
int e, f;
etype_t type;
ddef_t *field_def;
@ -326,36 +308,54 @@ PF_Find (progs_t *pr)
RETURN_EDICT (pr, *pr->edicts);
}
/*
void () coredump
*/
static void
PF_coredump (progs_t *pr)
{
ED_PrintEdicts (pr, "");
}
/*
void () traceon
*/
static void
PF_traceon (progs_t *pr)
{
pr->pr_trace = true;
}
/*
void () traceoff
*/
static void
PF_traceoff (progs_t *pr)
{
pr->pr_trace = false;
}
/*
void (entity e) eprint
*/
static void
PF_eprint (progs_t *pr)
{
ED_PrintNum (pr, P_EDICTNUM (pr, 0));
}
/*
void (string s) dprint
*/
static void
PF_dprint (progs_t *pr)
{
Sys_Printf ("%s", PF_VarString (pr, 0));
}
/*
float (float v) rint
*/
static void
PF_rint (progs_t *pr)
{
@ -368,12 +368,18 @@ PF_rint (progs_t *pr)
R_FLOAT (pr) = (int) (f - 0.5);
}
/*
float (float v) floor
*/
static void
PF_floor (progs_t *pr)
{
R_FLOAT (pr) = floor (P_FLOAT (pr, 0));
}
/*
float (float v) ceil
*/
static void
PF_ceil (progs_t *pr)
{
@ -381,9 +387,7 @@ PF_ceil (progs_t *pr)
}
/*
PF_nextent
entity nextent(entity)
entity (entity e) nextent
*/
static void
PF_nextent (progs_t *pr)
@ -414,8 +418,6 @@ PF_nextent (progs_t *pr)
#endif
/*
PF_ftoi
integer (float f) ftoi
*/
static void
@ -425,8 +427,6 @@ PF_ftoi (progs_t *pr)
}
/*
PF_ftos
string (float f) ftos
*/
static void
@ -451,8 +451,6 @@ PF_ftos (progs_t *pr)
}
/*
PF_itof
float (integer i) itof
*/
static void
@ -462,8 +460,6 @@ PF_itof (progs_t *pr)
}
/*
PF_itos
string (integer i) itos
*/
static void
@ -477,8 +473,6 @@ PF_itos (progs_t *pr)
}
/*
PF_stof
float (string s) stof
*/
static void
@ -488,8 +482,6 @@ PF_stof (progs_t *pr)
}
/*
PF_stoi
integer (string s) stoi
*/
static void
@ -499,8 +491,6 @@ PF_stoi (progs_t *pr)
}
/*
PF_stov
vector (string s) stov
*/
static void
@ -514,8 +504,6 @@ PF_stov (progs_t *pr)
}
/*
PF_vtos
string (vector v) vtos
*/
static void
@ -532,9 +520,7 @@ PF_vtos (progs_t *pr)
}
/*
PF_strlen
float(string s) strlen
float (string s) strlen
*/
static void
PF_strlen (progs_t *pr)
@ -546,9 +532,7 @@ PF_strlen (progs_t *pr)
}
/*
PF_charcount
float(string char, string s) charcount
float (string char, string s) charcount
*/
static void
PF_charcount (progs_t *pr)
@ -580,282 +564,78 @@ PF_charcount (progs_t *pr)
#endif
#define MAX_ARG 7
/*
string (...) sprintf
*/
static void
PF_sprintf (progs_t *pr)
{
const char *format;
const char *c; // current
char *out = 0;
char new_format[INT_WIDTH * 2 + 9]; // "%0-+ #." and conversion
int fmt_alternate, fmt_leadzero, fmt_leftjust, fmt_minwidth;
int fmt_precision, fmt_signed, fmt_space, fmt_type, looping;
int ret;
size_t new_format_i;
int curarg = 1, out_max = 32, out_size = 0;
const char *fmt = P_GSTRING (pr, 0);
int count = pr->pr_argc - 1;
pr_type_t **args = pr->pr_params + 1;
dstring_t *dstr;
int str;
format = P_GSTRING (pr, 0);
c = format;
out = malloc (out_max);
if (!out)
goto mallocerror;
while (*c) {
if (*c == '%' && c[1] != '%' && c[1] != 's') {
c++;
if (curarg > MAX_ARG)
goto maxargs;
// flags
looping = 1;
fmt_leadzero = 0;
fmt_leftjust = 0;
fmt_signed = 0;
fmt_space = 0;
fmt_alternate = 0;
while (looping) {
switch (*c) {
case '0': fmt_leadzero = 1; break;
case '-': fmt_leftjust = 1; break;
case '+': fmt_signed = 1; break;
case ' ': fmt_space = 1; break;
case '#': fmt_alternate = 1; break;
case '\0': goto endofstring;
default: looping = 0; continue;
}
c++;
}
// minimum field width
fmt_minwidth = 0;
if (*c >= '1' && *c <= '9')
while (*c >= '0' && *c <= '9') {
fmt_minwidth *= 10;
fmt_minwidth += *c - '0';
c++;
}
else if (*c == '*') {
fmt_minwidth = P_INT (pr, 0 + curarg);
curarg++;
}
// precision
fmt_precision = -1;
if (*c == '.') {
c++;
if (*c >= '0' && *c <= '9') {
fmt_precision = 0;
while (*c >= '0' && *c <= '9') {
fmt_precision *= 10;
fmt_precision += *c - '0';
c++;
}
} else if (*c == '*') {
fmt_precision = P_INT (pr, 0 + curarg);
curarg++;
}
}
if (!*c)
goto endofstring;
// length? Nope, not in QC
fmt_type = *c++;
// some preperation
if (fmt_precision < 0)
switch (fmt_type) {
case 'i': fmt_precision = 0; break;
case 'f': fmt_precision = 6; break;
case 'v': fmt_precision = 1; break;
}
// built the format string
new_format_i = 0;
new_format[new_format_i++] = '%';
if (fmt_leadzero) new_format[new_format_i++] = '0';
if (fmt_leftjust) new_format[new_format_i++] = '-';
if (fmt_signed) new_format[new_format_i++] = '+';
if (fmt_space) new_format[new_format_i++] = ' ';
if (fmt_alternate) new_format[new_format_i++] = '#';
if (fmt_minwidth)
if ((new_format_i += snprintf (new_format + new_format_i,
sizeof (new_format) -
new_format_i,
"%d", fmt_minwidth))
>= sizeof (new_format))
PR_Error (pr, "PF_sprintf: new_format overflowed?!");
if (fmt_type != 'i') {
new_format[new_format_i++] = '.';
if ((new_format_i += snprintf (new_format + new_format_i,
sizeof (new_format)
- new_format_i,
"%d", fmt_precision))
>= sizeof (new_format))
PR_Error (pr, "PF_sprintf: new_format overflowed?!");
}
switch (fmt_type) {
case 'i': new_format[new_format_i++] = 'd'; break;
case 'f':
case 'v': new_format[new_format_i++] = 'f'; break;
default: PR_Error (pr, "PF_sprintf: unknown type '%c'!", *c);
}
new_format[new_format_i++] = '\0';
switch (fmt_type) {
case 'i':
while ((ret = snprintf (&out[out_size], out_max - out_size,
new_format,
P_INT (pr, 0 + curarg)))
>= out_max - out_size) {
char *o;
out_max *= 2;
o = realloc (out, out_max);
if (!o)
goto mallocerror;
out = o;
}
out_size += ret;
curarg++;
break;
case 'f':
while ((ret = snprintf (&out[out_size], out_max - out_size,
new_format,
P_FLOAT (pr, 0 + curarg)))
>= out_max - out_size) {
char *o;
out_max *= 2;
o = realloc (out, out_max);
if (!o)
goto mallocerror;
out = o;
}
out_size += ret;
curarg++;
break;
case 'v': {
int i;
for (i = 0; i <= 2; i++) {
if (curarg > MAX_ARG)
goto maxargs;
while ((ret = snprintf (&out[out_size],
out_max - out_size, new_format,
P_VECTOR (pr, 0 + curarg)[i]))
>= out_max - out_size) {
char *o;
out_max *= 2;
o = realloc (out, out_max);
if (!o)
goto mallocerror;
out = o;
}
out_size += ret;
i++;
}
curarg++;
break;
}
}
} else if (*c == '%' && *(c + 1) == 's') {
const char *s;
if (curarg > MAX_ARG)
goto maxargs;
s = P_GSTRING (pr, 0 + curarg);
while ((ret = snprintf (&out[out_size], out_max - out_size, "%s",
s))
>= out_max - out_size) {
char *o;
out_max *= 2;
o = realloc (out, out_max);
if (!o)
goto mallocerror;
out = o;
}
out_size += ret;
curarg++;
c += 2;
} else {
if (*c == '%')
c++;
if (out_size == out_max) {
char *o;
out_max *= 2;
o = realloc (out, out_max);
if (!o)
goto mallocerror;
out = o;
}
out[out_size] = *c;
out_size++;
c++;
}
}
if (out_size == out_max) {
char *o;
out_max *= 2;
o = realloc (out, out_max);
if (!o)
goto mallocerror;
out = o;
}
out[out_size] = '\0';
RETURN_STRING (pr, out);
free (out);
return;
mallocerror:
// if (errno == ENOMEM)
// hopefully we can free up some mem so it can be used during shutdown
// free (out);
PR_Error (pr, "PF_sprintf: memory allocation error!\n");
endofstring:
PR_Error (pr, "PF_sprintf: unexpected end of string!\n");
maxargs:
PR_Error (pr, "PF_sprintf: argument limit exceeded\n");
str = PR_NewString (pr);
dstr = PR_GetDString (pr, str);
PR_Sprintf (pr, dstr, "bi_printf", fmt, count, args);
PR_MakeTempString (pr, str);
R_STRING (pr) = str;
}
/*
string () gametype
*/
static void
PR_gametype (progs_t *pr)
{
RETURN_STRING (pr, pr_gametype);
}
static builtin_t builtins[] = {
{"break", PF_break, 6},
{"random", PF_random, 7},
{"normalize", PF_normalize, 9},
{"vlen", PF_vlen, 12},
{"vectoyaw", PF_vectoyaw, 13},
{"find", PF_Find, 18},
{"dprint", PF_dprint, 25},
{"ftos", PF_ftos, 26},
{"vtos", PF_vtos, 27},
{"coredump", PF_coredump, 28},
{"traceon", PF_traceon, 29},
{"traceoff", PF_traceoff, 30},
{"eprint", PF_eprint, 31},
{"rint", PF_rint, 36},
{"floor", PF_floor, 37},
{"ceil", PF_ceil, 38},
{"fabs", PF_fabs, 43},
{"cvar", PF_cvar, 45},
{"nextent", PF_nextent, 47},
{"vectoangles", PF_vectoangles, 51},
{"cvar_set", PF_cvar_set, 72},
{"stof", PF_stof, 81},
{"strlen", PF_strlen, 100},
{"charcount", PF_charcount, 101},
{"sprintf", PF_sprintf, 109},
{"ftoi", PF_ftoi, 110},
{"itof", PF_itof, 111},
{"itos", PF_itos, 112},
{"stoi", PF_stoi, 113},
{"stov", PF_stov, 114},
{"gametype", PR_gametype, 115},
};
void
PR_Cmds_Init (progs_t *pr)
{
PR_AddBuiltin (pr, "break", PF_break, 6); // void () break
PR_AddBuiltin (pr, "random", PF_random, 7); // float () random
PR_AddBuiltin (pr, "normalize", PF_normalize, 9); // vector (vector v) normalize
PR_AddBuiltin (pr, "vlen", PF_vlen, 12); // float (vector v) vlen
PR_AddBuiltin (pr, "vectoyaw", PF_vectoyaw, 13); // float (vector v) vectoyaw
PR_AddBuiltin (pr, "find", PF_Find, 18); // entity (entity start, .(...) fld, ... match) find
PR_AddBuiltin (pr, "dprint", PF_dprint, 25); // void (string s) dprint
PR_AddBuiltin (pr, "ftos", PF_ftos, 26); // string (float f) ftos
PR_AddBuiltin (pr, "vtos", PF_vtos, 27); // string (vector v) vtos
PR_AddBuiltin (pr, "coredump", PF_coredump, 28); // void () coredump
PR_AddBuiltin (pr, "traceon", PF_traceon, 29); // void () traceon
PR_AddBuiltin (pr, "traceoff", PF_traceoff, 30); // void () traceoff
PR_AddBuiltin (pr, "eprint", PF_eprint, 31); // void (entity e) eprint
PR_AddBuiltin (pr, "rint", PF_rint, 36); // float (float v) rint
PR_AddBuiltin (pr, "floor", PF_floor, 37); // float (float v) floor
PR_AddBuiltin (pr, "ceil", PF_ceil, 38); // float (float v) ceil
PR_AddBuiltin (pr, "fabs", PF_fabs, 43); // float (float f) fabs
PR_AddBuiltin (pr, "cvar", PF_cvar, 45); // float (string s) cvar
PR_AddBuiltin (pr, "nextent", PF_nextent, 47); // entity (entity e) nextent
PR_AddBuiltin (pr, "vectoangles", PF_vectoangles, 51); // vector (vector v) vectoangles
PR_AddBuiltin (pr, "cvar_set", PF_cvar_set, 72); // void (string var, string val) cvar_set
PR_AddBuiltin (pr, "stof", PF_stof, 81); // float (string s) stof
PR_AddBuiltin (pr, "strlen", PF_strlen, 100); // float (string s) strlen
PR_AddBuiltin (pr, "charcount", PF_charcount, 101); // float (string goal, string s) charcount
PR_AddBuiltin (pr, "sprintf", PF_sprintf, 109); // string (...) sprintf
PR_AddBuiltin (pr, "ftoi", PF_ftoi, 110); // integer (float f) ftoi
PR_AddBuiltin (pr, "itof", PF_itof, 111); // float (integer i) itof
PR_AddBuiltin (pr, "itos", PF_itos, 112); // string (integer i) itos
PR_AddBuiltin (pr, "stoi", PF_stoi, 113); // integer (string s) stoi
PR_AddBuiltin (pr, "stov", PF_stov, 114); // vector (string s) stov
PR_AddBuiltin (pr, "gametype", PR_gametype, 115); // string () gametype
int i;
builtin_t *bi;
for (i = 0; i < sizeof (builtins) / sizeof (builtins[0]); i++) {
bi = builtins + i;
PR_AddBuiltin (pr, bi->name, bi->proc, bi->binum);
}
};

View File

@ -98,7 +98,7 @@ PR_AddBuiltin (progs_t *pr, const char *name, builtin_proc builtin, int num)
pr->builtins[i] = malloc (sizeof (builtin_t));
pr->builtins[i]->proc = builtin;
pr->builtins[i]->name = name;
pr->builtins[i]->first_statement = i;
pr->builtins[i]->binum = i;
Hash_Add (pr->builtin_hash, pr->builtins[i]);
}
@ -127,7 +127,7 @@ PR_RelocateBuiltins (progs_t *pr)
pr->progs_name, bi_name);
return 0;
}
func->first_statement = -bi->first_statement;
func->first_statement = -bi->binum;
}
return 1;
}

View File

@ -38,6 +38,7 @@ static __attribute__ ((unused)) const char rcsid[] =
# include <strings.h>
#endif
#include <ctype.h>
#include <stdarg.h>
#include <stdlib.h>
@ -150,7 +151,7 @@ strref_free (void *_sr, void *_pr)
int
PR_LoadStrings (progs_t *pr)
{
char *end = pr->pr_strings + pr->pr_stringsize;
char *end = pr->pr_strings + pr->progs->numstrings;
char *str = pr->pr_strings;
int count = 0;
@ -289,6 +290,25 @@ PR_SetTempString (progs_t *pr, const char *s)
return string_index (pr, sr);
}
void
PR_MakeTempString (progs_t *pr, int str)
{
strref_t *sr = get_strref (pr, str);
if (!sr)
PR_RunError (pr, "invalid string %d", str);
if (sr->dstring) {
if (sr->dstring->str)
sr->string = sr->dstring->str;
PR_Zone_Free (pr, sr->dstring);
}
if (!sr->string)
sr->string = pr_strdup (pr, "");
sr->count = 0;
sr->next = pr->pr_xtstr;
pr->pr_xtstr = sr;
}
int
PR_NewString (progs_t *pr)
{
@ -325,3 +345,353 @@ PR_FreeTempStrings (progs_t *pr)
}
pr->pr_xtstr = 0;
}
// format adjustments
#define FMT_ALTFORM (1<<0)
#define FMT_LJUSTIFY (1<<1)
#define FMT_ZEROPAD (1<<2)
#define FMT_ADDSIGN (1<<3)
#define FMT_ADDBLANK (1<<4)
#define FMT_HEX (1<<5)
typedef struct fmt_item_s {
byte type;
unsigned flags;
int minFieldWidth;
int precision;
union {
const char *string_var;
int integer_var;
unsigned uinteger_var;
float float_var;
} data;
struct fmt_item_s *next;
} fmt_item_t;
#define PRINT(t) \
switch ((doWidth << 1) | doPrecision) { \
case 3: \
dasprintf (result, tmp->str, current->minFieldWidth, \
current->precision, current->data.t##_var); \
break; \
case 2: \
dasprintf (result, tmp->str, current->minFieldWidth, \
current->precision, current->data.t##_var); \
break; \
case 1: \
dasprintf (result, tmp->str, current->precision, \
current->data.t##_var); \
break; \
case 0: \
dasprintf (result, tmp->str, current->data.t##_var); \
break; \
}
/*
This function takes as input a linked list of fmt_item_t representing
EVERYTHING to be printed. This includes text that is not affected by
formatting. A string without any formatting would wind up with only one
list item.
*/
static void
I_DoPrint (dstring_t *result, fmt_item_t *formatting)
{
fmt_item_t *current = formatting;
dstring_t *tmp = dstring_new ();
while (current) {
qboolean doPrecision, doWidth;
doPrecision = -1 != current->precision;
doWidth = 0 != current->minFieldWidth;
dsprintf (tmp, "%%%s%s%s%s%s%s%s",
(current->flags & FMT_ALTFORM) ? "#" : "", // hash
(current->flags & FMT_ZEROPAD) ? "0" : "", // zero padding
(current->flags & FMT_LJUSTIFY) ? "-" : "", // left justify
(current->flags & FMT_ADDBLANK) ? " " : "", // add space for +ve
(current->flags & FMT_ADDSIGN) ? "+" : "", // add sign always
doWidth ? "*" : "",
doPrecision ? ".*" : "");
switch (current->type) {
case 's':
dstring_appendstr (tmp, "s");
PRINT (string);
break;
case 'i':
dstring_appendstr (tmp, "ld");
PRINT (integer);
break;
case 'u':
if (current->flags & FMT_HEX)
dstring_appendstr (tmp, "lx");
else
dstring_appendstr (tmp, "lu");
PRINT (uinteger);
break;
case 'f':
dstring_appendstr (tmp, "f");
PRINT (float);
break;
case 'g':
dstring_appendstr (tmp, "g");
PRINT (float);
break;
default:
break;
}
current = current->next;
}
dstring_delete (tmp);
}
static fmt_item_t *free_fmt_items;
static fmt_item_t *
new_fmt_item (void)
{
int i;
fmt_item_t *fi;
if (!free_fmt_items) {
free_fmt_items = malloc (16 * sizeof (fmt_item_t));
for (i = 0; i < 15; i++)
free_fmt_items[i].next = free_fmt_items + i + 1;
free_fmt_items[i].next = 0;
}
fi = free_fmt_items;
free_fmt_items = fi->next;
memset (fi, 0, sizeof (*fi));
fi->precision = -1;
return fi;
}
static void
free_fmt_item (fmt_item_t *fi)
{
fi->next = free_fmt_items;
free_fmt_items = fi;
}
#undef P_var
#define P_var(p,n,t) (args[n]->t##_var)
void
PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
const char *format, int count, pr_type_t **args)
{
const char *c, *l;
const char *msg = "";
fmt_item_t *fmt_items = 0;
fmt_item_t **fi = &fmt_items;
int fmt_count = 0;
if (!name)
name = "PF_InternalSprintf";
*fi = new_fmt_item ();
c = l = format;
while (*c) { // count "%"s, checking our input along the way
if (*c++ == '%') {
if (c != l + 1) {
// have some unformatted text to print
(*fi)->precision = c - l - 1;
(*fi)->type = 's';
(*fi)->data.string_var = l;
(*fi)->next = new_fmt_item ();
fi = &(*fi)->next;
}
if (*c == '%') {
(*fi)->type = 's';
(*fi)->data.string_var = "%";
(*fi)->next = new_fmt_item ();
fi = &(*fi)->next;
} else {
do {
switch (*c) {
// format options
case '\0':
msg = "Unexpected end of format string";
goto error;
case '0':
(*fi)->flags |= FMT_ZEROPAD;
c++;
continue;
case '#':
(*fi)->flags |= FMT_ALTFORM;
c++;
continue;
case ' ':
(*fi)->flags |= FMT_ADDBLANK;
c++;
continue;
case '-':
(*fi)->flags |= FMT_LJUSTIFY;
c++;
continue;
case '+':
(*fi)->flags |= FMT_ADDSIGN;
c++;
continue;
case '.':
(*fi)->precision = 0;
c++;
while (isdigit (*c)) {
(*fi)->precision *= 10;
(*fi)->precision += *c++ - '0';
}
continue;
case '1': case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9':
while (isdigit (*c)) {
(*fi)->minFieldWidth *= 10;
(*fi)->minFieldWidth += *c++ - '0';
}
continue;
// format types
case '@':
// object
fmt_count++;
(*fi)->next = new_fmt_item ();
fi = &(*fi)->next;
break;
case 'e':
// entity
(*fi)->type = 'i';
(*fi)->data.integer_var =
P_EDICTNUM (pr, fmt_count);
fmt_count++;
(*fi)->next = new_fmt_item ();
fi = &(*fi)->next;
break;
case 'i':
// integer
(*fi)->type = *c;
(*fi)->data.integer_var = P_INT (pr, fmt_count);
fmt_count++;
(*fi)->next = new_fmt_item ();
fi = &(*fi)->next;
break;
case 'f':
// float
case 'g':
// float, no trailing zeroes, trim "." if nothing
// after
(*fi)->type = *c;
(*fi)->data.float_var = P_FLOAT (pr, fmt_count);
fmt_count++;
(*fi)->next = new_fmt_item ();
fi = &(*fi)->next;
break;
case 'p':
// pointer
(*fi)->flags |= FMT_ALTFORM;
(*fi)->type = 'x';
(*fi)->data.uinteger_var = P_UINT (pr, fmt_count);
fmt_count++;
(*fi)->next = new_fmt_item ();
fi = &(*fi)->next;
break;
case 's':
// string
(*fi)->type = *c;
(*fi)->data.string_var = P_GSTRING (pr, fmt_count);
fmt_count++;
(*fi)->next = new_fmt_item ();
fi = &(*fi)->next;
break;
case 'v':
// vector
{
int i;
int flags = (*fi)->flags;
int precision = (*fi)->precision;
unsigned minWidth = (*fi)->minFieldWidth;
(*fi)->flags = 0;
(*fi)->precision = -1;
(*fi)->minFieldWidth = 0;
for (i = 0; i < 3; i++) {
if (i == 0) {
(*fi)->type = 's';
(*fi)->data.string_var = "'";
} else {
(*fi)->type = 's';
(*fi)->data.string_var = " ";
}
(*fi)->next = new_fmt_item ();
fi = &(*fi)->next;
(*fi)->flags = flags;
(*fi)->precision = precision;
(*fi)->minFieldWidth = minWidth;
(*fi)->type = 'g';
(*fi)->data.float_var =
P_VECTOR (pr, fmt_count)[i];
(*fi)->next = new_fmt_item ();
fi = &(*fi)->next;
}
}
(*fi)->type = 's';
(*fi)->data.string_var = "'";
fmt_count++;
(*fi)->next = new_fmt_item ();
fi = &(*fi)->next;
break;
case 'x':
// integer, hex notation
(*fi)->type = *c;
(*fi)->data.uinteger_var = P_UINT (pr, fmt_count);
fmt_count++;
(*fi)->next = new_fmt_item ();
fi = &(*fi)->next;
break;
}
break;
} while (1);
}
l = ++c;
}
}
if (c != l) {
// have some unformatted text to print
(*fi)->precision = c - l;
(*fi)->type = 's';
(*fi)->data.string_var = l;
(*fi)->next = new_fmt_item ();
fi = &(*fi)->next;
}
if (0 && fmt_count != count) {
printf ("%d %d", fmt_count, count);
if (fmt_count > count)
msg = "Not enough arguments for format string.";
else
msg = "Too many arguments for format string.";
goto error;
}
I_DoPrint (result, fmt_items);
while (fmt_items) {
fmt_item_t *t = fmt_items->next;
free_fmt_item (fmt_items);
fmt_items = t;
}
return;
error:
PR_RunError (pr, "%s: %s", name, msg);
}

View File

@ -297,7 +297,7 @@ _dvsprintf (dstring_t *dstr, int offs, const char *fmt, va_list args)
dstring_clearstr (dstr); // Make it a string
// Some vsnprintf implementations return -1 on truncation
while ((size = vsnprintf (dstr->str + offs, dstr->truesize - offs, fmt, args)) == -1) {
dstr->size = dstr->truesize + 1024;
dstr->size = (dstr->truesize & 1023) + 1024;
dstring_adjust (dstr);
#ifdef VA_LIST_IS_ARRAY
VA_COPY (args, tmp_args);

View File

@ -134,7 +134,8 @@ SV_CreateBaseline (void)
} else {
((entity_state_t*)svent->data)->colormap = 0;
((entity_state_t*)svent->data)->modelindex =
SV_ModelIndex (PR_GetString (&sv_pr_state, SVstring (svent, model)));
SV_ModelIndex (PR_GetString (&sv_pr_state,
SVstring (svent, model)));
}
// LordHavoc: setup baseline to include new effects
((entity_state_t*)svent->data)->alpha = 255;

View File

@ -41,6 +41,7 @@ static __attribute__ ((unused)) const char rcsid[] =
#include <errno.h>
#include <string.h>
#include <QF/dstring.h>
#include <QF/progs.h>
#include <QF/zone.h>
@ -138,39 +139,14 @@ static void
bi_printf (progs_t *pr)
{
const char *fmt = P_GSTRING (pr, 0);
char c;
int count = 0;
float *v;
int count = pr->pr_argc - 1;
pr_type_t **args = pr->pr_params + 1;
dstring_t *dstr = dstring_new ();
while ((c = *fmt++)) {
if (c == '%' && count < 7) {
switch (c = *fmt++) {
case 'i':
fprintf (stdout, "%i",
P_INT (pr, 1 + count++ * pr->pr_param_size));
break;
case 'f':
fprintf (stdout, "%f",
P_FLOAT (pr, 1 + count++ * pr->pr_param_size));
break;
case 's':
fputs (P_GSTRING (pr, 1 + count++ * pr->pr_param_size),
stdout);
break;
case 'v':
v = P_VECTOR (pr, 1 + count++ * pr->pr_param_size);
fprintf (stdout, "'%f %f %f'", v[0], v[1], v[2]);
break;
default:
fputc ('%', stdout);
fputc (c, stdout);
count = 7;
break;
}
} else {
fputc (c, stdout);
}
}
PR_Sprintf (pr, dstr, "bi_printf", fmt, count, args);
if (dstr->str)
fputs (dstr->str, stdout);
dstring_delete (dstr);
}
void

View File

@ -6,6 +6,7 @@ void () test_str =
c = "strings ";
d = "\n";
print (a + b + c + d);
printf ("%i \"%.5s\" %3.4f %v\n", 14, "hi there", 3.1415926, '4 1 3');
};
integer (integer argc, string []argv) main =