mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-18 23:11:38 +00:00
Merge branch 'master' into vulkan
This commit is contained in:
commit
9ff4eefe65
78 changed files with 2810 additions and 508 deletions
|
@ -3,38 +3,39 @@
|
|||
/**
|
||||
\page connection_sequence QW Connection Sequence
|
||||
\msc
|
||||
Client,Server;
|
||||
Client=>Server [label = "getchallenge\n"];
|
||||
Server=>Client [label = "c[challenge][ext]"];
|
||||
Client=>Server [label = "connect [protover] [qport] [challenge] [userinfo]"];
|
||||
Server=>Client [label = "j"];
|
||||
Client->Server [label = "[clc_stringcmd]new"];
|
||||
Server->Client [label = "[svc_serverdata][data]"];
|
||||
|||;
|
||||
Client->Server [label = "[clc_stringcmd]soundlist [svcount] 0"];
|
||||
--- [label = "soundlist loop start"];
|
||||
Server->Client [label = "[svc_soundlist][data][next]"];
|
||||
Client->Server [label = "[clc_stringcmd]soundlist [svcount] [next]"];
|
||||
--- [label = "soundlist loop end"];
|
||||
Server->Client [label = "[svc_soundlist][data]0"];
|
||||
|||;
|
||||
Client->Server [label = "[clc_stringcmd]modellist [svcount] 0"];
|
||||
--- [label = "modellist list loop start"];
|
||||
Server->Client [label = "[svc_modellist][data][next]"];
|
||||
Client->Server [label = "[clc_stringcmd]modellist [svcount] [next]"];
|
||||
--- [label = "modellist list loop end"];
|
||||
Server->Client [label = "[svc_modellist][data]0"];
|
||||
|||;
|
||||
Client->Server [label = "[clc_stringcmd]prespawn [svcount] [n=0] [wcsum]"];
|
||||
--- [label = "prespawn loop start"];
|
||||
Server->Client [label = "[signon buffer n][stuffcmd]prespawn..."];
|
||||
Client->Server [label = "[clc_stringcmd]prespawn [svcount] [n]"];
|
||||
--- [label = "prespawn loop end"];
|
||||
Server->Client [label = "[signon buffer n][stuffcmd]spawn..."];
|
||||
|||;
|
||||
Client->Server [label = "[clc_stringcmd]spawn [svcount] 0"];
|
||||
Server->Client [label = "[spawn info][stuffcmd]skins"];
|
||||
Client->Server [label = "[clc_stringcmd]begin [svcount]"];
|
||||
#... [label = "in game message sequence"];
|
||||
Client [linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black],
|
||||
Server [linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
Client=>Server [label = "getchallenge\n", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
Server=>Client [label = "c[challenge][ext]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
Client=>Server [label = "connect [protover] [qport] [challenge] [userinfo]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
Server=>Client [label = "j", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
Client->Server [label = "[clc_stringcmd]new", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
Server->Client [label = "[svc_serverdata][data]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
||| [linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
Client->Server [label = "[clc_stringcmd]soundlist [svcount] 0", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
--- [label = "soundlist loop start", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
Server->Client [label = "[svc_soundlist][data][next]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
Client->Server [label = "[clc_stringcmd]soundlist [svcount] [next]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
--- [label = "soundlist loop end", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
Server->Client [label = "[svc_soundlist][data]0", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
||| [linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
Client->Server [label = "[clc_stringcmd]modellist [svcount] 0", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
--- [label = "modellist list loop start", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
Server->Client [label = "[svc_modellist][data][next]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
Client->Server [label = "[clc_stringcmd]modellist [svcount] [next]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
--- [label = "modellist list loop end", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
Server->Client [label = "[svc_modellist][data]0", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
||| [linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
Client->Server [label = "[clc_stringcmd]prespawn [svcount] [n=0] [wcsum]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
--- [label = "prespawn loop start", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
Server->Client [label = "[signon buffer n][stuffcmd]prespawn...", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
Client->Server [label = "[clc_stringcmd]prespawn [svcount] [n]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
--- [label = "prespawn loop end", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
Server->Client [label = "[signon buffer n][stuffcmd]spawn...", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
||| [linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
Client->Server [label = "[clc_stringcmd]spawn [svcount] 0", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
Server->Client [label = "[spawn info][stuffcmd]skins", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
Client->Server [label = "[clc_stringcmd]begin [svcount]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
... [label = "in game message sequence", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||
\endmsc
|
||||
*/
|
||||
|
|
|
@ -30,16 +30,28 @@
|
|||
|
||||
#include "QF/qtypes.h"
|
||||
|
||||
/** \defgroup llist Linked lists
|
||||
\ingroup utils
|
||||
*/
|
||||
//@{
|
||||
|
||||
typedef struct llist_node_s {
|
||||
struct llist_s *parent;
|
||||
struct llist_node_s *prev, *next;
|
||||
void *data;
|
||||
struct llist_s *parent; ///< The list owning this node.
|
||||
struct llist_node_s *prev; ///< The previous node in the list, or null.
|
||||
struct llist_node_s *next; ///< The flowing node in the list, or null.
|
||||
void *data; ///< The actual list item.
|
||||
} llist_node_t;
|
||||
|
||||
typedef struct llist_s {
|
||||
struct llist_node_s *start, *end, *iter;
|
||||
struct llist_node_s *start; ///< The first node in the list, or null.
|
||||
struct llist_node_s *end; ///< The last node in the list, or null.
|
||||
struct llist_node_s *iter;
|
||||
/// Function called when deleting a list item.
|
||||
/// \param element The item being deleted.
|
||||
/// \param userdata Pointer to user data supplied to llist_new().
|
||||
void (*freedata)(void *element, void *userdata);
|
||||
qboolean (*cmpdata)(const void *element, const void *comparison, void *userdata);
|
||||
qboolean (*cmpdata)(const void *element, const void *comparison,
|
||||
void *userdata);
|
||||
void *userdata;
|
||||
} llist_t;
|
||||
|
||||
|
@ -48,8 +60,43 @@ typedef qboolean (*llist_iterator_t)(void *element, llist_node_t *node);
|
|||
#define LLIST_ICAST(x) (llist_iterator_t)(x)
|
||||
#define LLIST_DATA(node, type) ((type *)((node)->data))
|
||||
|
||||
llist_t *llist_new (void (*freedata)(void *element, void *userdata), qboolean (*cmpdata)(const void *element, const void *comparison, void *userdata), void *userdata);
|
||||
/** Create a new, empty, linked list.
|
||||
|
||||
\param freedata Function to call when deleting a list item.
|
||||
\param cmpdata Function to call to compare two list items. It must
|
||||
return true when the items are the same and false when
|
||||
they differ.
|
||||
\param userdata User data pointer. Set to whatever you want, it will be
|
||||
passed to the \a freedata and \a cmpdata functions as
|
||||
their final parameter.
|
||||
\return Pointer to the list's control structure, which is to be
|
||||
passed to the other functions accessing the list.
|
||||
*/
|
||||
llist_t *llist_new (void (*freedata)(void *element, void *userdata),
|
||||
qboolean (*cmpdata)(const void *element,
|
||||
const void *comparison,
|
||||
void *userdata),
|
||||
void *userdata);
|
||||
|
||||
/** Empty a linked list.
|
||||
All of the items in the list will be deleted via the list's \a freedata
|
||||
function and the list will become empty.
|
||||
|
||||
\param list Pointer to the list's control structure created by
|
||||
llist_new(). May be null, in which case no operation is
|
||||
performed.
|
||||
*/
|
||||
void llist_flush (llist_t *list);
|
||||
|
||||
/** Delete a linked list.
|
||||
All of the items in the list will be deleted via the list's \a freedata
|
||||
function and the list will be destroyed. Do not attempt to use the list
|
||||
pointer after destroying the list.
|
||||
|
||||
\param list Pointer to the list's control structure created by
|
||||
llist_new(). May be null, in which case no operation is
|
||||
performed.
|
||||
*/
|
||||
void llist_delete (llist_t *list);
|
||||
llist_node_t *llist_append (llist_t *list, void *element);
|
||||
llist_node_t *llist_prefix (llist_t *list, void *element);
|
||||
|
@ -62,4 +109,7 @@ void llist_iterate (llist_t *list, llist_iterator_t iterate);
|
|||
void *llist_find (llist_t *list, void *comparison);
|
||||
llist_node_t *llist_findnode (llist_t *list, void *comparison);
|
||||
void *llist_createarray (llist_t *list, size_t esize);
|
||||
|
||||
//@}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -44,6 +44,7 @@ typedef enum {
|
|||
ev_integer,
|
||||
ev_uinteger,
|
||||
ev_short, // value is embedded in the opcode
|
||||
ev_double,
|
||||
|
||||
ev_invalid, // invalid type. used for instruction checking
|
||||
ev_type_count // not a type, gives number of types
|
||||
|
@ -180,8 +181,8 @@ typedef enum {
|
|||
OP_SHL_I,
|
||||
OP_SHR_I,
|
||||
|
||||
OP_MOD_F,
|
||||
OP_MOD_I,
|
||||
OP_REM_F,
|
||||
OP_REM_I,
|
||||
|
||||
OP_LOADB_F,
|
||||
OP_LOADB_V,
|
||||
|
@ -305,6 +306,7 @@ typedef enum {
|
|||
OP_PUSH_P,
|
||||
OP_PUSH_Q,
|
||||
OP_PUSH_I,
|
||||
OP_PUSH_D,
|
||||
|
||||
OP_PUSHB_S,
|
||||
OP_PUSHB_F,
|
||||
|
@ -315,6 +317,7 @@ typedef enum {
|
|||
OP_PUSHB_P,
|
||||
OP_PUSHB_Q,
|
||||
OP_PUSHB_I,
|
||||
OP_PUSHB_D,
|
||||
|
||||
OP_PUSHBI_S,
|
||||
OP_PUSHBI_F,
|
||||
|
@ -325,6 +328,7 @@ typedef enum {
|
|||
OP_PUSHBI_P,
|
||||
OP_PUSHBI_Q,
|
||||
OP_PUSHBI_I,
|
||||
OP_PUSHBI_D,
|
||||
|
||||
OP_POP_S,
|
||||
OP_POP_F,
|
||||
|
@ -335,6 +339,7 @@ typedef enum {
|
|||
OP_POP_P,
|
||||
OP_POP_Q,
|
||||
OP_POP_I,
|
||||
OP_POP_D,
|
||||
|
||||
OP_POPB_S,
|
||||
OP_POPB_F,
|
||||
|
@ -345,6 +350,7 @@ typedef enum {
|
|||
OP_POPB_P,
|
||||
OP_POPB_Q,
|
||||
OP_POPB_I,
|
||||
OP_POPB_D,
|
||||
|
||||
OP_POPBI_S,
|
||||
OP_POPBI_F,
|
||||
|
@ -355,6 +361,40 @@ typedef enum {
|
|||
OP_POPBI_P,
|
||||
OP_POPBI_Q,
|
||||
OP_POPBI_I,
|
||||
OP_POPBI_D,
|
||||
|
||||
OP_ADD_D,
|
||||
OP_SUB_D,
|
||||
OP_MUL_D,
|
||||
OP_MUL_QD,
|
||||
OP_MUL_DQ,
|
||||
OP_MUL_VD,
|
||||
OP_MUL_DV,
|
||||
OP_DIV_D,
|
||||
OP_REM_D,
|
||||
OP_GE_D,
|
||||
OP_LE_D,
|
||||
OP_GT_D,
|
||||
OP_LT_D,
|
||||
OP_NOT_D,
|
||||
OP_EQ_D,
|
||||
OP_NE_D,
|
||||
OP_CONV_FD,
|
||||
OP_CONV_DF,
|
||||
OP_CONV_ID,
|
||||
OP_CONV_DI,
|
||||
OP_STORE_D,
|
||||
OP_STOREB_D,
|
||||
OP_STOREBI_D,
|
||||
OP_STOREP_D,
|
||||
OP_LOAD_D,
|
||||
OP_LOADB_D,
|
||||
OP_LOADBI_D,
|
||||
OP_ADDRESS_D,
|
||||
|
||||
OP_MOD_I,
|
||||
OP_MOD_F,
|
||||
OP_MOD_D,
|
||||
} pr_opcode_e;
|
||||
|
||||
typedef struct opcode_s {
|
||||
|
@ -383,6 +423,11 @@ typedef struct ddef_s {
|
|||
pr_int_t s_name;
|
||||
} ddef_t;
|
||||
|
||||
typedef struct dparmsize_s {
|
||||
uint8_t size:5;
|
||||
uint8_t alignment:3;
|
||||
} dparmsize_t;
|
||||
|
||||
#define DEF_SAVEGLOBAL (1<<15)
|
||||
|
||||
#define MAX_PARMS 8
|
||||
|
@ -398,7 +443,7 @@ typedef struct dfunction_s {
|
|||
pr_int_t s_file; // source file defined in
|
||||
|
||||
pr_int_t numparms;
|
||||
uint8_t parm_size[MAX_PARMS];
|
||||
dparmsize_t parm_size[MAX_PARMS];
|
||||
} dfunction_t;
|
||||
|
||||
typedef union pr_type_u {
|
||||
|
@ -423,7 +468,7 @@ typedef struct pr_va_list_s {
|
|||
|(((0x##b) & 0xfff) << 12) \
|
||||
|(((0x##c) & 0xfff) << 0) )
|
||||
#define PROG_ID_VERSION 6
|
||||
#define PROG_VERSION PROG_VERSION_ENCODE(0,fff,009)
|
||||
#define PROG_VERSION PROG_VERSION_ENCODE(0,fff,00a)
|
||||
|
||||
typedef struct dprograms_s {
|
||||
pr_uint_t version;
|
||||
|
|
|
@ -320,6 +320,18 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_
|
|||
*/
|
||||
#define G_FLOAT(p,o) G_var (p, o, float)
|
||||
|
||||
/** Access a double global. Can be assigned to.
|
||||
|
||||
\par QC type:
|
||||
\c double
|
||||
\param p pointer to ::progs_t VM struct
|
||||
\param o offset into global data space
|
||||
\return double lvalue
|
||||
|
||||
\hideinitializer
|
||||
*/
|
||||
#define G_DOUBLE(p,o) (*(double *) ((p)->pr_globals + o))
|
||||
|
||||
/** Access an integer global. Can be assigned to.
|
||||
|
||||
\par QC type:
|
||||
|
@ -510,6 +522,18 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_
|
|||
*/
|
||||
#define P_FLOAT(p,n) P_var (p, n, float)
|
||||
|
||||
/** Access a double parameter. Can be assigned to.
|
||||
|
||||
\par QC type:
|
||||
\c double
|
||||
\param p pointer to ::progs_t VM struct
|
||||
\param n parameter number (0-7)
|
||||
\return double lvalue
|
||||
|
||||
\hideinitializer
|
||||
*/
|
||||
#define P_DOUBLE(p,n) (*(double *) ((p)->pr_params[n]))
|
||||
|
||||
/** Access an integer parameter. Can be assigned to.
|
||||
|
||||
\par QC type:
|
||||
|
@ -702,6 +726,17 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_
|
|||
*/
|
||||
#define R_FLOAT(p) R_var (p, float)
|
||||
|
||||
/** Access the VM function return value as a \c double
|
||||
|
||||
\par QC type:
|
||||
\c double
|
||||
\param p pointer to ::progs_t VM struct
|
||||
\return double lvalue
|
||||
|
||||
\hideinitializer
|
||||
*/
|
||||
#define R_DOUBLE(p) (*(double *) ((p)->pr_return))
|
||||
|
||||
/** Access the VM function return value as a \c ::pr_int_t (AKA int32_t)
|
||||
|
||||
\par QC type:
|
||||
|
@ -868,6 +903,18 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_
|
|||
*/
|
||||
#define E_FLOAT(e,o) E_var (e, o, float)
|
||||
|
||||
/** Access a double entity field. Can be assigned to.
|
||||
|
||||
\par QC type:
|
||||
\c double
|
||||
\param e pointer to the entity
|
||||
\param o field offset into entity data space
|
||||
\return double lvalue
|
||||
|
||||
\hideinitializer
|
||||
*/
|
||||
#define E_DOUBLE(e,o) (*(double *) ((e)->v + o))
|
||||
|
||||
/** Access an integer entity field. Can be assigned to.
|
||||
|
||||
\par QC type:
|
||||
|
@ -1032,7 +1079,7 @@ typedef struct {
|
|||
pr_int_t locals;
|
||||
pr_int_t profile;
|
||||
pr_int_t numparms;
|
||||
uint8_t parm_size[MAX_PARMS];
|
||||
dparmsize_t parm_size[MAX_PARMS];
|
||||
dfunction_t *descriptor;
|
||||
builtin_proc func;
|
||||
} bfunction_t;
|
||||
|
@ -1520,36 +1567,36 @@ struct progs_s {
|
|||
int zone_size; ///< set by user
|
||||
|
||||
/// \name builtin functions
|
||||
//@{
|
||||
///@{
|
||||
struct hashtab_s *builtin_hash;
|
||||
struct hashtab_s *builtin_num_hash;
|
||||
unsigned bi_next;
|
||||
unsigned (*bi_map) (progs_t *pr, unsigned binum);
|
||||
//@}
|
||||
///@}
|
||||
|
||||
/// \name symbol management
|
||||
//@{
|
||||
///@{
|
||||
struct hashtab_s *function_hash;
|
||||
struct hashtab_s *global_hash;
|
||||
struct hashtab_s *field_hash;
|
||||
//@}
|
||||
///@}
|
||||
|
||||
/// \name load hooks
|
||||
//@{
|
||||
///@{
|
||||
int num_load_funcs;
|
||||
int max_load_funcs;
|
||||
pr_load_func_t **load_funcs;
|
||||
|
||||
/// cleared each load
|
||||
//@{
|
||||
///@{
|
||||
int num_load_finish_funcs;
|
||||
int max_load_finish_funcs;
|
||||
pr_load_func_t **load_finish_funcs;
|
||||
//@}
|
||||
//@}
|
||||
///@}
|
||||
///@}
|
||||
|
||||
/// \name string management
|
||||
//@{
|
||||
///@{
|
||||
struct dstring_mem_s *ds_mem;
|
||||
strref_t *free_string_refs;
|
||||
strref_t *static_strings;
|
||||
|
@ -1560,10 +1607,11 @@ struct progs_s {
|
|||
struct hashtab_s *strref_hash;
|
||||
int num_strings;
|
||||
strref_t *pr_xtstr;
|
||||
//@}
|
||||
int float_promoted; ///< for PR_Sprintf
|
||||
///@}
|
||||
|
||||
/// \name memory map
|
||||
//@{
|
||||
///@{
|
||||
dfunction_t *pr_functions;
|
||||
bfunction_t *function_table;
|
||||
char *pr_strings;
|
||||
|
@ -1573,10 +1621,10 @@ struct progs_s {
|
|||
dstatement_t *pr_statements;
|
||||
pr_type_t *pr_globals;
|
||||
unsigned globals_size;
|
||||
//@}
|
||||
///@}
|
||||
|
||||
/// \name parameter block
|
||||
//@{
|
||||
///@{
|
||||
pr_type_t *pr_return;
|
||||
pr_type_t *pr_params[MAX_PARMS];
|
||||
pr_type_t *pr_real_params[MAX_PARMS];
|
||||
|
@ -1584,10 +1632,11 @@ struct progs_s {
|
|||
pr_type_t *pr_saved_params;
|
||||
int pr_saved_argc;
|
||||
int pr_param_size; ///< covers both params and return
|
||||
//@}
|
||||
int pr_param_alignment; ///< covers both params and return
|
||||
///@}
|
||||
|
||||
/// \name edicts
|
||||
//@{
|
||||
///@{
|
||||
edict_t **edicts;
|
||||
int max_edicts; ///< set by user
|
||||
int *num_edicts;
|
||||
|
@ -1599,10 +1648,10 @@ struct progs_s {
|
|||
int pr_edict_size; ///< in bytes
|
||||
int pr_edictareasize; ///< for bounds checking, starts at 0
|
||||
func_t edict_parse;
|
||||
//@}
|
||||
///@}
|
||||
|
||||
/// \name execution state
|
||||
//@{
|
||||
///@{
|
||||
int pr_argc;
|
||||
|
||||
qboolean pr_trace;
|
||||
|
@ -1620,24 +1669,24 @@ struct progs_s {
|
|||
/// be considered valid if there is no .stack global.
|
||||
/// \note The return address and saved locals will not ever be on this
|
||||
/// stack.
|
||||
//@{
|
||||
///@{
|
||||
pr_type_t *stack;
|
||||
pointer_t stack_bottom;
|
||||
int stack_size; ///< set by user
|
||||
//@}
|
||||
///@}
|
||||
|
||||
int localstack[LOCALSTACK_SIZE];
|
||||
int localstack_used;
|
||||
//@}
|
||||
///@}
|
||||
|
||||
/// \name resources
|
||||
//@{
|
||||
///@{
|
||||
pr_resource_t *resources;
|
||||
struct hashtab_s *resource_hash;
|
||||
//@}
|
||||
///@}
|
||||
|
||||
/// \name obj info
|
||||
//@{
|
||||
///@{
|
||||
unsigned selector_index;
|
||||
unsigned selector_index_max;
|
||||
struct obj_list_s **selector_sels;
|
||||
|
@ -1650,10 +1699,10 @@ struct progs_s {
|
|||
struct obj_list_s *unclaimed_proto_list;
|
||||
struct obj_list_s *module_list;
|
||||
struct obj_list_s *class_tree_list;
|
||||
//@}
|
||||
///@}
|
||||
|
||||
/// \name debug info
|
||||
//@{
|
||||
///@{
|
||||
const char *debugfile;
|
||||
struct pr_debug_header_s *debug;
|
||||
struct pr_auxfunction_s *auxfunctions;
|
||||
|
@ -1663,10 +1712,10 @@ struct progs_s {
|
|||
pr_type_t *watch;
|
||||
int wp_conditional;
|
||||
pr_type_t wp_val;
|
||||
//@}
|
||||
///@}
|
||||
|
||||
/// \name globals and fields needed by the VM
|
||||
//@{
|
||||
///@{
|
||||
struct {
|
||||
float *time; ///< required for OP_STATE
|
||||
pr_int_t *self; ///< required for OP_STATE
|
||||
|
@ -1678,7 +1727,7 @@ struct progs_s {
|
|||
pr_int_t think; ///< required for OP_STATE
|
||||
pr_int_t this; ///< optional for entity<->object linking
|
||||
} fields;
|
||||
//@}
|
||||
///@}
|
||||
};
|
||||
|
||||
/** \addtogroup progs_data_access
|
||||
|
|
|
@ -31,28 +31,110 @@
|
|||
#ifndef __QF_segtext_h
|
||||
#define __QF_segtext_h
|
||||
|
||||
/** \defgroup segtext Segmented text files.
|
||||
/** \defgroup segtext Segmented text files
|
||||
\ingroup utils
|
||||
|
||||
Based on The OpenGL Shader Wrangler: http://prideout.net/blog/?p=11
|
||||
Based on The OpenGL Shader Wrangler:
|
||||
https://prideout.net/blog/old/blog/index.html@p=11.html
|
||||
However, nothing is assumed about any of the segments: they are all nothing
|
||||
more than chunks of mostly random (lines cannot start with --) text with
|
||||
identifying tags. Also, the identifying tag represents only the shader_key
|
||||
of OpenGL Shader Wrangler's Effect.shader_key identifier.
|
||||
*/
|
||||
///@{
|
||||
|
||||
/** Represent a single text segment
|
||||
|
||||
Segments are separated by lines beginning with "--" (without the quotes).
|
||||
|
||||
The first word ([A-Za-z0-9_.]+) following the double-hyphen is used as an
|
||||
identifying tag for the segment. Whitespace and any additional characters
|
||||
are ignored.
|
||||
|
||||
The segment itself starts on the following line.
|
||||
*/
|
||||
typedef struct segchunk_s {
|
||||
struct segchunk_s *next;
|
||||
const char *tag;
|
||||
const char *text;
|
||||
int start_line;
|
||||
const char *tag; ///< identifying tag or null if no tag
|
||||
const char *text; ///< nul-terminated string holding the segment
|
||||
int start_line; ///< line number for first line of the segment
|
||||
} segchunk_t;
|
||||
|
||||
/** Container for all the segments extracted from the provided text
|
||||
|
||||
The first segment has no tag and may or may not be empty.
|
||||
Segments are stored sequentially in \a chunk_list are indexed by
|
||||
identifying tag (if present) in \a tab.
|
||||
Segments that have no identifying tag are not in \a tab, but can
|
||||
be accessed by walking \a chunk_list its \a next field.
|
||||
*/
|
||||
typedef struct segtext_s {
|
||||
struct segtext_s *next;
|
||||
segchunk_t *chunk_list;
|
||||
struct hashtab_s *tab;
|
||||
} segtext_t;
|
||||
|
||||
/** Parse a nul-terminated string into (optionally) tagged segments
|
||||
|
||||
The segments are separated by lines beginning with a double-hyphen ("--"),
|
||||
with an optional tag following the double-hyphen on the same line. Valid
|
||||
tag characters are ASCII alpha-numerics, "." and "_". Whitespace is ignored
|
||||
and invalid characters are treated as whitespace. Only the first tag on the
|
||||
line is significant.
|
||||
|
||||
\param src nul-terminated string to be parsed into segments
|
||||
\return Pointer to container of parsed segments. Can be freed using
|
||||
Segtext_delete().
|
||||
*/
|
||||
segtext_t *Segtext_new (const char *src);
|
||||
/** Free a segmented text container created by Segtext_new()
|
||||
|
||||
\param st Pointer to segmented text container to be freed. Must have been
|
||||
created by Segtext_new().
|
||||
*/
|
||||
void Segtext_delete (segtext_t *st);
|
||||
/** Find a text segment via its identifying tag
|
||||
|
||||
Like OpenGL Shader Wrangler, the segment tag does not have to be a perfect
|
||||
match with the specified tag: the segment with the longest string of
|
||||
sub-tags matching the leading subtags of the specified tag is selected.
|
||||
Tags are logically broken into sub-tag by the "." character. Thus in a
|
||||
collection of segments with tags "foo" and "foo.b", "foo.bar" will find the
|
||||
segment tagged "foo". However, if a segment tagged "foo.bar" is present, it
|
||||
will be returned. A segment tagged "foo.bar.baz" will not.
|
||||
|
||||
\param st Pointer to segmented text container
|
||||
\param tag String specifying the tag identifying the segment to be
|
||||
returned. Valid tag characters are alphanumerics, "_" and "."
|
||||
(ie, [A-Za-z0-9._]). "." is used as a sub-tag separator for
|
||||
partial matches.
|
||||
\return Pointer to segment data block with the best matching tag,
|
||||
providing access to the segment's tag and starting line number,
|
||||
as well as the segment contents. Null if no matching tag was
|
||||
found.
|
||||
*/
|
||||
const segchunk_t *Segtext_FindChunk (const segtext_t *st, const char *tag);
|
||||
|
||||
/** Find a text segment via its identifying tag
|
||||
|
||||
Like OpenGL Shader Wrangler, the segment tag does not have to be a perfect
|
||||
match with the specified tag: the segment with the longest string of
|
||||
sub-tags matching the leading subtags of the specified tag is selected.
|
||||
Tags are logically broken into sub-tag by the "." character. Thus in a
|
||||
collection of segments with tags "foo" and "foo.b", "foo.bar" will find the
|
||||
segment tagged "foo". However, if a segment tagged "foo.bar" is present, it
|
||||
will be returned. A segment tagged "foo.bar.baz" will not.
|
||||
|
||||
\param st Pointer to segmented text container
|
||||
\param tag String specifying the tag identifying the segment to be
|
||||
returned. Valid tag characters are alphanumerics, "_" and "."
|
||||
(ie, [A-Za-z0-9._]). "." is used as a sub-tag separator for
|
||||
partial matches.
|
||||
\return Contents of the segment with the best matching tag, or null if
|
||||
no matching tag was found.
|
||||
*/
|
||||
const char *Segtext_Find (const segtext_t *st, const char *tag);
|
||||
|
||||
///@}
|
||||
|
||||
#endif//__QF_segtext_h
|
||||
|
|
|
@ -81,6 +81,10 @@ void S_Init (int *viewentity, double *host_frametime);
|
|||
*/
|
||||
void S_Init_Cvars (void);
|
||||
|
||||
/** Shutdown the sound engine. Allows audio output modules to shutdown
|
||||
gracefully.
|
||||
*/
|
||||
void S_Shutdown (void);
|
||||
///@}
|
||||
|
||||
/** \defgroup sound_stuff Unclassified
|
||||
|
|
|
@ -692,7 +692,12 @@ value_string (progs_t *pr, etype_t type, pr_type_t *val)
|
|||
case ev_uinteger:
|
||||
dsprintf (line, "$%08x", val->uinteger_var);
|
||||
break;
|
||||
default:
|
||||
case ev_double:
|
||||
dsprintf (line, "%g", *(double *)val);
|
||||
break;
|
||||
case ev_short:
|
||||
case ev_invalid:
|
||||
case ev_type_count:
|
||||
//dsprintf (line, "bad type %i", type);
|
||||
dsprintf (line, "<%x %x %x %x>",
|
||||
val[0].integer_var, val[1].integer_var,
|
||||
|
|
|
@ -142,6 +142,21 @@ PR_PopFrame (progs_t *pr)
|
|||
pr->pr_xtstr = frame->tstr;
|
||||
}
|
||||
|
||||
static __attribute__((pure)) long
|
||||
align_offset (long offset, dparmsize_t parmsize)
|
||||
{
|
||||
int mask = (1 << parmsize.alignment) - 1;
|
||||
return (offset + mask) & ~mask;
|
||||
}
|
||||
|
||||
static void
|
||||
copy_param (pr_type_t *dst, pr_type_t *src, size_t size)
|
||||
{
|
||||
while (size--) {
|
||||
memcpy (dst++, src++, sizeof (pr_type_t));
|
||||
}
|
||||
}
|
||||
|
||||
/** Setup the stackframe prior to calling a progs function. Saves all local
|
||||
data the called function will trample on and copies the parameters used
|
||||
by the function into the function's local data space.
|
||||
|
@ -153,39 +168,44 @@ PR_PopFrame (progs_t *pr)
|
|||
static void
|
||||
PR_EnterFunction (progs_t *pr, bfunction_t *f)
|
||||
{
|
||||
pr_int_t i, j, c, o;
|
||||
pr_int_t k;
|
||||
pr_int_t count = 0;
|
||||
int size[2] = {0, 0};
|
||||
long paramofs = 0;
|
||||
long offs;
|
||||
pr_int_t i;
|
||||
pr_type_t *dstParams[MAX_PARMS];
|
||||
pointer_t paramofs = 0;
|
||||
|
||||
PR_PushFrame (pr);
|
||||
|
||||
if (f->numparms > 0) {
|
||||
for (i = 0; i < 2 && i < f->numparms; i++) {
|
||||
paramofs += f->parm_size[i];
|
||||
size[i] = f->parm_size[i];
|
||||
paramofs = f->parm_start;
|
||||
for (i = 0; i < f->numparms; i++) {
|
||||
paramofs = align_offset (paramofs, f->parm_size[i]);
|
||||
dstParams[i] = pr->pr_globals + paramofs;
|
||||
paramofs += f->parm_size[i].size;
|
||||
if (pr->pr_params[i] != pr->pr_real_params[i]) {
|
||||
copy_param (pr->pr_real_params[i], pr->pr_params[i],
|
||||
f->parm_size[i].size);
|
||||
}
|
||||
}
|
||||
count = i;
|
||||
} else if (f->numparms < 0) {
|
||||
for (i = 0; i < 2 && i < -f->numparms - 1; i++) {
|
||||
paramofs += f->parm_size[i];
|
||||
size[i] = f->parm_size[i];
|
||||
paramofs = f->parm_start + 2; // argc and argv
|
||||
for (i = 0; i < -f->numparms - 1; i++) {
|
||||
paramofs = align_offset (paramofs, f->parm_size[i]);
|
||||
dstParams[i] = pr->pr_globals + paramofs;
|
||||
paramofs += f->parm_size[i].size;
|
||||
if (pr->pr_params[i] != pr->pr_real_params[i]) {
|
||||
copy_param (pr->pr_real_params[i], pr->pr_params[i],
|
||||
f->parm_size[i].size);
|
||||
}
|
||||
}
|
||||
for (; i < 2; i++) {
|
||||
paramofs += pr->pr_param_size;
|
||||
size[i] = pr->pr_param_size;
|
||||
dparmsize_t parmsize = { pr->pr_param_size, pr->pr_param_alignment };
|
||||
paramofs = align_offset (paramofs, parmsize );
|
||||
if (i < MAX_PARMS) {
|
||||
dstParams[i] = pr->pr_globals + paramofs;
|
||||
}
|
||||
count = i;
|
||||
}
|
||||
|
||||
for (i = 0; i < count && i < pr->pr_argc; i++) {
|
||||
offs = (pr->pr_params[i] - pr->pr_globals) - f->parm_start;
|
||||
if (offs >= 0 && offs < paramofs) {
|
||||
memcpy (pr->pr_real_params[i], pr->pr_params[i],
|
||||
size[i] * sizeof (pr_type_t));
|
||||
pr->pr_params[i] = pr->pr_real_params[i];
|
||||
for (; i < pr->pr_argc; i++) {
|
||||
if (pr->pr_params[i] != pr->pr_real_params[i]) {
|
||||
copy_param (pr->pr_real_params[i], pr->pr_params[i],
|
||||
parmsize.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,44 +214,36 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f)
|
|||
pr->pr_xstatement = f->first_statement - 1; // offset the st++
|
||||
|
||||
// save off any locals that the new function steps on
|
||||
c = f->locals;
|
||||
if (pr->localstack_used + c > LOCALSTACK_SIZE)
|
||||
if (pr->localstack_used + f->locals > LOCALSTACK_SIZE)
|
||||
PR_RunError (pr, "PR_EnterFunction: locals stack overflow");
|
||||
|
||||
memcpy (&pr->localstack[pr->localstack_used],
|
||||
&pr->pr_globals[f->parm_start],
|
||||
sizeof (pr_type_t) * c);
|
||||
pr->localstack_used += c;
|
||||
sizeof (pr_type_t) * f->locals);
|
||||
pr->localstack_used += f->locals;
|
||||
|
||||
if (pr_deadbeef_locals->int_val)
|
||||
for (k = f->parm_start; k < f->parm_start + c; k++)
|
||||
pr->pr_globals[k].integer_var = 0xdeadbeef;
|
||||
for (i = f->parm_start; i < f->parm_start + f->locals; i++)
|
||||
pr->pr_globals[i].integer_var = 0xdeadbeef;
|
||||
|
||||
// copy parameters
|
||||
o = f->parm_start;
|
||||
if (f->numparms >= 0) {
|
||||
for (i = 0; i < f->numparms; i++) {
|
||||
for (j = 0; j < f->parm_size[i]; j++) {
|
||||
memcpy (&pr->pr_globals[o], &P_INT (pr, i) + j,
|
||||
sizeof (pr_type_t));
|
||||
o++;
|
||||
}
|
||||
copy_param (dstParams[i], pr->pr_params[i], f->parm_size[i].size);
|
||||
}
|
||||
} else {
|
||||
pr_type_t *argc = &pr->pr_globals[o++];
|
||||
pr_type_t *argv = &pr->pr_globals[o++];
|
||||
int copy_args;
|
||||
pr_type_t *argc = &pr->pr_globals[f->parm_start + 0];
|
||||
pr_type_t *argv = &pr->pr_globals[f->parm_start + 1];
|
||||
for (i = 0; i < -f->numparms - 1; i++) {
|
||||
for (j = 0; j < f->parm_size[i]; j++) {
|
||||
memcpy (&pr->pr_globals[o], &P_INT (pr, i) + j,
|
||||
sizeof (pr_type_t));
|
||||
o++;
|
||||
}
|
||||
copy_param (dstParams[i], pr->pr_params[i], f->parm_size[i].size);
|
||||
}
|
||||
argc->integer_var = pr->pr_argc - i;
|
||||
argv->integer_var = o;
|
||||
copy_args = pr->pr_argc - i;
|
||||
argc->integer_var = copy_args;
|
||||
argv->integer_var = dstParams[i] - pr->pr_globals;
|
||||
if (i < MAX_PARMS) {
|
||||
memcpy (&pr->pr_globals[o], &P_INT (pr, i),
|
||||
(MAX_PARMS - i) * pr->pr_param_size * sizeof (pr_type_t));
|
||||
memcpy (dstParams[i], pr->pr_params[i],
|
||||
(copy_args * pr->pr_param_size) * sizeof (pr_type_t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -239,19 +251,18 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f)
|
|||
static void
|
||||
PR_LeaveFunction (progs_t *pr)
|
||||
{
|
||||
int c;
|
||||
bfunction_t *f = pr->pr_xfunction;
|
||||
|
||||
PR_PopFrame (pr);
|
||||
|
||||
// restore locals from the stack
|
||||
c = f->locals;
|
||||
pr->localstack_used -= c;
|
||||
pr->localstack_used -= f->locals;
|
||||
if (pr->localstack_used < 0)
|
||||
PR_RunError (pr, "PR_LeaveFunction: locals stack underflow");
|
||||
|
||||
memcpy (&pr->pr_globals[f->parm_start],
|
||||
&pr->localstack[pr->localstack_used], sizeof (pr_type_t) * c);
|
||||
&pr->localstack[pr->localstack_used],
|
||||
sizeof (pr_type_t) * f->locals);
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
|
@ -280,12 +291,15 @@ PR_BoundsCheck (progs_t *pr, int addr, etype_t type)
|
|||
#define OPB (*op_b)
|
||||
#define OPC (*op_c)
|
||||
|
||||
#define OPA_double_var (*((double *) (op_a)))
|
||||
#define OPB_double_var (*((double *) (op_b)))
|
||||
#define OPC_double_var (*((double *) (op_c)))
|
||||
|
||||
/*
|
||||
This gets around the problem of needing to test for -0.0 but denormals
|
||||
causing exceptions (or wrong results for what we need) on the alpha.
|
||||
*/
|
||||
#define FNZ(x) ((x).uinteger_var && (x).uinteger_var != 0x80000000u)
|
||||
|
||||
#define FNZ(x) ((x).uinteger_var & ~0x80000000u)
|
||||
|
||||
static int
|
||||
signal_hook (int sig, void *data)
|
||||
|
@ -317,6 +331,8 @@ signal_hook (int sig, void *data)
|
|||
return 1;
|
||||
case OP_MOD_I:
|
||||
case OP_MOD_F:
|
||||
case OP_REM_I:
|
||||
case OP_REM_F:
|
||||
OPC.integer_var = 0x00000000;
|
||||
return 1;
|
||||
default:
|
||||
|
@ -421,6 +437,9 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
PR_PrintStatement (pr, st, 1);
|
||||
|
||||
switch (st->op) {
|
||||
case OP_ADD_D:
|
||||
OPC_double_var = OPA_double_var + OPB_double_var;
|
||||
break;
|
||||
case OP_ADD_F:
|
||||
OPC.float_var = OPA.float_var + OPB.float_var;
|
||||
break;
|
||||
|
@ -437,6 +456,9 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
PR_GetString (pr,
|
||||
OPB.string_var));
|
||||
break;
|
||||
case OP_SUB_D:
|
||||
OPC_double_var = OPA_double_var - OPB_double_var;
|
||||
break;
|
||||
case OP_SUB_F:
|
||||
OPC.float_var = OPA.float_var - OPB.float_var;
|
||||
break;
|
||||
|
@ -446,12 +468,31 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
case OP_SUB_Q:
|
||||
QuatSubtract (OPA.quat_var, OPB.quat_var, OPC.quat_var);
|
||||
break;
|
||||
case OP_MUL_D:
|
||||
OPC_double_var = OPA_double_var * OPB_double_var;
|
||||
break;
|
||||
case OP_MUL_F:
|
||||
OPC.float_var = OPA.float_var * OPB.float_var;
|
||||
break;
|
||||
case OP_MUL_V:
|
||||
OPC.float_var = DotProduct (OPA.vector_var, OPB.vector_var);
|
||||
break;
|
||||
case OP_MUL_DV:
|
||||
{
|
||||
// avoid issues with the likes of x = x.x * x;
|
||||
// makes for faster code, too
|
||||
double scale = OPA_double_var;
|
||||
VectorScale (OPB.vector_var, scale, OPC.vector_var);
|
||||
}
|
||||
break;
|
||||
case OP_MUL_VD:
|
||||
{
|
||||
// avoid issues with the likes of x = x * x.x;
|
||||
// makes for faster code, too
|
||||
double scale = OPB_double_var;
|
||||
VectorScale (OPA.vector_var, scale, OPC.vector_var);
|
||||
}
|
||||
break;
|
||||
case OP_MUL_FV:
|
||||
{
|
||||
// avoid issues with the likes of x = x.x * x;
|
||||
|
@ -474,6 +515,22 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
case OP_MUL_QV:
|
||||
QuatMultVec (OPA.quat_var, OPB.vector_var, OPC.vector_var);
|
||||
break;
|
||||
case OP_MUL_DQ:
|
||||
{
|
||||
// avoid issues with the likes of x = x.s * x;
|
||||
// makes for faster code, too
|
||||
double scale = OPA_double_var;
|
||||
QuatScale (OPB.quat_var, scale, OPC.quat_var);
|
||||
}
|
||||
break;
|
||||
case OP_MUL_QD:
|
||||
{
|
||||
// avoid issues with the likes of x = x * x.s;
|
||||
// makes for faster code, too
|
||||
double scale = OPB_double_var;
|
||||
QuatScale (OPA.quat_var, scale, OPC.quat_var);
|
||||
}
|
||||
break;
|
||||
case OP_MUL_FQ:
|
||||
{
|
||||
// avoid issues with the likes of x = x.s * x;
|
||||
|
@ -493,6 +550,9 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
case OP_CONJ_Q:
|
||||
QuatConj (OPA.quat_var, OPC.quat_var);
|
||||
break;
|
||||
case OP_DIV_D:
|
||||
OPC_double_var = OPA_double_var / OPB_double_var;
|
||||
break;
|
||||
case OP_DIV_F:
|
||||
OPC.float_var = OPA.float_var / OPB.float_var;
|
||||
break;
|
||||
|
@ -630,6 +690,9 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
case OP_STORE_Q:
|
||||
QuatCopy (OPA.quat_var, OPB.quat_var);
|
||||
break;
|
||||
case OP_STORE_D:
|
||||
OPB_double_var = OPA_double_var;
|
||||
break;
|
||||
|
||||
case OP_STOREP_F:
|
||||
case OP_STOREP_ENT:
|
||||
|
@ -661,6 +724,14 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
ptr = pr->pr_globals + pointer;
|
||||
QuatCopy (OPA.quat_var, ptr->quat_var);
|
||||
break;
|
||||
case OP_STOREP_D:
|
||||
pointer = OPB.integer_var;
|
||||
if (pr_boundscheck->int_val) {
|
||||
PR_BoundsCheck (pr, pointer, ev_double);
|
||||
}
|
||||
ptr = pr->pr_globals + pointer;
|
||||
*(double *) ptr = OPA_double_var;
|
||||
break;
|
||||
|
||||
case OP_ADDRESS:
|
||||
if (pr_boundscheck->int_val) {
|
||||
|
@ -687,6 +758,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
case OP_ADDRESS_FN:
|
||||
case OP_ADDRESS_I:
|
||||
case OP_ADDRESS_P:
|
||||
case OP_ADDRESS_D:
|
||||
OPC.integer_var = st->a;
|
||||
break;
|
||||
|
||||
|
@ -735,6 +807,19 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
ed = PROG_TO_EDICT (pr, OPA.entity_var);
|
||||
memcpy (&OPC, &ed->v[OPB.integer_var], 4 * sizeof (OPC));
|
||||
break;
|
||||
case OP_LOAD_D:
|
||||
if (pr_boundscheck->int_val) {
|
||||
if (OPA.entity_var < 0
|
||||
|| OPA.entity_var >= pr->pr_edictareasize)
|
||||
PR_RunError (pr, "Progs attempted to read an out of "
|
||||
"bounds edict number");
|
||||
if (OPB.uinteger_var + 1 >= pr->progs->entityfields)
|
||||
PR_RunError (pr, "Progs attempted to read an invalid "
|
||||
"field in an edict");
|
||||
}
|
||||
ed = PROG_TO_EDICT (pr, OPA.entity_var);
|
||||
OPC_double_var = *(double *) (ed->v + OPB.integer_var);
|
||||
break;
|
||||
|
||||
case OP_LOADB_F:
|
||||
case OP_LOADB_S:
|
||||
|
@ -766,6 +851,14 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
ptr = pr->pr_globals + pointer;
|
||||
QuatCopy (ptr->quat_var, OPC.quat_var);
|
||||
break;
|
||||
case OP_LOADB_D:
|
||||
pointer = OPA.integer_var + OPB.integer_var;
|
||||
if (pr_boundscheck->int_val) {
|
||||
PR_BoundsCheck (pr, pointer, ev_double);
|
||||
}
|
||||
ptr = pr->pr_globals + pointer;
|
||||
OPC_double_var = *(double *) ptr;
|
||||
break;
|
||||
|
||||
case OP_LOADBI_F:
|
||||
case OP_LOADBI_S:
|
||||
|
@ -797,6 +890,14 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
ptr = pr->pr_globals + pointer;
|
||||
QuatCopy (ptr->quat_var, OPC.quat_var);
|
||||
break;
|
||||
case OP_LOADBI_D:
|
||||
pointer = OPA.integer_var + (short) st->b;
|
||||
if (pr_boundscheck->int_val) {
|
||||
PR_BoundsCheck (pr, pointer, ev_quat);
|
||||
}
|
||||
ptr = pr->pr_globals + pointer;
|
||||
OPC_double_var = *(double *) ptr;
|
||||
break;
|
||||
|
||||
case OP_LEA:
|
||||
pointer = OPA.integer_var + OPB.integer_var;
|
||||
|
@ -838,6 +939,14 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
ptr = pr->pr_globals + pointer;
|
||||
QuatCopy (OPA.quat_var, ptr->quat_var);
|
||||
break;
|
||||
case OP_STOREB_D:
|
||||
pointer = OPB.integer_var + OPC.integer_var;
|
||||
if (pr_boundscheck->int_val) {
|
||||
PR_BoundsCheck (pr, pointer, ev_quat);
|
||||
}
|
||||
ptr = pr->pr_globals + pointer;
|
||||
*(double *) ptr = OPA_double_var;
|
||||
break;
|
||||
|
||||
case OP_STOREBI_F:
|
||||
case OP_STOREBI_S:
|
||||
|
@ -869,6 +978,14 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
ptr = pr->pr_globals + pointer;
|
||||
QuatCopy (OPA.quat_var, ptr->quat_var);
|
||||
break;
|
||||
case OP_STOREBI_D:
|
||||
pointer = OPB.integer_var + (short) st->c;
|
||||
if (pr_boundscheck->int_val) {
|
||||
PR_BoundsCheck (pr, pointer, ev_quat);
|
||||
}
|
||||
ptr = pr->pr_globals + pointer;
|
||||
*(double *) ptr = OPA_double_var;
|
||||
break;
|
||||
|
||||
case OP_PUSH_F:
|
||||
case OP_PUSH_FLD:
|
||||
|
@ -1322,22 +1439,58 @@ op_call:
|
|||
case OP_MUL_I:
|
||||
OPC.integer_var = OPA.integer_var * OPB.integer_var;
|
||||
break;
|
||||
/*
|
||||
case OP_DIV_VF:
|
||||
{
|
||||
float temp = 1.0f / OPB.float_var;
|
||||
VectorScale (OPA.vector_var, temp, OPC.vector_var);
|
||||
}
|
||||
break;
|
||||
*/
|
||||
case OP_DIV_I:
|
||||
OPC.integer_var = OPA.integer_var / OPB.integer_var;
|
||||
break;
|
||||
case OP_MOD_I:
|
||||
{
|
||||
// implement true modulo for integers:
|
||||
// 5 mod 3 = 2
|
||||
// -5 mod 3 = 1
|
||||
// 5 mod -3 = -1
|
||||
// -5 mod -3 = -2
|
||||
int a = OPA.integer_var;
|
||||
int b = OPB.integer_var;
|
||||
int c = a % b;
|
||||
// % is really remainder and so has the same sign rules
|
||||
// as division: -5 % 3 = -2, so need to add b (3 here)
|
||||
// if c's sign is incorrect, but only if c is non-zero
|
||||
int mask = (a ^ b) >> 31;
|
||||
mask &= ~(!!c + 0) + 1; // +0 to convert bool to int (gcc)
|
||||
OPC.integer_var = c + (mask & b);
|
||||
}
|
||||
break;
|
||||
case OP_REM_I:
|
||||
OPC.integer_var = OPA.integer_var % OPB.integer_var;
|
||||
break;
|
||||
case OP_MOD_D:
|
||||
{
|
||||
double a = OPA_double_var;
|
||||
double b = OPB_double_var;
|
||||
// floating point modulo is so much easier :P
|
||||
OPC_double_var = a - b * floor (a / b);
|
||||
}
|
||||
break;
|
||||
case OP_REM_D:
|
||||
{
|
||||
double a = OPA_double_var;
|
||||
double b = OPB_double_var;
|
||||
OPC_double_var = a - b * trunc (a / b);
|
||||
}
|
||||
break;
|
||||
case OP_MOD_F:
|
||||
OPC.float_var = (int) OPA.float_var % (int) OPB.float_var;
|
||||
{
|
||||
float a = OPA.float_var;
|
||||
float b = OPB.float_var;
|
||||
OPC.float_var = a - b * floorf (a / b);
|
||||
}
|
||||
break;
|
||||
case OP_REM_F:
|
||||
{
|
||||
float a = OPA.float_var;
|
||||
float b = OPB.float_var;
|
||||
OPC.float_var = a - b * truncf (a / b);
|
||||
}
|
||||
break;
|
||||
case OP_CONV_IF:
|
||||
OPC.float_var = OPA.integer_var;
|
||||
|
@ -1428,6 +1581,41 @@ op_call:
|
|||
st->b * 4);
|
||||
break;
|
||||
|
||||
case OP_GE_D:
|
||||
OPC.float_var = OPA_double_var >= OPB_double_var;
|
||||
break;
|
||||
case OP_LE_D:
|
||||
OPC.float_var = OPA_double_var <= OPB_double_var;
|
||||
break;
|
||||
case OP_GT_D:
|
||||
OPC.float_var = OPA_double_var > OPB_double_var;
|
||||
break;
|
||||
case OP_LT_D:
|
||||
OPC.float_var = OPA_double_var < OPB_double_var;
|
||||
break;
|
||||
case OP_NOT_D:
|
||||
OPC.integer_var = (op_a[0].integer_var
|
||||
|| (op_a[1].integer_var & ~0x80000000u));
|
||||
break;
|
||||
case OP_EQ_D:
|
||||
OPC.integer_var = OPA_double_var == OPB_double_var;
|
||||
break;
|
||||
case OP_NE_D:
|
||||
OPC.integer_var = OPA_double_var != OPB_double_var;
|
||||
break;
|
||||
case OP_CONV_ID:
|
||||
OPC_double_var = OPA.integer_var;
|
||||
break;
|
||||
case OP_CONV_DI:
|
||||
OPC.integer_var = OPA_double_var;
|
||||
break;
|
||||
case OP_CONV_FD:
|
||||
OPC_double_var = OPA.float_var;
|
||||
break;
|
||||
case OP_CONV_DF:
|
||||
OPC.float_var = OPA_double_var;
|
||||
break;
|
||||
|
||||
// LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized
|
||||
/*
|
||||
case OP_BOUNDCHECK:
|
||||
|
|
|
@ -202,6 +202,8 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size)
|
|||
base -= sizeof (progs); // offsets are from file start
|
||||
heap = ((byte *) pr->progs + pr->progs_size + pr->pr_edictareasize);
|
||||
|
||||
pr->float_promoted = progs.version == PROG_VERSION;
|
||||
|
||||
if (pr->edicts) {
|
||||
*pr->edicts = (edict_t *)((byte *) pr->progs + pr->progs_size);
|
||||
}
|
||||
|
|
|
@ -61,6 +61,7 @@ VISIBLE int pr_type_size[ev_type_count] = {
|
|||
1, // ev_integer
|
||||
1, // ev_uinteger
|
||||
0, // ev_short value in opcode
|
||||
2, // ev_double
|
||||
};
|
||||
|
||||
VISIBLE const char *pr_type_name[ev_type_count] = {
|
||||
|
@ -76,6 +77,7 @@ VISIBLE const char *pr_type_name[ev_type_count] = {
|
|||
"integer",
|
||||
"uinteger",
|
||||
"short",
|
||||
"double",
|
||||
"invalid",
|
||||
};
|
||||
|
||||
|
@ -102,6 +104,10 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
"%Va",
|
||||
},
|
||||
|
||||
{"*", "mul.d", OP_MUL_D, false,
|
||||
ev_double, ev_double, ev_double,
|
||||
PROG_VERSION,
|
||||
},
|
||||
{"*", "mul.f", OP_MUL_F, false,
|
||||
ev_float, ev_float, ev_float,
|
||||
PROG_ID_VERSION,
|
||||
|
@ -118,6 +124,14 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
ev_vector, ev_float, ev_vector,
|
||||
PROG_ID_VERSION,
|
||||
},
|
||||
{"*", "mul.dv", OP_MUL_DV, false,
|
||||
ev_double, ev_vector, ev_vector,
|
||||
PROG_ID_VERSION,
|
||||
},
|
||||
{"*", "mul.vd", OP_MUL_VD, false,
|
||||
ev_vector, ev_double, ev_vector,
|
||||
PROG_ID_VERSION,
|
||||
},
|
||||
{"*", "mul.q", OP_MUL_Q, false,
|
||||
ev_quat, ev_quat, ev_quat,
|
||||
PROG_VERSION,
|
||||
|
@ -130,6 +144,14 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
ev_quat, ev_float, ev_quat,
|
||||
PROG_VERSION,
|
||||
},
|
||||
{"*", "mul.dq", OP_MUL_DQ, false,
|
||||
ev_double, ev_quat, ev_quat,
|
||||
PROG_VERSION,
|
||||
},
|
||||
{"*", "mul.qd", OP_MUL_QD, false,
|
||||
ev_quat, ev_double, ev_quat,
|
||||
PROG_VERSION,
|
||||
},
|
||||
{"*", "mul.qv", OP_MUL_QV, false,
|
||||
ev_quat, ev_vector, ev_vector,
|
||||
PROG_VERSION,
|
||||
|
@ -145,7 +167,23 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
ev_float, ev_float, ev_float,
|
||||
PROG_ID_VERSION,
|
||||
},
|
||||
{"/", "div.d", OP_DIV_D, false,
|
||||
ev_double, ev_double, ev_double,
|
||||
PROG_VERSION,
|
||||
},
|
||||
{"%", "rem.d", OP_REM_D, false,
|
||||
ev_double, ev_double, ev_double,
|
||||
PROG_VERSION,
|
||||
},
|
||||
{"%%", "mod.d", OP_MOD_D, false,
|
||||
ev_double, ev_double, ev_double,
|
||||
PROG_VERSION,
|
||||
},
|
||||
|
||||
{"+", "add.d", OP_ADD_D, false,
|
||||
ev_double, ev_double, ev_double,
|
||||
PROG_VERSION,
|
||||
},
|
||||
{"+", "add.f", OP_ADD_F, false,
|
||||
ev_float, ev_float, ev_float,
|
||||
PROG_ID_VERSION,
|
||||
|
@ -163,6 +201,10 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
PROG_VERSION,
|
||||
},
|
||||
|
||||
{"-", "sub.d", OP_SUB_D, false,
|
||||
ev_double, ev_double, ev_double,
|
||||
PROG_VERSION,
|
||||
},
|
||||
{"-", "sub.f", OP_SUB_F, false,
|
||||
ev_float, ev_float, ev_float,
|
||||
PROG_ID_VERSION,
|
||||
|
@ -176,6 +218,10 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
PROG_VERSION,
|
||||
},
|
||||
|
||||
{"==", "eq.d", OP_EQ_D, false,
|
||||
ev_double, ev_double, ev_integer,
|
||||
PROG_VERSION,
|
||||
},
|
||||
{"==", "eq.f", OP_EQ_F, false,
|
||||
ev_float, ev_float, ev_integer,
|
||||
PROG_ID_VERSION,
|
||||
|
@ -201,6 +247,10 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
PROG_ID_VERSION,
|
||||
},
|
||||
|
||||
{"!=", "ne.d", OP_NE_D, false,
|
||||
ev_double, ev_double, ev_integer,
|
||||
PROG_VERSION,
|
||||
},
|
||||
{"!=", "ne.f", OP_NE_F, false,
|
||||
ev_float, ev_float, ev_integer,
|
||||
PROG_ID_VERSION,
|
||||
|
@ -226,10 +276,18 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
PROG_ID_VERSION,
|
||||
},
|
||||
|
||||
{"<=", "le.d", OP_LE_D, false,
|
||||
ev_double, ev_double, ev_integer,
|
||||
PROG_VERSION,
|
||||
},
|
||||
{"<=", "le.f", OP_LE_F, false,
|
||||
ev_float, ev_float, ev_integer,
|
||||
PROG_ID_VERSION,
|
||||
},
|
||||
{">=", "ge.d", OP_GE_D, false,
|
||||
ev_double, ev_double, ev_integer,
|
||||
PROG_VERSION,
|
||||
},
|
||||
{">=", "ge.f", OP_GE_F, false,
|
||||
ev_float, ev_float, ev_integer,
|
||||
PROG_ID_VERSION,
|
||||
|
@ -242,10 +300,18 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
ev_string, ev_string, ev_integer,
|
||||
PROG_VERSION,
|
||||
},
|
||||
{"<", "lt.d", OP_LT_D, false,
|
||||
ev_double, ev_double, ev_integer,
|
||||
PROG_VERSION,
|
||||
},
|
||||
{"<", "lt.f", OP_LT_F, false,
|
||||
ev_float, ev_float, ev_integer,
|
||||
PROG_ID_VERSION,
|
||||
},
|
||||
{">", "gt.d", OP_GT_D, false,
|
||||
ev_double, ev_double, ev_integer,
|
||||
PROG_VERSION,
|
||||
},
|
||||
{">", "gt.f", OP_GT_F, false,
|
||||
ev_float, ev_float, ev_integer,
|
||||
PROG_ID_VERSION,
|
||||
|
@ -264,6 +330,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
PROG_ID_VERSION,
|
||||
"%Ga.%Gb(%Ec), %gc",//FIXME %E more flexible?
|
||||
},
|
||||
{".", "load.d", OP_LOAD_D, false,
|
||||
ev_entity, ev_field, ev_double,
|
||||
PROG_VERSION,
|
||||
"%Ga.%Gb(%Ec), %gc",
|
||||
},
|
||||
{".", "load.v", OP_LOAD_V, false,
|
||||
ev_entity, ev_field, ev_vector,
|
||||
PROG_ID_VERSION,
|
||||
|
@ -305,6 +376,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
"%Ga.%Gb(%Ec), %gc",
|
||||
},
|
||||
|
||||
{".", "loadb.d", OP_LOADB_D, false,
|
||||
ev_pointer, ev_integer, ev_double,
|
||||
PROG_VERSION,
|
||||
"*(%Ga + %Gb), %gc",
|
||||
},
|
||||
{".", "loadb.f", OP_LOADB_F, false,
|
||||
ev_pointer, ev_integer, ev_float,
|
||||
PROG_VERSION,
|
||||
|
@ -351,6 +427,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
"*(%Ga + %Gb), %gc",
|
||||
},
|
||||
|
||||
{".", "loadbi.d", OP_LOADBI_D, false,
|
||||
ev_pointer, ev_short, ev_double,
|
||||
PROG_VERSION,
|
||||
"*(%Ga + %sb), %gc",
|
||||
},
|
||||
{".", "loadbi.f", OP_LOADBI_F, false,
|
||||
ev_pointer, ev_short, ev_float,
|
||||
PROG_VERSION,
|
||||
|
@ -408,6 +489,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
PROG_VERSION,
|
||||
"%Ga, %gc",
|
||||
},
|
||||
{"&", "address.d", OP_ADDRESS_D, false,
|
||||
ev_double, ev_invalid, ev_pointer,
|
||||
PROG_VERSION,
|
||||
"%Ga, %gc",
|
||||
},
|
||||
{"&", "address.f", OP_ADDRESS_F, false,
|
||||
ev_float, ev_invalid, ev_pointer,
|
||||
PROG_VERSION,
|
||||
|
@ -475,7 +561,32 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
PROG_VERSION,
|
||||
"%Ga, %gc",
|
||||
},
|
||||
{"<CONV>", "conv.id", OP_CONV_ID, false,
|
||||
ev_integer, ev_invalid, ev_double,
|
||||
PROG_VERSION,
|
||||
"%Ga, %gc",
|
||||
},
|
||||
{"<CONV>", "conv.di", OP_CONV_DI, false,
|
||||
ev_double, ev_invalid, ev_integer,
|
||||
PROG_VERSION,
|
||||
"%Ga, %gc",
|
||||
},
|
||||
{"<CONV>", "conv.fd", OP_CONV_FD, false,
|
||||
ev_float, ev_invalid, ev_double,
|
||||
PROG_VERSION,
|
||||
"%Ga, %gc",
|
||||
},
|
||||
{"<CONV>", "conv.df", OP_CONV_DF, false,
|
||||
ev_double, ev_invalid, ev_float,
|
||||
PROG_VERSION,
|
||||
"%Ga, %gc",
|
||||
},
|
||||
|
||||
{"=", "store.d", OP_STORE_D, true,
|
||||
ev_double, ev_double, ev_invalid,
|
||||
PROG_VERSION,
|
||||
"%Ga, %gb",
|
||||
},
|
||||
{"=", "store.f", OP_STORE_F, true,
|
||||
ev_float, ev_float, ev_invalid,
|
||||
PROG_ID_VERSION,
|
||||
|
@ -522,6 +633,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
"%Ga, %gb",
|
||||
},
|
||||
|
||||
{".=", "storep.d", OP_STOREP_D, true,
|
||||
ev_double, ev_pointer, ev_invalid,
|
||||
PROG_ID_VERSION,
|
||||
"%Ga, *%Gb",
|
||||
},
|
||||
{".=", "storep.f", OP_STOREP_F, true,
|
||||
ev_float, ev_pointer, ev_invalid,
|
||||
PROG_ID_VERSION,
|
||||
|
@ -568,6 +684,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
"%Ga, *%Gb",
|
||||
},
|
||||
|
||||
{".=", "storeb.d", OP_STOREB_D, true,
|
||||
ev_double, ev_pointer, ev_integer,
|
||||
PROG_VERSION,
|
||||
"%Ga, *(%Gb + %Gc)",
|
||||
},
|
||||
{".=", "storeb.f", OP_STOREB_F, true,
|
||||
ev_float, ev_pointer, ev_integer,
|
||||
PROG_VERSION,
|
||||
|
@ -614,6 +735,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
"%Ga, *(%Gb + %Gc)",
|
||||
},
|
||||
|
||||
{".=", "storebi.d", OP_STOREBI_D, true,
|
||||
ev_double, ev_pointer, ev_short,
|
||||
PROG_VERSION,
|
||||
"%Ga, *(%Gb + %sc)",
|
||||
},
|
||||
{".=", "storebi.f", OP_STOREBI_F, true,
|
||||
ev_float, ev_pointer, ev_short,
|
||||
PROG_VERSION,
|
||||
|
@ -672,6 +798,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
"",
|
||||
},
|
||||
|
||||
{"!", "not.d", OP_NOT_D, false,
|
||||
ev_double, ev_invalid, ev_integer,
|
||||
PROG_VERSION,
|
||||
"%Ga, %gc",
|
||||
},
|
||||
{"!", "not.f", OP_NOT_F, false,
|
||||
ev_float, ev_invalid, ev_integer,
|
||||
PROG_ID_VERSION,
|
||||
|
@ -909,7 +1040,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
ev_integer, ev_integer, ev_integer,
|
||||
PROG_VERSION,
|
||||
},
|
||||
{"%", "mod.i", OP_MOD_I, false,
|
||||
{"%", "rem.i", OP_REM_I, false,
|
||||
ev_integer, ev_integer, ev_integer,
|
||||
PROG_VERSION,
|
||||
},
|
||||
{"%%", "mod.i", OP_MOD_I, false,
|
||||
ev_integer, ev_integer, ev_integer,
|
||||
PROG_VERSION,
|
||||
},
|
||||
|
@ -922,7 +1057,12 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
PROG_VERSION,
|
||||
},
|
||||
|
||||
{"%", "mod.f", OP_MOD_F, false,
|
||||
{"%", "rem.f", OP_REM_F, false,
|
||||
ev_float, ev_float, ev_float,
|
||||
PROG_VERSION,
|
||||
},
|
||||
|
||||
{"%%", "mod.f", OP_MOD_F, false,
|
||||
ev_float, ev_float, ev_float,
|
||||
PROG_VERSION,
|
||||
},
|
||||
|
|
|
@ -122,6 +122,7 @@ PR_ResolveGlobals (progs_t *pr)
|
|||
pr->pr_params[6] = &pr->pr_globals[OFS_PARM6];
|
||||
pr->pr_params[7] = &pr->pr_globals[OFS_PARM7];
|
||||
pr->pr_param_size = OFS_PARM1 - OFS_PARM0;
|
||||
pr->pr_param_alignment = 0; // log2
|
||||
} else {
|
||||
if (!(def = PR_FindGlobal (pr, sym = ".return")))
|
||||
goto error;
|
||||
|
@ -134,6 +135,9 @@ PR_ResolveGlobals (progs_t *pr)
|
|||
if (!(def = PR_FindGlobal (pr, sym = ".param_size")))
|
||||
goto error;
|
||||
pr->pr_param_size = G_INT (pr, def->ofs);
|
||||
if (!(def = PR_FindGlobal (pr, sym = ".param_alignment")))
|
||||
goto error;
|
||||
pr->pr_param_alignment = G_INT (pr, def->ofs);
|
||||
}
|
||||
if (pr->pr_saved_params)
|
||||
free (pr->pr_saved_params);
|
||||
|
|
|
@ -70,6 +70,7 @@ struct strref_s {
|
|||
#define FMT_ADDSIGN (1<<3)
|
||||
#define FMT_ADDBLANK (1<<4)
|
||||
#define FMT_HEX (1<<5)
|
||||
#define FMT_LONG (1<<6)
|
||||
|
||||
typedef struct fmt_item_s {
|
||||
byte type;
|
||||
|
@ -81,6 +82,7 @@ typedef struct fmt_item_s {
|
|||
int integer_var;
|
||||
unsigned uinteger_var;
|
||||
float float_var;
|
||||
double double_var;
|
||||
} data;
|
||||
struct fmt_item_s *next;
|
||||
} fmt_item_t;
|
||||
|
@ -596,11 +598,19 @@ I_DoPrint (dstring_t *result, fmt_item_t *formatting)
|
|||
break;
|
||||
case 'f':
|
||||
dstring_appendstr (tmp, "f");
|
||||
PRINT (float);
|
||||
if (current->flags & FMT_LONG) {
|
||||
PRINT (double);
|
||||
} else {
|
||||
PRINT (float);
|
||||
}
|
||||
break;
|
||||
case 'g':
|
||||
dstring_appendstr (tmp, "g");
|
||||
PRINT (float);
|
||||
if (current->flags & FMT_LONG) {
|
||||
PRINT (double);
|
||||
} else {
|
||||
PRINT (float);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -639,6 +649,8 @@ free_fmt_item (fmt_item_t *fi)
|
|||
|
||||
#undef P_var
|
||||
#define P_var(p,n,t) (args[n]->t##_var)
|
||||
#undef P_DOUBLE
|
||||
#define P_DOUBLE(p,n) (*(double *) (args[n]))
|
||||
VISIBLE void
|
||||
PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
|
||||
const char *format, int count, pr_type_t **args)
|
||||
|
@ -650,7 +662,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
|
|||
int fmt_count = 0;
|
||||
|
||||
if (!name)
|
||||
name = "PF_InternalSprintf";
|
||||
name = "PR_Sprintf";
|
||||
|
||||
*fi = new_fmt_item ();
|
||||
c = l = format;
|
||||
|
@ -742,12 +754,19 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
|
|||
fi = &(*fi)->next;
|
||||
break;
|
||||
case 'f':
|
||||
// float
|
||||
// float or double
|
||||
case 'g':
|
||||
// float, no trailing zeroes, trim "." if nothing
|
||||
// after
|
||||
// float or double, no trailing zeroes, trim "."
|
||||
// if nothing after
|
||||
(*fi)->type = *c;
|
||||
(*fi)->data.float_var = P_FLOAT (pr, fmt_count);
|
||||
if (pr->float_promoted) {
|
||||
(*fi)->flags |= FMT_LONG;
|
||||
(*fi)->data.double_var
|
||||
= P_DOUBLE (pr, fmt_count);
|
||||
} else {
|
||||
(*fi)->data.float_var
|
||||
= P_FLOAT (pr, fmt_count);
|
||||
}
|
||||
|
||||
fmt_count++;
|
||||
(*fi)->next = new_fmt_item ();
|
||||
|
|
|
@ -42,55 +42,55 @@
|
|||
#include "rua_internal.h"
|
||||
|
||||
static void
|
||||
bi_sin (progs_t *pr)
|
||||
bi_sinf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = sinf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_cos (progs_t *pr)
|
||||
bi_cosf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = cosf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_tan (progs_t *pr)
|
||||
bi_tanf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = tanf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_asin (progs_t *pr)
|
||||
bi_asinf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = asinf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_acos (progs_t *pr)
|
||||
bi_acosf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = acosf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_atan (progs_t *pr)
|
||||
bi_atanf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = atanf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_atan2 (progs_t *pr)
|
||||
bi_atan2f (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = atan2f (P_FLOAT (pr, 0), P_FLOAT (pr, 1));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_log (progs_t *pr)
|
||||
bi_logf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = logf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_log2 (progs_t *pr)
|
||||
bi_log2f (progs_t *pr)
|
||||
{
|
||||
#ifdef HAVE_LOG2F
|
||||
R_FLOAT (pr) = log2f (P_FLOAT (pr, 0));
|
||||
|
@ -100,95 +100,259 @@ bi_log2 (progs_t *pr)
|
|||
}
|
||||
|
||||
static void
|
||||
bi_log10 (progs_t *pr)
|
||||
bi_log10f (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = log10f (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_pow (progs_t *pr)
|
||||
bi_powf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = powf (P_FLOAT (pr, 0), P_FLOAT (pr, 1));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_sqrt (progs_t *pr)
|
||||
bi_sqrtf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = sqrtf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_cbrt (progs_t *pr)
|
||||
bi_cbrtf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = cbrtf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_hypot (progs_t *pr)
|
||||
bi_hypotf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = hypotf (P_FLOAT (pr, 0), P_FLOAT (pr, 1));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_sinh (progs_t *pr)
|
||||
bi_sinhf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = sinhf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_cosh (progs_t *pr)
|
||||
bi_coshf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = coshf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_tanh (progs_t *pr)
|
||||
bi_tanhf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = tanhf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_asinh (progs_t *pr)
|
||||
bi_asinhf (progs_t *pr)
|
||||
{
|
||||
double y = P_FLOAT (pr, 0);
|
||||
R_FLOAT (pr) = logf (y + sqrtf (y * y + 1));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_acosh (progs_t *pr)
|
||||
bi_acoshf (progs_t *pr)
|
||||
{
|
||||
double y = P_FLOAT (pr, 0);
|
||||
R_FLOAT (pr) = logf (y + sqrtf (y * y - 1));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_atanh (progs_t *pr)
|
||||
bi_atanhf (progs_t *pr)
|
||||
{
|
||||
double y = P_FLOAT (pr, 0);
|
||||
R_FLOAT (pr) = logf ((1 + y) / (1 - y)) / 2;
|
||||
}
|
||||
|
||||
static void
|
||||
bi_floor (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = floor (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_ceil (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = ceil (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_fabs (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = fabs (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_sin (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = sin (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_cos (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = cos (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_tan (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = tan (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_asin (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = asin (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_acos (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = acos (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_atan (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = atan (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_atan2 (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = atan2 (P_DOUBLE (pr, 0), P_DOUBLE (pr, 1));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_log (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = log (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_log2 (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = log (P_DOUBLE (pr, 0)) / M_LOG2E;
|
||||
}
|
||||
|
||||
static void
|
||||
bi_log10 (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = log10 (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_pow (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = pow (P_DOUBLE (pr, 0), P_DOUBLE (pr, 1));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_sqrt (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = sqrt (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_cbrt (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = cbrt (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_hypot (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = hypot (P_DOUBLE (pr, 0), P_DOUBLE (pr, 1));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_sinh (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = sinh (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_cosh (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = cosh (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_tanh (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = tanh (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_asinh (progs_t *pr)
|
||||
{
|
||||
double y = P_DOUBLE (pr, 0);
|
||||
R_DOUBLE (pr) = log (y + sqrt (y * y + 1));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_acosh (progs_t *pr)
|
||||
{
|
||||
double y = P_DOUBLE (pr, 0);
|
||||
R_DOUBLE (pr) = log (y + sqrt (y * y - 1));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_atanh (progs_t *pr)
|
||||
{
|
||||
double y = P_DOUBLE (pr, 0);
|
||||
R_DOUBLE (pr) = log ((1 + y) / (1 - y)) / 2;
|
||||
}
|
||||
|
||||
static builtin_t builtins[] = {
|
||||
{"sin", bi_sin, -1},
|
||||
{"cos", bi_cos, -1},
|
||||
{"tan", bi_tan, -1},
|
||||
{"asin", bi_asin, -1},
|
||||
{"acos", bi_acos, -1},
|
||||
{"atan", bi_atan, -1},
|
||||
{"atan2", bi_atan2, -1},
|
||||
{"log", bi_log, -1},
|
||||
{"log2", bi_log2, -1},
|
||||
{"log10", bi_log10, -1},
|
||||
{"pow", bi_pow, -1},
|
||||
{"sqrt", bi_sqrt, -1},
|
||||
{"cbrt", bi_cbrt, -1},
|
||||
{"hypot", bi_hypot, -1},
|
||||
{"sinh", bi_sinh, -1},
|
||||
{"cosh", bi_cosh, -1},
|
||||
{"tanh", bi_tanh, -1},
|
||||
{"asinh", bi_asinh, -1},
|
||||
{"acosh", bi_acosh, -1},
|
||||
{"atanh", bi_atanh, -1},
|
||||
{"sin|f", bi_sinf, -1},
|
||||
{"cos|f", bi_cosf, -1},
|
||||
{"tan|f", bi_tanf, -1},
|
||||
{"asin|f", bi_asinf, -1},
|
||||
{"acos|f", bi_acosf, -1},
|
||||
{"atan|f", bi_atanf, -1},
|
||||
{"atan2|ff",bi_atan2f, -1},
|
||||
{"log|f", bi_logf, -1},
|
||||
{"log2|f", bi_log2f, -1},
|
||||
{"log10|f", bi_log10f, -1},
|
||||
{"pow|ff", bi_powf, -1},
|
||||
{"sqrt|f", bi_sqrtf, -1},
|
||||
{"cbrt|f", bi_cbrtf, -1},
|
||||
{"hypot|ff",bi_hypotf, -1},
|
||||
{"sinh|f", bi_sinhf, -1},
|
||||
{"cosh|f", bi_coshf, -1},
|
||||
{"tanh|f", bi_tanhf, -1},
|
||||
{"asinh|f", bi_asinhf, -1},
|
||||
{"acosh|f", bi_acoshf, -1},
|
||||
{"atanh|f", bi_atanhf, -1},
|
||||
{"floor|d", bi_floor, -1}, // float version in pr_cmds
|
||||
{"ceil|d", bi_ceil, -1}, // float version in pr_cmds
|
||||
{"fabs|d", bi_fabs, -1}, // float version in pr_cmds
|
||||
{"sin|d", bi_sin, -1},
|
||||
{"cos|d", bi_cos, -1},
|
||||
{"tan|d", bi_tan, -1},
|
||||
{"asin|d", bi_asin, -1},
|
||||
{"acos|d", bi_acos, -1},
|
||||
{"atan|d", bi_atan, -1},
|
||||
{"atan2|dd",bi_atan2, -1},
|
||||
{"log|d", bi_log, -1},
|
||||
{"log2|d", bi_log2, -1},
|
||||
{"log10|d", bi_log10, -1},
|
||||
{"pow|dd", bi_pow, -1},
|
||||
{"sqrt|d", bi_sqrt, -1},
|
||||
{"cbrt|d", bi_cbrt, -1},
|
||||
{"hypot|dd",bi_hypot, -1},
|
||||
{"sinh|d", bi_sinh, -1},
|
||||
{"cosh|d", bi_cosh, -1},
|
||||
{"tanh|d", bi_tanh, -1},
|
||||
{"asinh|d", bi_asinh, -1},
|
||||
{"acosh|d", bi_acosh, -1},
|
||||
{"atanh|d", bi_atanh, -1},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
|
|
@ -439,19 +439,23 @@ X11_SetVidMode (int width, int height)
|
|||
&vidmodes);
|
||||
XF86VidModeGetModeLine (x_disp, x_screen, &dotclock, &orig_data);
|
||||
|
||||
if (developer->int_val & SYS_VID) {
|
||||
Sys_Printf ("VID: %d modes\n", nummodes);
|
||||
for (i = 0; i < nummodes; i++) {
|
||||
Sys_Printf ("VID: %xx%d\n", vidmodes[i]->hdisplay,
|
||||
vidmodes[i]->vdisplay);
|
||||
}
|
||||
}
|
||||
|
||||
Sys_MaskPrintf (SYS_VID, "VID: %d modes\n", nummodes);
|
||||
original_mode = -1;
|
||||
for (i = 0; i < nummodes; i++) {
|
||||
if ((vidmodes[i]->hdisplay == orig_data.hdisplay) &&
|
||||
(vidmodes[i]->vdisplay == orig_data.vdisplay)) {
|
||||
if (original_mode == -1
|
||||
&& (vidmodes[i]->hdisplay == orig_data.hdisplay) &&
|
||||
(vidmodes[i]->vdisplay == orig_data.vdisplay)) {
|
||||
original_mode = i;
|
||||
break;
|
||||
}
|
||||
if (developer->int_val & SYS_VID) {
|
||||
Sys_Printf ("VID:%c%dx%d\n",
|
||||
original_mode == i ? '*' : ' ',
|
||||
vidmodes[i]->hdisplay, vidmodes[i]->vdisplay);
|
||||
Sys_Printf ("\t%d %d %d %d:%d %d %d:%d\n",
|
||||
vidmodes[i]->hsyncstart, vidmodes[i]->hsyncend,
|
||||
vidmodes[i]->htotal, vidmodes[i]->hskew,
|
||||
vidmodes[i]->vsyncstart, vidmodes[i]->vsyncend,
|
||||
vidmodes[i]->vtotal, vidmodes[i]->flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -468,8 +472,10 @@ X11_SetVidMode (int width, int height)
|
|||
Sys_MaskPrintf (SYS_VID, "VID: Chose video mode: %dx%d\n",
|
||||
viddef.width, viddef.height);
|
||||
|
||||
if (0) {
|
||||
XF86VidModeSwitchToMode (x_disp, x_screen,
|
||||
vidmodes[best_mode]);
|
||||
}
|
||||
vidmode_active = true;
|
||||
X11_SetScreenSaver ();
|
||||
} else {
|
||||
|
@ -594,7 +600,7 @@ X11_RestoreVidMode (void)
|
|||
#ifdef HAVE_VIDMODE
|
||||
if (vidmode_active) {
|
||||
X11_RestoreScreenSaver ();
|
||||
XF86VidModeSwitchToMode (x_disp, x_screen, vidmodes[original_mode]);
|
||||
//XF86VidModeSwitchToMode (x_disp, x_screen, vidmodes[original_mode]);
|
||||
XFree (vidmodes);
|
||||
vidmode_active = false;
|
||||
}
|
||||
|
|
|
@ -210,6 +210,11 @@ extern progs_t sv_pr_state;
|
|||
#define SVentity(e,f) SVFIELD (e, f, entity)
|
||||
#define SVvector(e,f) SVFIELD (e, f, vector)
|
||||
#define SVinteger(e,f) SVFIELD (e, f, integer)
|
||||
#if TYPECHECK_PROGS
|
||||
#define SVdouble(e,f) E_DOUBLE (e, PR_AccessField (&sv_pr_state, #f, ev_##t, __FILE__, __LINE__))
|
||||
#else
|
||||
#define SVdouble(e,f) E_DOUBLE (e, sv_fields.f)
|
||||
#endif
|
||||
|
||||
typedef struct edict_leaf_s {
|
||||
struct edict_leaf_s *next;
|
||||
|
|
|
@ -361,6 +361,9 @@ set_address (sv_def_t *def, void *address)
|
|||
case ev_quat:
|
||||
*(float **)def->field = (float *) address;
|
||||
break;
|
||||
case ev_double:
|
||||
*(double **)def->field = (double *) address;
|
||||
break;
|
||||
case ev_string:
|
||||
case ev_entity:
|
||||
case ev_field:
|
||||
|
|
|
@ -195,6 +195,11 @@ extern progs_t sv_pr_state;
|
|||
#define SVentity(e,f) SVFIELD (e, f, entity)
|
||||
#define SVvector(e,f) SVFIELD (e, f, vector)
|
||||
#define SVinteger(e,f) SVFIELD (e, f, integer)
|
||||
#if TYPECHECK_PROGS
|
||||
#define SVdouble(e,f) E_DOUBLE (e, PR_AccessField (&sv_pr_state, #f, ev_##t, __FILE__, __LINE__))
|
||||
#else
|
||||
#define SVdouble(e,f) E_DOUBLE (e, sv_fields.f)
|
||||
#endif
|
||||
|
||||
typedef struct edict_leaf_s {
|
||||
struct edict_leaf_s *next;
|
||||
|
|
|
@ -371,6 +371,9 @@ set_address (sv_def_t *def, void *address)
|
|||
case ev_quat:
|
||||
*(float **)def->field = (float *) address;
|
||||
break;
|
||||
case ev_double:
|
||||
*(double **)def->field = (double *) address;
|
||||
break;
|
||||
case ev_string:
|
||||
case ev_entity:
|
||||
case ev_field:
|
||||
|
|
|
@ -166,7 +166,7 @@ int HUDHandleClass;
|
|||
if (looping)
|
||||
currentFrame = 0;
|
||||
else {
|
||||
nextFrameTime = 0.0;
|
||||
nextFrameTime = 0.0f;
|
||||
currentFrame = 0;
|
||||
return;
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ int HUDHandleClass;
|
|||
|
||||
- (void) stop
|
||||
{
|
||||
nextFrameTime = 0.0;
|
||||
nextFrameTime = 0.0f;
|
||||
currentFrame = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
- (id) init
|
||||
{
|
||||
[super init];
|
||||
damage = (deathmatch > 3) ? 75.0 : 20.0;
|
||||
damage = (deathmatch > 3) ? 75.0f : 20.0f;
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
|||
source = s.origin + '0 0 16';
|
||||
|
||||
traceline (source, source + v_forward * 64, NO, s);
|
||||
if (trace_fraction == 1.0)
|
||||
if (trace_fraction == 1.0f)
|
||||
return;
|
||||
|
||||
org = trace_endpos - v_forward * 4;
|
||||
|
|
|
@ -60,17 +60,20 @@
|
|||
/**
|
||||
Returns \a f, rounded down to the next lower integer
|
||||
*/
|
||||
@extern float floor (float f);
|
||||
@extern @overload float floor (float f);
|
||||
@extern @overload double floor (double f);
|
||||
|
||||
/**
|
||||
Returns \a f, rounded up to the next highest integer
|
||||
*/
|
||||
@extern float ceil (float f);
|
||||
@extern @overload float ceil (float f);
|
||||
@extern @overload double ceil (double f);
|
||||
|
||||
/**
|
||||
Returns the absolute value of \a f
|
||||
*/
|
||||
@extern float fabs (float f);
|
||||
@extern @overload float fabs (float f);
|
||||
@extern @overload double fabs (double f);
|
||||
//\}
|
||||
|
||||
///\name Exponentials and Logarithms
|
||||
|
@ -78,32 +81,38 @@
|
|||
/**
|
||||
Returns the natural log of \a x.
|
||||
*/
|
||||
@extern float log (float x);
|
||||
@extern @overload float log (float x);
|
||||
@extern @overload double log (double x);
|
||||
|
||||
/**
|
||||
Returns the base-2 log of \a x.
|
||||
*/
|
||||
@extern float log2 (float x);
|
||||
@extern @overload float log2 (float x);
|
||||
@extern @overload double log2 (double x);
|
||||
|
||||
/**
|
||||
Returns the base-10 log of \a x.
|
||||
*/
|
||||
@extern float log10 (float x);
|
||||
@extern @overload float log10 (float x);
|
||||
@extern @overload double log10 (double x);
|
||||
|
||||
/**
|
||||
Returns \a x to the \a y power
|
||||
*/
|
||||
@extern float pow (float x, float y);
|
||||
@extern @overload float pow (float x, float y);
|
||||
@extern @overload double pow (double x, double y);
|
||||
|
||||
/**
|
||||
Returns the square root of \a x
|
||||
*/
|
||||
@extern float sqrt (float x);
|
||||
@extern @overload float sqrt (float x);
|
||||
@extern @overload double sqrt (double x);
|
||||
|
||||
/**
|
||||
Returns the cube root of \a x
|
||||
*/
|
||||
@extern float cbrt (float x);
|
||||
@extern @overload float cbrt (float x);
|
||||
@extern @overload double cbrt (double x);
|
||||
//\}
|
||||
|
||||
///\name Trigonometric functions
|
||||
|
@ -112,40 +121,52 @@
|
|||
/**
|
||||
Returns the sine of \a x.
|
||||
*/
|
||||
@extern float sin (float x);
|
||||
@extern @overload float sin (float x);
|
||||
@extern @overload double sin (double x);
|
||||
|
||||
/**
|
||||
Returns the cosine of \a x.
|
||||
*/
|
||||
@extern float cos (float x);
|
||||
@extern @overload float cos (float x);
|
||||
@extern @overload double cos (double x);
|
||||
|
||||
/**
|
||||
Returns the tangent of \a x.
|
||||
*/
|
||||
@extern float tan (float x);
|
||||
@extern @overload float tan (float x);
|
||||
@extern @overload double tan (double x);
|
||||
|
||||
/**
|
||||
Returns the arcsine of \a x.
|
||||
*/
|
||||
@extern float asin (float x);
|
||||
@extern @overload float asin (float x);
|
||||
@extern @overload double asin (double x);
|
||||
|
||||
/**
|
||||
Returns the arccosine of \a x.
|
||||
*/
|
||||
@extern float acos (float x);
|
||||
@extern @overload float acos (float x);
|
||||
@extern @overload double acos (double x);
|
||||
|
||||
/**
|
||||
Returns the arctangent of \a x.
|
||||
*/
|
||||
@extern float atan (float x);
|
||||
@extern float atan2 (float y, float x);
|
||||
@extern @overload float atan (float x);
|
||||
@extern @overload double atan (double x);
|
||||
|
||||
/**
|
||||
Returns the arctangent of \a y / \a x preserving the quadrant.
|
||||
*/
|
||||
@extern @overload float atan2 (float y, float x);
|
||||
@extern @overload double atan2 (double y, double x);
|
||||
|
||||
/**
|
||||
Returns the length of the hypotenuse of a right triangle with sides \a x
|
||||
and \a y. That is, this function returns
|
||||
<code>sqrt (\a x*\a x + \a y*\a y)</code>.
|
||||
*/
|
||||
@extern float hypot (float x, float y);
|
||||
@extern @overload float hypot (float x, float y);
|
||||
@extern @overload double hypot (double x, double y);
|
||||
//\}
|
||||
|
||||
///\name Hyperbolic functions
|
||||
|
@ -153,32 +174,38 @@
|
|||
/**
|
||||
Returns the hyperbolic sine of \a x
|
||||
*/
|
||||
@extern float sinh (float x);
|
||||
@extern @overload float sinh (float x);
|
||||
@extern @overload double sinh (double x);
|
||||
|
||||
/**
|
||||
Returns the hyperbolic cosine of \a x
|
||||
*/
|
||||
@extern float cosh (float x);
|
||||
@extern @overload float cosh (float x);
|
||||
@extern @overload double cosh (double x);
|
||||
|
||||
/**
|
||||
Returns the hyperbolic tangent of \a x
|
||||
*/
|
||||
@extern float tanh (float x);
|
||||
@extern @overload float tanh (float x);
|
||||
@extern @overload double tanh (double x);
|
||||
|
||||
/**
|
||||
Returns the area hyperbolic sine of \a x
|
||||
*/
|
||||
@extern float asinh (float x);
|
||||
@extern @overload float asinh (float x);
|
||||
@extern @overload double asinh (double x);
|
||||
|
||||
/**
|
||||
Returns the area hyperbolic cosine of \a x
|
||||
*/
|
||||
@extern float acosh (float x);
|
||||
@extern @overload float acosh (float x);
|
||||
@extern @overload double acosh (double x);
|
||||
|
||||
/**
|
||||
Returns the area hyperbolic tangent of \a x
|
||||
*/
|
||||
@extern float atanh (float x);
|
||||
@extern @overload float atanh (float x);
|
||||
@extern @overload double atanh (double x);
|
||||
//\}
|
||||
|
||||
///\name Vector Functions
|
||||
|
|
|
@ -34,3 +34,27 @@ float (float x) atanh = #0;
|
|||
float (float x) sqrt = #0;
|
||||
float (float x) cbrt = #0;
|
||||
float (float x, float y) hypot = #0;
|
||||
|
||||
double (double v) floor = #0;
|
||||
double (double v) ceil = #0;
|
||||
double (double f) fabs = #0;
|
||||
double (double x) sin = #0;
|
||||
double (double x) cos = #0;
|
||||
double (double x) tan = #0;
|
||||
double (double x) asin = #0;
|
||||
double (double x) acos = #0;
|
||||
double (double x) atan = #0;
|
||||
double (double y, double x) atan2 = #0;
|
||||
double (double x) log = #0;
|
||||
double (double x) log2 = #0;
|
||||
double (double x) log10 = #0;
|
||||
double (double x, double y) pow = #0;
|
||||
double (double x) sinh = #0;
|
||||
double (double x) cosh = #0;
|
||||
double (double x) tanh = #0;
|
||||
double (double x) asinh = #0;
|
||||
double (double x) acosh = #0;
|
||||
double (double x) atanh = #0;
|
||||
double (double x) sqrt = #0;
|
||||
double (double x) cbrt = #0;
|
||||
double (double x, double y) hypot = #0;
|
||||
|
|
|
@ -24,14 +24,14 @@
|
|||
bl_info = {
|
||||
"name": "Quake MDL format",
|
||||
"author": "Bill Currie",
|
||||
"blender": (2, 6, 3),
|
||||
"blender": (2, 80, 0),
|
||||
"api": 35622,
|
||||
"location": "File > Import-Export",
|
||||
"description": "Import-Export Quake MDL (version 6) files. (.mdl)",
|
||||
"warning": "not even alpha",
|
||||
"warning": "still work in progress",
|
||||
"wiki_url": "",
|
||||
"tracker_url": "",
|
||||
# "support": 'OFFICIAL',
|
||||
# "support": 'OFFICIAL',
|
||||
"category": "Import-Export"}
|
||||
|
||||
# To support reload properly, try to access a package var, if it's there,
|
||||
|
@ -66,28 +66,33 @@ EFFECTS=(
|
|||
)
|
||||
|
||||
class QFMDLSettings(bpy.types.PropertyGroup):
|
||||
eyeposition = FloatVectorProperty(
|
||||
eyeposition : FloatVectorProperty(
|
||||
name="Eye Position",
|
||||
description="View possion relative to object origin")
|
||||
synctype = EnumProperty(
|
||||
synctype : EnumProperty(
|
||||
items=SYNCTYPE,
|
||||
name="Sync Type",
|
||||
description="Add random time offset for automatic animations")
|
||||
rotate = BoolProperty(
|
||||
rotate : BoolProperty(
|
||||
name="Rotate",
|
||||
description="Rotate automatically (for pickup items)")
|
||||
effects = EnumProperty(
|
||||
effects : EnumProperty(
|
||||
items=EFFECTS,
|
||||
name="Effects",
|
||||
description="Particle trail effects")
|
||||
#doesn't work :(
|
||||
#script = PointerProperty(
|
||||
# type=bpy.types.Object,
|
||||
# name="Script",
|
||||
# description="Script for animating frames and skins")
|
||||
script = StringProperty(
|
||||
|
||||
script : PointerProperty(
|
||||
type=bpy.types.Text,
|
||||
name="Script",
|
||||
description="Script for animating frames and skins")
|
||||
|
||||
xform : BoolProperty(
|
||||
name="Auto transform",
|
||||
description="Auto-apply location/rotation/scale when exporting",
|
||||
default=True)
|
||||
md16 : BoolProperty(
|
||||
name="16-bit",
|
||||
description="16 bit vertex coordinates: QuakeForge only")
|
||||
xform = BoolProperty(
|
||||
name="Auto transform",
|
||||
description="Auto-apply location/rotation/scale when exporting",
|
||||
|
@ -102,7 +107,7 @@ class ImportMDL6(bpy.types.Operator, ImportHelper):
|
|||
bl_label = "Import MDL"
|
||||
|
||||
filename_ext = ".mdl"
|
||||
filter_glob = StringProperty(default="*.mdl", options={'HIDDEN'})
|
||||
filter_glob : StringProperty(default="*.mdl", options={'HIDDEN'})
|
||||
|
||||
def execute(self, context):
|
||||
from . import import_mdl
|
||||
|
@ -116,7 +121,7 @@ class ExportMDL6(bpy.types.Operator, ExportHelper):
|
|||
bl_label = "Export MDL"
|
||||
|
||||
filename_ext = ".mdl"
|
||||
filter_glob = StringProperty(default="*.mdl", options={'HIDDEN'})
|
||||
filter_glob : StringProperty(default="*.mdl", options={'HIDDEN'})
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
@ -129,10 +134,11 @@ class ExportMDL6(bpy.types.Operator, ExportHelper):
|
|||
return export_mdl.export_mdl(self, context, **keywords)
|
||||
|
||||
class OBJECT_PT_MDLPanel(bpy.types.Panel):
|
||||
bl_label = "MDL Properties"
|
||||
bl_space_type = 'PROPERTIES'
|
||||
bl_region_type = 'WINDOW'
|
||||
bl_context = 'object'
|
||||
bl_label = 'QF MDL'
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
@ -157,21 +163,28 @@ def menu_func_import(self, context):
|
|||
def menu_func_export(self, context):
|
||||
self.layout.operator(ExportMDL6.bl_idname, text="Quake MDL (.mdl)")
|
||||
|
||||
classes = (
|
||||
QFMDLSettings,
|
||||
OBJECT_PT_MDLPanel,
|
||||
ImportMDL6,
|
||||
ExportMDL6
|
||||
)
|
||||
|
||||
def register():
|
||||
bpy.utils.register_module(__name__)
|
||||
for cls in classes:
|
||||
bpy.utils.register_class(cls)
|
||||
|
||||
bpy.types.Object.qfmdl = PointerProperty(type=QFMDLSettings)
|
||||
|
||||
bpy.types.INFO_MT_file_import.append(menu_func_import)
|
||||
bpy.types.INFO_MT_file_export.append(menu_func_export)
|
||||
|
||||
bpy.types.TOPBAR_MT_file_import.append(menu_func_import)
|
||||
bpy.types.TOPBAR_MT_file_export.append(menu_func_export)
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_module(__name__)
|
||||
for cls in classes:
|
||||
bpy.utils.unregister_class(cls)
|
||||
|
||||
bpy.types.INFO_MT_file_import.remove(menu_func_import)
|
||||
bpy.types.INFO_MT_file_export.remove(menu_func_export)
|
||||
bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)
|
||||
bpy.types.TOPBAR_MT_file_export.remove(menu_func_export)
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
||||
|
|
|
@ -27,6 +27,7 @@ from .qfplist import pldata, PListError
|
|||
from .quakepal import palette
|
||||
from .quakenorm import map_normal
|
||||
from .mdl import MDL
|
||||
from .__init__ import SYNCTYPE, EFFECTS
|
||||
|
||||
def check_faces(mesh):
|
||||
#Check that all faces are tris because mdl does not support anything else.
|
||||
|
@ -35,17 +36,17 @@ def check_faces(mesh):
|
|||
faces_ok = True
|
||||
save_select = []
|
||||
for f in mesh.polygons:
|
||||
save_select.append(f.select)
|
||||
f.select = False
|
||||
save_select.append(f.select_get())
|
||||
f.select_set('DESELECT')
|
||||
if len(f.vertices) > 3:
|
||||
f.select = True
|
||||
f.select_set('SELECT')
|
||||
faces_ok = False
|
||||
if not faces_ok:
|
||||
mesh.update()
|
||||
return False
|
||||
#reset selection to what it was before the check.
|
||||
for f, s in map(lambda x, y: (x, y), mesh.polygons, save_select):
|
||||
f.select = s
|
||||
f.select_set('SELECT' if s else 'DESELECT')
|
||||
mesh.update()
|
||||
return True
|
||||
|
||||
|
@ -85,7 +86,7 @@ def null_skin(size):
|
|||
return skin
|
||||
|
||||
def active_uv(mesh):
|
||||
for uvt in mesh.uv_textures:
|
||||
for uvt in mesh.uv_layers:
|
||||
if uvt.active:
|
||||
return uvt
|
||||
return None
|
||||
|
@ -94,6 +95,40 @@ def make_skin(operator, mdl, mesh):
|
|||
uvt = active_uv(mesh)
|
||||
mdl.skinwidth, mdl.skinheight = (4, 4)
|
||||
skin = null_skin((mdl.skinwidth, mdl.skinheight))
|
||||
|
||||
materials = mesh.materials
|
||||
|
||||
if len(materials) > 0:
|
||||
for mat in materials:
|
||||
allTextureNodes = list(filter(lambda node: node.type == "TEX_IMAGE", mat.node_tree.nodes))
|
||||
if len(allTextureNodes) > 1: #=== skingroup
|
||||
skingroup = MDL.Skin()
|
||||
skingroup.type = 1
|
||||
skingroup.skins = []
|
||||
skingroup.times = []
|
||||
sortedNodes = list(allTextureNodes)
|
||||
sortedNodes.sort(key=lambda x: x.location[1], reverse=True)
|
||||
for node in sortedNodes:
|
||||
if node.type == "TEX_IMAGE":
|
||||
image = node.image
|
||||
mdl.skinwidth, mdl.skinheight = image.size
|
||||
skin = convert_image(image)
|
||||
skingroup.skins.append(skin)
|
||||
skingroup.times.append(0.1) # hardcoded at the moment
|
||||
mdl.skins.append(skingroup)
|
||||
elif len(allTextureNodes) == 1: #=== single skin
|
||||
for node in allTextureNodes:
|
||||
if node.type == "TEX_IMAGE":
|
||||
image = node.image
|
||||
mdl.skinwidth, mdl.skinheight = image.size
|
||||
skin = convert_image(image)
|
||||
mdl.skins.append(skin)
|
||||
else:
|
||||
mdl.skins.append(skin) # add empty skin - no texture nodes
|
||||
else:
|
||||
mdl.skins.append(skin) # add empty skin - no materials
|
||||
|
||||
'''
|
||||
if (uvt and uvt.data and uvt.data[0].image):
|
||||
image = uvt.data[0].image
|
||||
if (uvt.data[0].image.size[0] and uvt.data[0].image.size[1]):
|
||||
|
@ -102,7 +137,9 @@ def make_skin(operator, mdl, mesh):
|
|||
else:
|
||||
operator.report({'WARNING'},
|
||||
"Texture '%s' invalid (missing?)." % image.name)
|
||||
|
||||
mdl.skins.append(skin)
|
||||
'''
|
||||
|
||||
def build_tris(mesh):
|
||||
# mdl files have a 1:1 relationship between stverts and 3d verts.
|
||||
|
@ -182,7 +219,7 @@ def calc_average_area(mdl):
|
|||
a = Vector(verts[0].r) - Vector(verts[1].r)
|
||||
b = Vector(verts[2].r) - Vector(verts[1].r)
|
||||
c = a.cross(b)
|
||||
totalarea += (c * c) ** 0.5 / 2.0
|
||||
totalarea += (c @ c) ** 0.5 / 2.0
|
||||
return totalarea / len(mdl.tris)
|
||||
|
||||
def get_properties(operator, mdl, obj):
|
||||
|
@ -192,16 +229,11 @@ def get_properties(operator, mdl, obj):
|
|||
| MDL.EFFECTS[obj.qfmdl.effects])
|
||||
if obj.qfmdl.md16:
|
||||
mdl.ident = "MD16"
|
||||
|
||||
script = obj.qfmdl.script
|
||||
mdl.script = None
|
||||
if script:
|
||||
try:
|
||||
script = bpy.data.texts[script].as_string()
|
||||
except KeyError:
|
||||
operator.report({'ERROR'},
|
||||
"Script '%s' not found." % script)
|
||||
return False
|
||||
pl = pldata(script)
|
||||
pl = pldata(script.as_string())
|
||||
try:
|
||||
mdl.script = pl.parse()
|
||||
except PListError as err:
|
||||
|
@ -268,17 +300,29 @@ def process_frame(mdl, scene, frame, vertmap, ingroup = False,
|
|||
return fr
|
||||
mdl.frames += fr.frames[:-1]
|
||||
return fr.frames[-1]
|
||||
scene.frame_set(int(frameno), frameno - int(frameno))
|
||||
mesh = mdl.obj.to_mesh(scene, True, 'PREVIEW') #wysiwyg?
|
||||
scene.frame_set(int(frameno), subframe = frameno - int(frameno))
|
||||
depsgraph = bpy.context.evaluated_depsgraph_get()
|
||||
mesh = mdl.obj.evaluated_get(depsgraph).to_mesh() #wysiwyg?
|
||||
if mdl.obj.qfmdl.xform:
|
||||
mesh.transform(mdl.obj.matrix_world)
|
||||
fr = make_frame(mesh, vertmap)
|
||||
fr.name = name
|
||||
return fr
|
||||
|
||||
def get_frame_name(mesh, idx):
|
||||
name = "frame" + str(idx)
|
||||
if mesh.shape_keys:
|
||||
shape_keys_amount = len(mesh.shape_keys.key_blocks)
|
||||
if shape_keys_amount > idx:
|
||||
name = mesh.shape_keys.key_blocks[idx].name
|
||||
return name
|
||||
|
||||
def export_mdl(operator, context, filepath):
|
||||
obj = context.active_object
|
||||
mesh = obj.to_mesh(context.scene, True, 'PREVIEW') #wysiwyg?
|
||||
obj.update_from_editmode()
|
||||
depsgraph = context.evaluated_depsgraph_get()
|
||||
ob_eval = obj.evaluated_get(depsgraph)
|
||||
mesh = ob_eval.to_mesh()
|
||||
#if not check_faces(mesh):
|
||||
# operator.report({'ERROR'},
|
||||
# "Mesh has faces with more than 3 vertices.")
|
||||
|
@ -287,6 +331,7 @@ def export_mdl(operator, context, filepath):
|
|||
mdl.obj = obj
|
||||
if not get_properties(operator, mdl, obj):
|
||||
return {'CANCELLED'}
|
||||
|
||||
mdl.tris, mdl.stverts, vertmap = build_tris(mesh)
|
||||
if mdl.script:
|
||||
if 'skins' in mdl.script:
|
||||
|
@ -299,13 +344,19 @@ def export_mdl(operator, context, filepath):
|
|||
if not mdl.skins:
|
||||
make_skin(operator, mdl, mesh)
|
||||
if not mdl.frames:
|
||||
curframe = context.scene.frame_current
|
||||
for fno in range(1, curframe + 1):
|
||||
scene = context.scene
|
||||
for fno in range(scene.frame_start, scene.frame_end + 1):
|
||||
context.scene.frame_set(fno)
|
||||
mesh = obj.to_mesh(context.scene, True, 'PREVIEW') #wysiwyg?
|
||||
if mdl.obj.qfmdl.xform:
|
||||
obj.update_from_editmode()
|
||||
depsgraph = context.evaluated_depsgraph_get()
|
||||
ob_eval = obj.evaluated_get(depsgraph)
|
||||
mesh = ob_eval.to_mesh()
|
||||
if obj.qfmdl.xform:
|
||||
mesh.transform(mdl.obj.matrix_world)
|
||||
mdl.frames.append(make_frame(mesh, vertmap))
|
||||
frame = make_frame(mesh, vertmap)
|
||||
frame.name = get_frame_name(obj.data, fno)
|
||||
mdl.frames.append(frame)
|
||||
|
||||
convert_stverts(mdl, mdl.stverts)
|
||||
mdl.size = calc_average_area(mdl)
|
||||
scale_verts(mdl)
|
||||
|
|
|
@ -39,7 +39,7 @@ def make_verts(mdl, framenum, subframenum=0):
|
|||
( 0, 0,s.z,o.z),
|
||||
( 0, 0, 0, 1)))
|
||||
for v in frame.verts:
|
||||
verts.append(m * Vector(v.r))
|
||||
verts.append(m @ Vector(v.r))
|
||||
return verts
|
||||
|
||||
def make_faces(mdl):
|
||||
|
@ -87,7 +87,7 @@ def load_skins(mdl):
|
|||
p[l + 2] = c[2] / 255.0
|
||||
p[l + 3] = 1.0
|
||||
img.pixels[:] = p[:]
|
||||
img.pack(True)
|
||||
img.pack()
|
||||
img.use_fake_user = True
|
||||
|
||||
mdl.images=[]
|
||||
|
@ -98,30 +98,80 @@ def load_skins(mdl):
|
|||
else:
|
||||
load_skin(skin, "%s_%d" % (mdl.name, i))
|
||||
|
||||
def setup_main_material(mdl):
|
||||
mat = bpy.data.materials.new(mdl.name)
|
||||
mat.blend_method = 'OPAQUE'
|
||||
mat.diffuse_color = (1, 1, 1, 1)
|
||||
mat.metallic = 1
|
||||
mat.roughness = 1
|
||||
mat.specular_intensity = 0
|
||||
mat.use_nodes = True
|
||||
return mat
|
||||
|
||||
def setup_skins(mdl, uvs):
|
||||
load_skins(mdl)
|
||||
img = mdl.images[0] # use the first skin for now
|
||||
uvlay = mdl.mesh.uv_textures.new(mdl.name)
|
||||
uvloop = mdl.mesh.uv_layers[0]
|
||||
for i, texpoly in enumerate(uvlay.data):
|
||||
# img = mdl.images[0] # use the first skin for now
|
||||
# uvlay = mdl.mesh.uv_textures.new(mdl.name)
|
||||
# uvloop = mdl.mesh.uv_layers[0]
|
||||
# for i, texpoly in enumerate(uvlay.data):
|
||||
uvloop = mdl.mesh.uv_layers.new(name = mdl.name)
|
||||
for i in range(len(mdl.mesh.polygons)):
|
||||
poly = mdl.mesh.polygons[i]
|
||||
mdl_uv = uvs[i]
|
||||
texpoly.image = img
|
||||
# texpoly.image = img # TODO: commented out by jazz
|
||||
for j,k in enumerate(poly.loop_indices):
|
||||
uvloop.data[k].uv = mdl_uv[j]
|
||||
mat = bpy.data.materials.new(mdl.name)
|
||||
mat.diffuse_color = (1,1,1)
|
||||
mat.use_raytrace = False
|
||||
tex = bpy.data.textures.new(mdl.name, 'IMAGE')
|
||||
tex.extension = 'CLIP'
|
||||
tex.use_preview_alpha = True
|
||||
tex.image = img
|
||||
mat.texture_slots.add()
|
||||
ts = mat.texture_slots[0]
|
||||
ts.texture = tex
|
||||
ts.use_map_alpha = True
|
||||
ts.texture_coords = 'UV'
|
||||
mdl.mesh.materials.append(mat)
|
||||
|
||||
#Load all skins
|
||||
img_counter = 0
|
||||
for i, skin in enumerate(mdl.skins):
|
||||
if skin.type:
|
||||
mat = setup_main_material(mdl)
|
||||
emissionNode = mat.node_tree.nodes.new("ShaderNodeEmission")
|
||||
shaderOut = mat.node_tree.nodes["Material Output"]
|
||||
mat.node_tree.nodes.remove(mat.node_tree.nodes["Principled BSDF"])
|
||||
|
||||
emissionNode.location = (0, 0)
|
||||
shaderOut.location = (200, 0)
|
||||
|
||||
yPos = 0
|
||||
|
||||
for j, subskin in enumerate(skin.skins):
|
||||
tex_node = mat.node_tree.nodes.new("ShaderNodeTexImage")
|
||||
tex_node.image = mdl.images[img_counter]
|
||||
img_counter += 1
|
||||
tex_node.interpolation = "Closest"
|
||||
|
||||
tex_node.location = (-300, yPos)
|
||||
yPos -= 280
|
||||
|
||||
if j == 0:
|
||||
# connect only first texture (we'll need something smarter in the future)
|
||||
mat.node_tree.links.new(tex_node.outputs[0], emissionNode.inputs[0])
|
||||
|
||||
mat.node_tree.links.new(emissionNode.outputs[0], shaderOut.inputs[0])
|
||||
mdl.mesh.materials.append(mat)
|
||||
|
||||
else:
|
||||
mat = setup_main_material(mdl)
|
||||
|
||||
# TODO: turn transform to True and position it properly in editor
|
||||
emissionNode = mat.node_tree.nodes.new("ShaderNodeEmission")
|
||||
shaderOut = mat.node_tree.nodes["Material Output"]
|
||||
mat.node_tree.nodes.remove(mat.node_tree.nodes["Principled BSDF"])
|
||||
|
||||
tex_node = mat.node_tree.nodes.new("ShaderNodeTexImage")
|
||||
tex_node.image = mdl.images[img_counter]
|
||||
img_counter += 1
|
||||
tex_node.interpolation = "Closest"
|
||||
|
||||
emissionNode.location = (0, 0)
|
||||
shaderOut.location = (200, 0)
|
||||
tex_node.location = (-300, 0)
|
||||
|
||||
mat.node_tree.links.new(tex_node.outputs[0], emissionNode.inputs[0])
|
||||
mat.node_tree.links.new(emissionNode.outputs[0], shaderOut.inputs[0])
|
||||
mdl.mesh.materials.append(mat)
|
||||
|
||||
def make_shape_key(mdl, framenum, subframenum=0):
|
||||
frame = mdl.frames[framenum]
|
||||
|
@ -133,7 +183,7 @@ def make_shape_key(mdl, framenum, subframenum=0):
|
|||
name = frame.name
|
||||
else:
|
||||
frame.name = name
|
||||
frame.key = mdl.obj.shape_key_add(name)
|
||||
frame.key = mdl.obj.shape_key_add(name=name)
|
||||
frame.key.value = 0.0
|
||||
mdl.keys.append(frame.key)
|
||||
s = Vector(mdl.scale)
|
||||
|
@ -143,20 +193,25 @@ def make_shape_key(mdl, framenum, subframenum=0):
|
|||
( 0, 0,s.z,o.z),
|
||||
( 0, 0, 0, 1)))
|
||||
for i, v in enumerate(frame.verts):
|
||||
frame.key.data[i].co = m * Vector(v.r)
|
||||
frame.key.data[i].co = m @ Vector(v.r)
|
||||
|
||||
def build_shape_keys(mdl):
|
||||
mdl.keys = []
|
||||
mdl.obj.shape_key_add("Basis")
|
||||
mdl.obj.shape_key_add(name="Basis",from_mix=False)
|
||||
mdl.mesh.shape_keys.name = mdl.name
|
||||
mdl.obj.active_shape_key_index = 0
|
||||
bpy.context.scene.frame_end = 0
|
||||
for i, frame in enumerate(mdl.frames):
|
||||
frame = mdl.frames[i]
|
||||
if frame.type:
|
||||
for j in range(len(frame.frames)):
|
||||
make_shape_key(mdl, i, j)
|
||||
bpy.context.scene.frame_end += 1
|
||||
else:
|
||||
make_shape_key(mdl, i)
|
||||
bpy.context.scene.frame_end += 1
|
||||
|
||||
bpy.context.scene.frame_start = 1
|
||||
|
||||
def set_keys(act, data):
|
||||
for d in data:
|
||||
|
@ -241,8 +296,8 @@ def write_text(mdl):
|
|||
/* This script represents the animation data within the model file. It
|
||||
is generated automatically on import, and is optional when exporting.
|
||||
If no script is used when exporting, frames will be exported one per
|
||||
blender frame from frame 1 to the current frame (inclusive), and only
|
||||
one skin will be exported.
|
||||
blender frame from the scene start frame to the scene end frame
|
||||
(inclusive), and one skin per teximage node will be exported.
|
||||
|
||||
The fundamental format of the script is documented at
|
||||
http://quakeforge.net/doxygen/property-list.html
|
||||
|
@ -335,14 +390,14 @@ def set_properties(mdl):
|
|||
mdl.obj.qfmdl.synctype = 'ST_SYNC'
|
||||
mdl.obj.qfmdl.rotate = (mdl.flags & MDL.EF_ROTATE) and True or False
|
||||
mdl.obj.qfmdl.effects = parse_flags(mdl.flags)
|
||||
mdl.obj.qfmdl.script = mdl.text.name #FIXME really want the text object
|
||||
mdl.obj.qfmdl.script = mdl.text
|
||||
mdl.obj.qfmdl.md16 = (mdl.ident == "MD16")
|
||||
|
||||
def import_mdl(operator, context, filepath):
|
||||
bpy.context.user_preferences.edit.use_global_undo = False
|
||||
def import_mdl(operator, context, filepath, **opts):
|
||||
bpy.context.preferences.edit.use_global_undo = False
|
||||
|
||||
for obj in bpy.context.scene.objects:
|
||||
obj.select = False
|
||||
for obj in bpy.context.scene.collection.objects:
|
||||
obj.select_set(False)
|
||||
|
||||
mdl = MDL()
|
||||
if not mdl.read(filepath):
|
||||
|
@ -354,10 +409,14 @@ def import_mdl(operator, context, filepath):
|
|||
mdl.mesh = bpy.data.meshes.new(mdl.name)
|
||||
mdl.mesh.from_pydata(verts, [], faces)
|
||||
mdl.obj = bpy.data.objects.new(mdl.name, mdl.mesh)
|
||||
bpy.context.scene.objects.link(mdl.obj)
|
||||
bpy.context.scene.objects.active = mdl.obj
|
||||
mdl.obj.select = True
|
||||
|
||||
bpy.context.scene.collection.objects.link(mdl.obj)
|
||||
mdl.obj.select_set(True)
|
||||
bpy.context.view_layer.objects.active = mdl.obj
|
||||
setup_skins(mdl, uvs)
|
||||
|
||||
bpy.context.scene.frame_start = 1
|
||||
bpy.context.scene.frame_end = 1
|
||||
if len(mdl.frames) > 1 or mdl.frames[0].type:
|
||||
build_shape_keys(mdl)
|
||||
merge_frames(mdl)
|
||||
|
@ -367,5 +426,5 @@ def import_mdl(operator, context, filepath):
|
|||
|
||||
mdl.mesh.update()
|
||||
|
||||
bpy.context.user_preferences.edit.use_global_undo = True
|
||||
bpy.context.preferences.edit.use_global_undo = True
|
||||
return {'FINISHED'}
|
||||
|
|
|
@ -109,6 +109,27 @@ defspace_t *defspace_new (ds_type_t type);
|
|||
*/
|
||||
int defspace_alloc_loc (defspace_t *space, int size);
|
||||
|
||||
/** Allocate space from the defspace's backing memory.
|
||||
|
||||
If the memory is fragmented, then the first available location at least
|
||||
as large as \a size plus padding for alignment is returned. This means
|
||||
that freeing a location then allocating the same amount of space may
|
||||
return a different location.
|
||||
|
||||
If memory cannot be allocated (there is no free space in the currently
|
||||
available memory and defspace_t::grow is null), then an internal error
|
||||
will be generated.
|
||||
|
||||
\param space The space from which to allocate data.
|
||||
\param size The amount of pr_type_t words to allocated. int and float
|
||||
need 1 word, vector 3 words, and quaternion 4.
|
||||
\param alignment The alignment of the allocated space.
|
||||
\return The offset of the first word of the freshly allocated
|
||||
space. May be 0 if the allocated space is at the beginning
|
||||
of the defspace.
|
||||
*/
|
||||
int defspace_alloc_aligned_loc (defspace_t *space, int size, int alignment);
|
||||
|
||||
/** Free a block of contiguous words, returning them to the defspace.
|
||||
|
||||
The block to be freed is specified by \a ofs indicating the offset of the
|
||||
|
|
|
@ -174,6 +174,7 @@ typedef struct ex_value_s {
|
|||
etype_t lltype;
|
||||
union {
|
||||
const char *string_val; ///< string constant
|
||||
double double_val; ///< double constant
|
||||
float float_val; ///< float constant
|
||||
float vector_val[3]; ///< vector constant
|
||||
int entity_val; ///< entity constant
|
||||
|
@ -397,6 +398,15 @@ expr_t *new_name_expr (const char *name);
|
|||
expr_t *new_string_expr (const char *string_val);
|
||||
const char *expr_string (expr_t *e) __attribute__((pure));
|
||||
|
||||
/** Create a new double constant expression node.
|
||||
|
||||
\param double_val The double constant being represented.
|
||||
\return The new double constant expression node
|
||||
(expr_t::e::double_val).
|
||||
*/
|
||||
expr_t *new_double_expr (double double_val);
|
||||
double expr_double (expr_t *e) __attribute__((pure));
|
||||
|
||||
/** Create a new float constant expression node.
|
||||
|
||||
\param float_val The float constant being represented.
|
||||
|
|
|
@ -305,6 +305,19 @@ enum {
|
|||
*/
|
||||
#define QFO_var(q, s, t, o) ((q)->spaces[s].d.data[o].t##_var)
|
||||
|
||||
/** Access a double variable in the object file. Can be assigned to.
|
||||
|
||||
\par QC type:
|
||||
\c double
|
||||
\param q pointer to ::qfo_t struct
|
||||
\param s space index
|
||||
\param o offset into object file data space
|
||||
\return double lvalue
|
||||
|
||||
\hideinitializer
|
||||
*/
|
||||
#define QFO_DOUBLE(q, s, o) (*(double *) ((q)->spaces[s].d.data + o))
|
||||
|
||||
/** Access a float variable in the object file. Can be assigned to.
|
||||
|
||||
\par QC type:
|
||||
|
@ -484,6 +497,8 @@ qfo_t *qfo_new (void);
|
|||
*/
|
||||
void qfo_delete (qfo_t *qfo);
|
||||
|
||||
__attribute__((const)) int qfo_log2 (unsigned x);
|
||||
|
||||
///@}
|
||||
|
||||
#endif//__obj_file_h
|
||||
|
|
|
@ -70,6 +70,11 @@ typedef struct {
|
|||
qboolean silent; // don't even bother (overrides promote)
|
||||
} notice_options_t;
|
||||
|
||||
typedef struct {
|
||||
qboolean promote; // Promote bugs to internal errors
|
||||
qboolean silent; // don't even bother (overrides promote)
|
||||
} bug_options_t;
|
||||
|
||||
typedef struct {
|
||||
qboolean initial;
|
||||
qboolean thread;
|
||||
|
@ -88,6 +93,7 @@ typedef struct {
|
|||
code_options_t code; // Code generation options
|
||||
warn_options_t warnings; // Warning options
|
||||
notice_options_t notices; // Notice options
|
||||
bug_options_t bug; // Bug options
|
||||
blockdot_options_t block_dot; // Statement block flow diagrams
|
||||
|
||||
int verbosity; // 0=silent, goes up to 2 currently
|
||||
|
|
|
@ -35,7 +35,8 @@
|
|||
*/
|
||||
///@{
|
||||
|
||||
void pragma (const char *id);
|
||||
void pragma_process (void);
|
||||
void pragma_add_arg (const char *id);
|
||||
|
||||
///@}
|
||||
|
||||
|
|
|
@ -92,6 +92,7 @@ extern pr_info_t pr;
|
|||
|
||||
#define GETSTR(s) (pr.strings->strings + (s))
|
||||
#define D_var(t, d) ((d)->space->data[(d)->offset].t##_var)
|
||||
#define D_DOUBLE(d) (*(double *) ((d)->space->data + (d)->offset))
|
||||
#define D_FLOAT(d) D_var (float, d)
|
||||
#define D_INT(d) D_var (integer, d)
|
||||
#define D_VECTOR(d) D_var (vector, d)
|
||||
|
|
|
@ -116,6 +116,7 @@ struct dstring_s;
|
|||
const char *optype_str (op_type_e type) __attribute__((const));
|
||||
|
||||
operand_t *def_operand (struct def_s *def, struct type_s *type);
|
||||
operand_t *return_operand (struct type_s *type);
|
||||
operand_t *value_operand (struct ex_value_s *value);
|
||||
int tempop_overlap (tempop_t *t1, tempop_t *t2) __attribute__((pure));
|
||||
operand_t *temp_operand (struct type_s *type);
|
||||
|
|
|
@ -63,6 +63,7 @@ typedef enum {
|
|||
typedef struct type_s {
|
||||
etype_t type; ///< ev_invalid means structure/array etc
|
||||
const char *name;
|
||||
int alignment; ///< required alignment for instances
|
||||
/// function/pointer/array/struct types are more complex
|
||||
ty_meta_e meta;
|
||||
union {
|
||||
|
@ -98,6 +99,7 @@ typedef struct {
|
|||
extern type_t type_invalid;
|
||||
extern type_t type_void;
|
||||
extern type_t type_string;
|
||||
extern type_t type_double;
|
||||
extern type_t type_float;
|
||||
extern type_t type_vector;
|
||||
extern type_t type_entity;
|
||||
|
@ -153,6 +155,7 @@ const char *type_get_encoding (const type_t *type);
|
|||
int is_void (const type_t *type) __attribute__((pure));
|
||||
int is_enum (const type_t *type) __attribute__((pure));
|
||||
int is_integral (const type_t *type) __attribute__((pure));
|
||||
int is_double (const type_t *type) __attribute__((pure));
|
||||
int is_float (const type_t *type) __attribute__((pure));
|
||||
int is_scalar (const type_t *type) __attribute__((pure));
|
||||
int is_vector (const type_t *type) __attribute__((pure));
|
||||
|
|
|
@ -40,6 +40,7 @@ struct ex_value_s;
|
|||
struct type_s;
|
||||
|
||||
struct ex_value_s *new_string_val (const char *string_val);
|
||||
struct ex_value_s *new_double_val (double double_val);
|
||||
struct ex_value_s *new_float_val (float float_val);
|
||||
struct ex_value_s *new_vector_val (const float *vector_val);
|
||||
struct ex_value_s *new_entity_val (int entity_val);
|
||||
|
|
|
@ -53,7 +53,7 @@ qfcc_DEPENDENCIES= $(QFCC_DEPS)
|
|||
|
||||
qfprogs_SOURCES= \
|
||||
disassemble.c dump_globals.c dump_lines.c dump_modules.c dump_strings.c \
|
||||
obj_file.c qfprogs.c strpool.c stub.c
|
||||
obj_file.c qfprogs.c strpool.c stub.c type.c
|
||||
qfprogs_LDADD= $(QFCC_LIBS)
|
||||
qfprogs_DEPENDENCIES= $(QFCC_DEPS)
|
||||
|
||||
|
|
|
@ -68,28 +68,29 @@ static hashtab_t *category_hash;
|
|||
static hashtab_t *protocol_hash;
|
||||
|
||||
// these will be built up further
|
||||
type_t type_obj_selector = { ev_invalid, 0, ty_struct};
|
||||
type_t type_SEL = { ev_pointer, "SEL", ty_none, {{&type_obj_selector}}};
|
||||
type_t type_IMP = { ev_func, "IMP", ty_none,
|
||||
type_t type_obj_selector = { ev_invalid, 0, 0, ty_struct};
|
||||
type_t type_SEL = { ev_pointer, "SEL", 1, ty_none, {{&type_obj_selector}}};
|
||||
type_t type_IMP = { ev_func, "IMP", 1, ty_none,
|
||||
{{&type_id, -3, {&type_id, &type_SEL}}}};
|
||||
type_t type_obj_super = { ev_invalid, 0 };
|
||||
type_t type_SuperPtr = { ev_pointer, 0, ty_none, {{&type_obj_super}}};
|
||||
type_t type_supermsg = { ev_func, ".supermsg", ty_none,
|
||||
type_t type_obj_super = { ev_invalid, 0, 0 };
|
||||
type_t type_SuperPtr = { ev_pointer, 0, 1, ty_none, {{&type_obj_super}}};
|
||||
type_t type_supermsg = { ev_func, ".supermsg", 1, ty_none,
|
||||
{{&type_id, -3, {&type_SuperPtr, &type_SEL}}}};
|
||||
type_t type_obj_method = { ev_invalid, 0, ty_struct };
|
||||
type_t type_obj_method_description = { ev_invalid, 0, ty_struct };
|
||||
type_t type_obj_category = { ev_invalid, 0, ty_struct};
|
||||
type_t type_obj_ivar = { ev_invalid, 0, ty_struct};
|
||||
type_t type_obj_module = { ev_invalid, 0, ty_struct};
|
||||
type_t type_moduleptr = { ev_pointer, 0, ty_none, {{&type_obj_module}}};
|
||||
type_t type_obj_exec_class = { ev_func, 0, ty_none,
|
||||
type_t type_obj_method = { ev_invalid, 0, 0, ty_struct };
|
||||
type_t type_obj_method_description = { ev_invalid, 0, 0, ty_struct };
|
||||
type_t type_obj_category = { ev_invalid, 0, 0, ty_struct};
|
||||
type_t type_obj_ivar = { ev_invalid, 0, 0, ty_struct};
|
||||
type_t type_obj_module = { ev_invalid, 0, 0, ty_struct};
|
||||
type_t type_moduleptr = { ev_pointer, 0, 1, ty_none,
|
||||
{{&type_obj_module}}};
|
||||
type_t type_obj_exec_class = { ev_func, 0, 1, ty_none,
|
||||
{{&type_void, 1, { &type_moduleptr }}}};
|
||||
|
||||
type_t type_obj_object = {ev_invalid, 0, ty_struct};
|
||||
type_t type_id = { ev_pointer, "id", ty_none, {{&type_obj_object}}};
|
||||
type_t type_obj_class = { ev_invalid, 0, ty_struct};
|
||||
type_t type_Class = { ev_pointer, 0, ty_none, {{&type_obj_class}}};
|
||||
type_t type_obj_protocol = { ev_invalid, 0, ty_struct};
|
||||
type_t type_obj_object = {ev_invalid, 0, 0, ty_struct};
|
||||
type_t type_id = { ev_pointer, "id", 1, ty_none, {{&type_obj_object}}};
|
||||
type_t type_obj_class = { ev_invalid, 0, 0, ty_struct};
|
||||
type_t type_Class = { ev_pointer, 0, 1, ty_none, {{&type_obj_class}}};
|
||||
type_t type_obj_protocol = { ev_invalid, 0, 0, ty_struct};
|
||||
|
||||
int obj_initialized = 0;
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "qfcc.h"
|
||||
#include "strpool.h"
|
||||
#include "type.h"
|
||||
#include "value.h"
|
||||
#include "qc-parse.h"
|
||||
|
||||
typedef expr_t *(*operation_t) (int op, expr_t *e, expr_t *e1, expr_t *e2);
|
||||
|
@ -163,6 +164,40 @@ convert_to_float (expr_t *e)
|
|||
}
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
convert_to_double (expr_t *e)
|
||||
{
|
||||
if (get_type (e) == &type_double)
|
||||
return e;
|
||||
|
||||
switch (e->type) {
|
||||
case ex_value:
|
||||
switch (e->e.value->lltype) {
|
||||
case ev_integer:
|
||||
e->e.value = new_double_val (expr_integer (e));
|
||||
return e;
|
||||
case ev_short:
|
||||
e->e.value = new_double_val (expr_short (e));
|
||||
return e;
|
||||
case ev_float:
|
||||
e->e.value = new_double_val (expr_float (e));
|
||||
return e;
|
||||
default:
|
||||
internal_error (e, 0);
|
||||
}
|
||||
break;
|
||||
case ex_symbol:
|
||||
case ex_expr:
|
||||
case ex_uexpr:
|
||||
case ex_temp:
|
||||
case ex_block:
|
||||
e = cf_cast_expr (&type_float, e);
|
||||
return e;
|
||||
default:
|
||||
internal_error (e, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
do_op_float (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
||||
{
|
||||
|
@ -292,6 +327,111 @@ do_op_float (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
|||
return e;
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
do_op_double (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
||||
{
|
||||
double d1, d2;
|
||||
expr_t *conv;
|
||||
type_t *type = &type_double;
|
||||
static int valid[] = {
|
||||
'=', '+', '-', '*', '/', '%',
|
||||
LT, GT, LE, GE, EQ, NE, 0
|
||||
};
|
||||
|
||||
if (!valid_op (op, valid))
|
||||
return error (e1, "invalid operator for double");
|
||||
|
||||
if (op == '=' || op == PAS) {
|
||||
if ((type = get_type (e1)) != &type_double) {
|
||||
//FIXME optimize casting a constant
|
||||
e->e.expr.e2 = e2 = cf_cast_expr (type, e2);
|
||||
} else if ((conv = convert_to_double (e2)) != e2) {
|
||||
e->e.expr.e2 = e2 = conv;
|
||||
}
|
||||
} else {
|
||||
if ((conv = convert_to_double (e1)) != e1) {
|
||||
e->e.expr.e1 = e1 = conv;
|
||||
}
|
||||
if ((conv = convert_to_double (e2)) != e2) {
|
||||
e->e.expr.e2 = e2 = conv;
|
||||
}
|
||||
}
|
||||
if (is_compare (op) || is_logic (op)) {
|
||||
type = &type_integer;
|
||||
}
|
||||
e->e.expr.type = type;
|
||||
|
||||
if (op == '*' && is_constant (e1) && expr_double (e1) == 1)
|
||||
return e2;
|
||||
if (op == '*' && is_constant (e2) && expr_double (e2) == 1)
|
||||
return e1;
|
||||
if (op == '*' && is_constant (e1) && expr_double (e1) == 0)
|
||||
return e1;
|
||||
if (op == '*' && is_constant (e2) && expr_double (e2) == 0)
|
||||
return e2;
|
||||
if (op == '/' && is_constant (e2) && expr_double (e2) == 1)
|
||||
return e1;
|
||||
if (op == '/' && is_constant (e2) && expr_double (e2) == 0)
|
||||
return error (e, "division by zero");
|
||||
if (op == '/' && is_constant (e1) && expr_double (e1) == 0)
|
||||
return e1;
|
||||
if (op == '+' && is_constant (e1) && expr_double (e1) == 0)
|
||||
return e2;
|
||||
if (op == '+' && is_constant (e2) && expr_double (e2) == 0)
|
||||
return e1;
|
||||
if (op == '-' && is_constant (e2) && expr_double (e2) == 0)
|
||||
return e1;
|
||||
|
||||
if (op == '=' || !is_constant (e1) || !is_constant (e2))
|
||||
return e;
|
||||
|
||||
d1 = expr_double (e1);
|
||||
d2 = expr_double (e2);
|
||||
|
||||
switch (op) {
|
||||
case '+':
|
||||
e = new_double_expr (d1 + d2);
|
||||
break;
|
||||
case '-':
|
||||
e = new_double_expr (d1 - d2);
|
||||
break;
|
||||
case '*':
|
||||
e = new_double_expr (d1 * d2);
|
||||
break;
|
||||
case '/':
|
||||
if (!d2)
|
||||
return error (e1, "divide by zero");
|
||||
e = new_double_expr (d1 / d2);
|
||||
break;
|
||||
case '%':
|
||||
e = new_double_expr ((int)d1 % (int)d2);
|
||||
break;
|
||||
case LT:
|
||||
e = new_integer_expr (d1 < d2);
|
||||
break;
|
||||
case GT:
|
||||
e = new_integer_expr (d1 > d2);
|
||||
break;
|
||||
case LE:
|
||||
e = new_integer_expr (d1 <= d2);
|
||||
break;
|
||||
case GE:
|
||||
e = new_integer_expr (d1 >= d2);
|
||||
break;
|
||||
case EQ:
|
||||
e = new_integer_expr (d1 == d2);
|
||||
break;
|
||||
case NE:
|
||||
e = new_integer_expr (d1 != d2);
|
||||
break;
|
||||
default:
|
||||
internal_error (e1, 0);
|
||||
}
|
||||
e->file = e1->file;
|
||||
e->line = e1->line;
|
||||
return e;
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
||||
{
|
||||
|
@ -884,11 +1024,15 @@ do_op_compound (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
|||
return do_op_struct (op, e, e1, e2);
|
||||
if (is_scalar (t1) && is_scalar (t2)) {
|
||||
if (is_enum (t1)) {
|
||||
if (t2->type == ev_float)
|
||||
if (t2->type == ev_double)
|
||||
return do_op_float (op, e, e1, e2);
|
||||
if (t2->type == ev_double)
|
||||
return do_op_float (op, e, e1, e2);
|
||||
return do_op_integer (op, e, e1, e2);
|
||||
}
|
||||
if (is_enum (t2)) {
|
||||
if (t1->type == ev_double)
|
||||
return do_op_double (op, e, e1, e2);
|
||||
if (t1->type == ev_float)
|
||||
return do_op_float (op, e, e1, e2);
|
||||
return do_op_integer (op, e, e1, e2);
|
||||
|
@ -947,6 +1091,7 @@ static operation_t op_void[ev_type_count] = {
|
|||
do_op_invalid, // ev_integer
|
||||
do_op_invalid, // ev_uinteger
|
||||
do_op_invalid, // ev_short
|
||||
do_op_invalid, // ev_double
|
||||
do_op_invalid, // ev_invalid
|
||||
};
|
||||
|
||||
|
@ -963,6 +1108,7 @@ static operation_t op_string[ev_type_count] = {
|
|||
do_op_invalid, // ev_integer
|
||||
do_op_invalid, // ev_uinteger
|
||||
do_op_invalid, // ev_short
|
||||
do_op_invalid, // ev_double
|
||||
do_op_invalid, // ev_invalid
|
||||
};
|
||||
|
||||
|
@ -979,6 +1125,7 @@ static operation_t op_float[ev_type_count] = {
|
|||
do_op_float, // ev_integer
|
||||
do_op_float, // ev_uinteger
|
||||
do_op_float, // ev_short
|
||||
do_op_double, // ev_double
|
||||
do_op_invalid, // ev_invalid
|
||||
};
|
||||
|
||||
|
@ -995,6 +1142,7 @@ static operation_t op_vector[ev_type_count] = {
|
|||
do_op_vector, // ev_integer
|
||||
do_op_vector, // ev_uinteger
|
||||
do_op_vector, // ev_short
|
||||
do_op_vector, // ev_double
|
||||
do_op_invalid, // ev_invalid
|
||||
};
|
||||
|
||||
|
@ -1011,6 +1159,7 @@ static operation_t op_entity[ev_type_count] = {
|
|||
do_op_invalid, // ev_integer
|
||||
do_op_invalid, // ev_uinteger
|
||||
do_op_invalid, // ev_short
|
||||
do_op_invalid, // ev_double
|
||||
do_op_invalid, // ev_invalid
|
||||
};
|
||||
|
||||
|
@ -1027,6 +1176,7 @@ static operation_t op_field[ev_type_count] = {
|
|||
do_op_invalid, // ev_integer
|
||||
do_op_invalid, // ev_uinteger
|
||||
do_op_invalid, // ev_short
|
||||
do_op_invalid, // ev_double
|
||||
do_op_invalid, // ev_invalid
|
||||
};
|
||||
|
||||
|
@ -1043,6 +1193,7 @@ static operation_t op_func[ev_type_count] = {
|
|||
do_op_func, // ev_integer
|
||||
do_op_func, // ev_uinteger
|
||||
do_op_func, // ev_short
|
||||
do_op_func, // ev_double
|
||||
do_op_func, // ev_invalid
|
||||
};
|
||||
|
||||
|
@ -1059,6 +1210,7 @@ static operation_t op_pointer[ev_type_count] = {
|
|||
do_op_pointer, // ev_integer
|
||||
do_op_pointer, // ev_uinteger
|
||||
do_op_pointer, // ev_short
|
||||
do_op_pointer, // ev_double
|
||||
do_op_pointer, // ev_invalid
|
||||
};
|
||||
|
||||
|
@ -1075,6 +1227,7 @@ static operation_t op_quaternion[ev_type_count] = {
|
|||
do_op_quaternion, // ev_integer
|
||||
do_op_quaternion, // ev_uinteger
|
||||
do_op_quaternion, // ev_short
|
||||
do_op_quaternion, // ev_double
|
||||
do_op_invalid, // ev_invalid
|
||||
};
|
||||
|
||||
|
@ -1091,6 +1244,7 @@ static operation_t op_integer[ev_type_count] = {
|
|||
do_op_integer, // ev_integer
|
||||
do_op_uinteger, // ev_uinteger
|
||||
do_op_integer, // ev_short
|
||||
do_op_double, // ev_double
|
||||
do_op_invalid, // ev_invalid
|
||||
};
|
||||
|
||||
|
@ -1107,6 +1261,7 @@ static operation_t op_uinteger[ev_type_count] = {
|
|||
do_op_uinteger, // ev_integer
|
||||
do_op_uinteger, // ev_uinteger
|
||||
do_op_uinteger, // ev_short
|
||||
do_op_double, // ev_double
|
||||
do_op_invalid, // ev_invalid
|
||||
};
|
||||
|
||||
|
@ -1123,6 +1278,24 @@ static operation_t op_short[ev_type_count] = {
|
|||
do_op_integer, // ev_integer
|
||||
do_op_uinteger, // ev_uinteger
|
||||
do_op_short, // ev_short
|
||||
do_op_double, // ev_double
|
||||
do_op_invalid, // ev_invalid
|
||||
};
|
||||
|
||||
static operation_t op_double[ev_type_count] = {
|
||||
do_op_invalid, // ev_void
|
||||
do_op_invalid, // ev_string
|
||||
do_op_float, // ev_float
|
||||
do_op_vector, // ev_vector
|
||||
do_op_invalid, // ev_entity
|
||||
do_op_invalid, // ev_field
|
||||
do_op_invalid, // ev_func
|
||||
do_op_invalid, // ev_pointer
|
||||
do_op_quaternion, // ev_quaternion
|
||||
do_op_integer, // ev_integer
|
||||
do_op_uinteger, // ev_uinteger
|
||||
do_op_short, // ev_short
|
||||
do_op_double, // ev_double
|
||||
do_op_invalid, // ev_invalid
|
||||
};
|
||||
|
||||
|
@ -1139,6 +1312,7 @@ static operation_t op_compound[ev_type_count] = {
|
|||
do_op_compound, // ev_integer
|
||||
do_op_compound, // ev_uinteger
|
||||
do_op_compound, // ev_short
|
||||
do_op_compound, // ev_double
|
||||
do_op_compound, // ev_invalid
|
||||
};
|
||||
|
||||
|
@ -1155,6 +1329,7 @@ static operation_t *do_op[ev_type_count] = {
|
|||
op_integer, // ev_integer
|
||||
op_uinteger, // ev_uinteger
|
||||
op_short, // ev_short
|
||||
op_double, // ev_double
|
||||
op_compound, // ev_invalid
|
||||
};
|
||||
|
||||
|
@ -1203,13 +1378,15 @@ static expr_t *
|
|||
uop_float (int op, expr_t *e, expr_t *e1)
|
||||
{
|
||||
static int valid[] = { '+', '-', '!', '~', 'C', 0 };
|
||||
type_t *type;
|
||||
|
||||
if (!valid_op (op, valid))
|
||||
return error (e1, "invalid unary operator for float: %s",
|
||||
get_op_string (op));
|
||||
if (op == '+')
|
||||
return e1;
|
||||
if (op == 'C' && get_type (e) != &type_integer)
|
||||
type = get_type (e);
|
||||
if (op == 'C' && type != &type_integer && type != &type_double)
|
||||
return error (e1, "invalid cast of float");
|
||||
if (!is_constant (e1))
|
||||
return e;
|
||||
|
@ -1222,7 +1399,11 @@ uop_float (int op, expr_t *e, expr_t *e1)
|
|||
case '~':
|
||||
return new_float_expr (~(int) expr_float (e1));
|
||||
case 'C':
|
||||
return new_integer_expr (expr_float (e1));
|
||||
if (type == &type_integer) {
|
||||
return new_integer_expr (expr_float (e1));
|
||||
} else {
|
||||
return new_double_expr (expr_float (e1));
|
||||
}
|
||||
}
|
||||
internal_error (e, "float unary op blew up");
|
||||
}
|
||||
|
@ -1420,6 +1601,38 @@ uop_short (int op, expr_t *e, expr_t *e1)
|
|||
internal_error (e, "short unary op blew up");
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
uop_double (int op, expr_t *e, expr_t *e1)
|
||||
{
|
||||
static int valid[] = { '+', '-', '!', 'C', 0 };
|
||||
type_t *type;
|
||||
|
||||
if (!valid_op (op, valid))
|
||||
return error (e1, "invalid unary operator for double: %s",
|
||||
get_op_string (op));
|
||||
if (op == '+')
|
||||
return e1;
|
||||
type = get_type (e);
|
||||
if (op == 'C' && type != &type_integer && type != &type_float)
|
||||
return error (e1, "invalid cast of double");
|
||||
if (!is_constant (e1))
|
||||
return e;
|
||||
switch (op) {
|
||||
case '-':
|
||||
return new_double_expr (-expr_double (e1));
|
||||
case '!':
|
||||
print_type (get_type (e));
|
||||
return new_integer_expr (!expr_double (e1));
|
||||
case 'C':
|
||||
if (type == &type_integer) {
|
||||
return new_integer_expr (expr_double (e1));
|
||||
} else {
|
||||
return new_float_expr (expr_double (e1));
|
||||
}
|
||||
}
|
||||
internal_error (e, "float unary op blew up");
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
uop_compound (int op, expr_t *e, expr_t *e1)
|
||||
{
|
||||
|
@ -1446,6 +1659,7 @@ static unaryop_t do_unary_op[ev_type_count] = {
|
|||
uop_integer, // ev_integer
|
||||
uop_uinteger, // ev_uinteger
|
||||
uop_short, // ev_short
|
||||
uop_double, // ev_double
|
||||
uop_compound, // ev_invalid
|
||||
};
|
||||
|
||||
|
@ -1487,7 +1701,7 @@ fold_constants (expr_t *e)
|
|||
|
||||
if (t1 >= ev_type_count || t2 >= ev_type_count
|
||||
|| !do_op[t1] || !do_op[t1][t2])
|
||||
internal_error (e, "invalid type");
|
||||
internal_error (e, "invalid type %d %d", t1, t2);
|
||||
return do_op[t1][t2] (op, e, e1, e2);
|
||||
}
|
||||
return e;
|
||||
|
|
|
@ -148,11 +148,17 @@ new_def (const char *name, type_t *type, defspace_t *space,
|
|||
|
||||
if (storage != sc_extern) {
|
||||
int size = type_size (type);
|
||||
int alignment = type->alignment;
|
||||
|
||||
if (!size) {
|
||||
error (0, "%s has incomplete type", name);
|
||||
size = 1;
|
||||
}
|
||||
def->offset = defspace_alloc_loc (space, size);
|
||||
if (alignment < 1) {
|
||||
print_type (type);
|
||||
internal_error (0, "temp type has no alignment");
|
||||
}
|
||||
def->offset = defspace_alloc_aligned_loc (space, size, alignment);
|
||||
}
|
||||
|
||||
return def;
|
||||
|
@ -199,16 +205,20 @@ temp_def (type_t *type)
|
|||
def_t *temp;
|
||||
defspace_t *space = current_func->symtab->space;
|
||||
int size = type_size (type);
|
||||
int alignment = type->alignment;
|
||||
|
||||
if (size < 1 || size > 4) {
|
||||
internal_error (0, "%d invalid size for temp def", size);
|
||||
}
|
||||
if (alignment < 1) {
|
||||
internal_error (0, "temp type has no alignment");
|
||||
}
|
||||
if ((temp = current_func->temp_defs[size - 1])) {
|
||||
current_func->temp_defs[size - 1] = temp->temp_next;
|
||||
temp->temp_next = 0;
|
||||
} else {
|
||||
ALLOC (16384, def_t, defs, temp);
|
||||
temp->offset = defspace_alloc_loc (space, size);
|
||||
temp->offset = defspace_alloc_aligned_loc (space, size, alignment);
|
||||
*space->def_tail = temp;
|
||||
space->def_tail = &temp->next;
|
||||
temp->name = save_string (va (".tmp%d", current_func->temp_num++));
|
||||
|
@ -565,7 +575,8 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space,
|
|||
init_elements (sym->s.def, init);
|
||||
sym->s.def->initialized = 1;
|
||||
} else {
|
||||
if (!type_assignable (sym->type, get_type (init))) {
|
||||
type_t *init_type = get_type (init);
|
||||
if (!type_assignable (sym->type, init_type)) {
|
||||
error (init, "type mismatch in initializer");
|
||||
return;
|
||||
}
|
||||
|
@ -575,8 +586,20 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space,
|
|||
// fold_constants takes care of int/float conversions
|
||||
append_expr (local_expr, fold_constants (init));
|
||||
} else {
|
||||
int offset = 0;
|
||||
if (!is_constant (init)) {
|
||||
error (init, "non-constant initializier");
|
||||
return;
|
||||
}
|
||||
while ((init->type == ex_uexpr || init->type == ex_expr)
|
||||
&& init->e.expr.op == 'A') {
|
||||
if (init->type == ex_expr) {
|
||||
offset += expr_integer (init->e.expr.e2);
|
||||
}
|
||||
init = init->e.expr.e1;
|
||||
}
|
||||
if (init->type != ex_value) { //FIXME enum etc
|
||||
error (0, "non-constant initializier");
|
||||
internal_error (0, "initializier not a value");
|
||||
return;
|
||||
}
|
||||
if (init->e.value->lltype == ev_pointer
|
||||
|
@ -587,6 +610,11 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space,
|
|||
reloc_def_field (init->e.value->v.pointer.def, sym->s.def);
|
||||
} else {
|
||||
ex_value_t *v = init->e.value;
|
||||
if (is_double (init_type)
|
||||
&& (is_integral (sym->type) || is_float (sym->type))) {
|
||||
warning (init, "assigning double to %s in initializer "
|
||||
"(use a cast)", sym->type->name);
|
||||
}
|
||||
if (is_scalar (sym->type))
|
||||
v = convert_value (v, sym->type);
|
||||
if (v->lltype == ev_string) {
|
||||
|
|
|
@ -63,6 +63,33 @@ typedef struct locref_s {
|
|||
static defspace_t *spaces_freelist;
|
||||
static locref_t *locrefs_freelist;
|
||||
|
||||
static locref_t *
|
||||
new_locref (int ofs, int size, locref_t *next)
|
||||
{
|
||||
locref_t *loc;
|
||||
|
||||
ALLOC (1024, locref_t, locrefs, loc);
|
||||
loc->ofs = ofs;
|
||||
loc->size = size;
|
||||
loc->next = next;
|
||||
return loc;
|
||||
}
|
||||
|
||||
static void
|
||||
del_locref (locref_t *loc)
|
||||
{
|
||||
FREE (locrefs, loc);
|
||||
}
|
||||
|
||||
static defspace_t *
|
||||
new_defspace (void)
|
||||
{
|
||||
defspace_t *space;
|
||||
|
||||
ALLOC (1024, defspace_t, spaces, space);
|
||||
return space;
|
||||
}
|
||||
|
||||
#define GROW 1024
|
||||
|
||||
static int
|
||||
|
@ -98,9 +125,8 @@ grow_space_virtual (defspace_t *space)
|
|||
defspace_t *
|
||||
defspace_new (ds_type_t type)
|
||||
{
|
||||
defspace_t *space;
|
||||
defspace_t *space = new_defspace ();
|
||||
|
||||
ALLOC (1024, defspace_t, spaces, space);
|
||||
space->def_tail = &space->defs;
|
||||
space->type = type;
|
||||
if (type == ds_backed) {
|
||||
|
@ -116,33 +142,59 @@ defspace_new (ds_type_t type)
|
|||
int
|
||||
defspace_alloc_loc (defspace_t *space, int size)
|
||||
{
|
||||
int ofs;
|
||||
return defspace_alloc_aligned_loc (space, size, 1);
|
||||
}
|
||||
|
||||
int
|
||||
defspace_alloc_aligned_loc (defspace_t *space, int size, int alignment)
|
||||
{
|
||||
int ofs, pad;
|
||||
locref_t *loc;
|
||||
locref_t **l = &space->free_locs;
|
||||
|
||||
if (size <= 0)
|
||||
internal_error (0, "invalid number of words requested: %d", size);
|
||||
while (*l && (*l)->size < size)
|
||||
l = &(*l)->next;
|
||||
if ((loc = *l)) {
|
||||
ofs = (*l)->ofs;
|
||||
if ((*l)->size == size) {
|
||||
loc = *l;
|
||||
*l = (*l)->next;
|
||||
FREE (locrefs, loc);
|
||||
} else {
|
||||
(*l)->ofs += size;
|
||||
(*l)->size -= size;
|
||||
if (alignment <= 0)
|
||||
internal_error (0, "invalid alignment requested: %d", alignment);
|
||||
while ((loc = *l)) {
|
||||
ofs = loc->ofs;
|
||||
pad = alignment * ((ofs + alignment - 1) / alignment) - ofs;
|
||||
// exact fit, so just shrink the block or remove it if there is no
|
||||
// padding (any padding remains free)
|
||||
if (size + pad == loc->size) {
|
||||
if (!pad) {
|
||||
*l = loc->next;
|
||||
del_locref (loc);
|
||||
}
|
||||
return ofs + pad;
|
||||
}
|
||||
return ofs;
|
||||
// there's excess space in the block. If there's no padding, then
|
||||
// just shrink it, otherwise split it into two, one on either side
|
||||
// of the allocated block, such that the padding remains free
|
||||
if (size + pad < loc->size) {
|
||||
if (!pad) {
|
||||
loc->ofs += size;
|
||||
loc->size -= size;
|
||||
} else {
|
||||
loc->next = new_locref (ofs + pad + size,
|
||||
loc->size - ofs - pad, loc->next);
|
||||
loc->size = pad;
|
||||
}
|
||||
return ofs + pad;
|
||||
}
|
||||
l = &(*l)->next;
|
||||
}
|
||||
ofs = space->size;
|
||||
space->size += size;
|
||||
pad = alignment * ((ofs + alignment - 1) / alignment) - ofs;
|
||||
space->size += size + pad;
|
||||
if (space->size > space->max_size) {
|
||||
if (!space->grow || !space->grow (space))
|
||||
internal_error (0, "unable to allocate %d words", size);
|
||||
}
|
||||
return ofs;
|
||||
if (pad) {
|
||||
*l = new_locref (ofs, pad, 0);
|
||||
}
|
||||
return ofs + pad;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -184,17 +236,13 @@ defspace_free_loc (defspace_t *space, int ofs, int size)
|
|||
loc->size += loc->next->size;
|
||||
loc = loc->next;
|
||||
*l = loc->next;
|
||||
FREE (locrefs, loc);
|
||||
del_locref (loc);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
// insert a new free block for the location to be freed
|
||||
ALLOC (1024, locref_t, locrefs, loc);
|
||||
loc->ofs = ofs;
|
||||
loc->size = size;
|
||||
loc->next = *l;
|
||||
*l = loc;
|
||||
*l = new_locref (ofs, size, *l);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -141,17 +141,39 @@ _debug (expr_t *e, const char *file, int line, const char *fmt, ...)
|
|||
va_end (args);
|
||||
}
|
||||
|
||||
static __attribute__((noreturn, format(printf, 4, 0))) void
|
||||
__internal_error (expr_t *e, const char *file, int line,
|
||||
const char *fmt, va_list args)
|
||||
{
|
||||
dstring_t *message = dstring_new ();
|
||||
|
||||
report_function (e);
|
||||
|
||||
format_message (message, "internal error", e, fmt, args);
|
||||
dasprintf (message, " (%s:%d)", file, line);
|
||||
fprintf (stderr, "%s\n", message->str);
|
||||
dstring_delete (message);
|
||||
abort ();
|
||||
}
|
||||
|
||||
void
|
||||
_bug (expr_t *e, const char *file, int line, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
report_function (e);
|
||||
if (options.bug.silent)
|
||||
return;
|
||||
|
||||
va_start (args, fmt);
|
||||
if (options.bug.promote) {
|
||||
__internal_error (e, file, line, fmt, args);
|
||||
}
|
||||
|
||||
{
|
||||
dstring_t *message = dstring_new ();
|
||||
|
||||
report_function (e);
|
||||
|
||||
format_message (message, "BUG", e, fmt, args);
|
||||
dasprintf (message, " (%s:%d)", file, line);
|
||||
if (bug_hook) {
|
||||
|
@ -211,19 +233,9 @@ _internal_error (expr_t *e, const char *file, int line, const char *fmt, ...)
|
|||
{
|
||||
va_list args;
|
||||
|
||||
report_function (e);
|
||||
|
||||
va_start (args, fmt);
|
||||
{
|
||||
dstring_t *message = dstring_new ();
|
||||
|
||||
format_message (message, "internal error", e, fmt, args);
|
||||
dasprintf (message, " (%s:%d)", file, line);
|
||||
fprintf (stderr, "%s\n", message->str);
|
||||
dstring_delete (message);
|
||||
}
|
||||
__internal_error (e, file, line, fmt, args);
|
||||
va_end (args);
|
||||
abort ();
|
||||
}
|
||||
|
||||
expr_t *
|
||||
|
|
|
@ -88,6 +88,7 @@ get_op_string (int op)
|
|||
case '*': return "*";
|
||||
case '/': return "/";
|
||||
case '%': return "%";
|
||||
case MOD: return "%%";
|
||||
case '&': return "&";
|
||||
case '|': return "|";
|
||||
case '^': return "^";
|
||||
|
@ -438,6 +439,9 @@ print_value (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next)
|
|||
case ev_string:
|
||||
label = va ("\\\"%s\\\"", quote_string (e->e.value->v.string_val));
|
||||
break;
|
||||
case ev_double:
|
||||
label = va ("f %g", e->e.value->v.double_val);
|
||||
break;
|
||||
case ev_float:
|
||||
label = va ("f %g", e->e.value->v.float_val);
|
||||
break;
|
||||
|
|
|
@ -97,6 +97,9 @@ dump_def (progs_t *pr, ddef_t *def, int indent)
|
|||
case ev_float:
|
||||
comment = va (" %g", G_FLOAT (pr, offset));
|
||||
break;
|
||||
case ev_double:
|
||||
comment = va (" %.17g", G_DOUBLE (pr, offset));
|
||||
break;
|
||||
case ev_vector:
|
||||
comment = va (" '%g %g %g'",
|
||||
G_VECTOR (pr, offset)[0],
|
||||
|
@ -214,7 +217,8 @@ dump_functions (progs_t *pr)
|
|||
else
|
||||
count = func->numparms;
|
||||
for (j = 0; j < count; j++)
|
||||
printf (" %d", func->parm_size[j]);
|
||||
printf (" %d:%d", func->parm_size[j].alignment,
|
||||
func->parm_size[j].size);
|
||||
printf (") %d @ %x", func->locals, func->parm_start);
|
||||
puts ("");
|
||||
if (pr->debug) {
|
||||
|
|
|
@ -611,6 +611,15 @@ new_string_expr (const char *string_val)
|
|||
return e;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
new_double_expr (double double_val)
|
||||
{
|
||||
expr_t *e = new_expr ();
|
||||
e->type = ex_value;
|
||||
e->e.value = new_double_val (double_val);
|
||||
return e;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
new_float_expr (float float_val)
|
||||
{
|
||||
|
@ -768,6 +777,10 @@ new_short_expr (short short_val)
|
|||
int
|
||||
is_constant (expr_t *e)
|
||||
{
|
||||
while ((e->type == ex_uexpr || e->type == ex_expr)
|
||||
&& e->e.expr.op == 'A') {
|
||||
e = e->e.expr.e1;
|
||||
}
|
||||
if (e->type == ex_nil || e->type == ex_value || e->type == ex_labelref
|
||||
|| (e->type == ex_symbol && e->e.symbol->sy_type == sy_const)
|
||||
|| (e->type == ex_symbol && e->e.symbol->sy_type == sy_var
|
||||
|
@ -845,6 +858,23 @@ is_float_val (expr_t *e)
|
|||
return 0;
|
||||
}
|
||||
|
||||
double
|
||||
expr_double (expr_t *e)
|
||||
{
|
||||
if (e->type == ex_nil)
|
||||
return 0;
|
||||
if (e->type == ex_value && e->e.value->lltype == ev_double)
|
||||
return e->e.value->v.double_val;
|
||||
if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const
|
||||
&& e->e.symbol->type->type == ev_double)
|
||||
return e->e.symbol->s.value->v.double_val;
|
||||
if (e->type == ex_symbol && e->e.symbol->sy_type == sy_var
|
||||
&& e->e.symbol->s.def->constant
|
||||
&& is_double (e->e.symbol->s.def->type))
|
||||
return D_DOUBLE (e->e.symbol->s.def);
|
||||
internal_error (e, "not a double constant");
|
||||
}
|
||||
|
||||
float
|
||||
expr_float (expr_t *e)
|
||||
{
|
||||
|
@ -1024,8 +1054,6 @@ new_alias_expr (type_t *type, expr_t *expr)
|
|||
{
|
||||
expr_t *alias;
|
||||
|
||||
if (expr->type == ex_value)
|
||||
return new_value_expr (alias_value (expr->e.value, type));
|
||||
alias = new_unary_expr ('A', expr);
|
||||
alias->e.expr.type = type;
|
||||
//if (expr->type == ex_uexpr && expr->e.expr.op == 'A')
|
||||
|
@ -1276,6 +1304,9 @@ test_expr (expr_t *e)
|
|||
}
|
||||
new = new_float_expr (0);
|
||||
break;
|
||||
case ev_double:
|
||||
new = new_double_expr (0);
|
||||
break;
|
||||
case ev_vector:
|
||||
new = new_vector_expr (zero);
|
||||
break;
|
||||
|
@ -1610,6 +1641,8 @@ unary_expr (int op, expr_t *e)
|
|||
case ev_func:
|
||||
case ev_pointer:
|
||||
internal_error (e, "type check failed!");
|
||||
case ev_double:
|
||||
return new_double_expr (-expr_double (e));
|
||||
case ev_float:
|
||||
return new_float_expr (-expr_float (e));
|
||||
case ev_vector:
|
||||
|
@ -1676,6 +1709,8 @@ unary_expr (int op, expr_t *e)
|
|||
case ev_string:
|
||||
s = expr_string (e);
|
||||
return new_integer_expr (!s || !s[0]);
|
||||
case ev_double:
|
||||
return new_integer_expr (!expr_double (e));
|
||||
case ev_float:
|
||||
return new_integer_expr (!expr_float (e));
|
||||
case ev_vector:
|
||||
|
@ -1735,6 +1770,7 @@ unary_expr (int op, expr_t *e)
|
|||
case ev_func:
|
||||
case ev_pointer:
|
||||
case ev_vector:
|
||||
case ev_double:
|
||||
return error (e, "invalid type for unary ~");
|
||||
case ev_float:
|
||||
return new_float_expr (~(int) expr_float (e));
|
||||
|
@ -1881,6 +1917,10 @@ build_function_call (expr_t *fexpr, type_t *ftype, expr_t *params)
|
|||
if (is_integer_val (e)
|
||||
&& options.code.progsversion == PROG_ID_VERSION)
|
||||
convert_int (e);
|
||||
if (is_float (get_type (e))
|
||||
&& options.code.progsversion != PROG_ID_VERSION) {
|
||||
t = &type_double;
|
||||
}
|
||||
if (is_integer_val (e) && options.warnings.vararg_integer)
|
||||
warning (e, "passing integer constant into ... function");
|
||||
}
|
||||
|
@ -2235,6 +2275,14 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t)
|
|||
e = e1->e.expr.e2;
|
||||
break;
|
||||
}
|
||||
if (e1->e.expr.op == 'A') {
|
||||
if (!t)
|
||||
t = e1->e.expr.type;
|
||||
if (e2) {
|
||||
e2 = binary_expr ('+', e1->e.expr.e2, e2);
|
||||
}
|
||||
return address_expr (e1->e.expr.e1, e2, t);
|
||||
}
|
||||
return error (e1, "invalid type for unary &");
|
||||
case ex_uexpr:
|
||||
if (e1->e.expr.op == '.') {
|
||||
|
@ -2577,8 +2625,9 @@ cast_expr (type_t *type, expr_t *e)
|
|||
e->e.value = convert_value (val, type);
|
||||
e->type = ex_value;
|
||||
c = e;
|
||||
} else if ((is_float (type) && is_integral (e_type))
|
||||
|| (is_integral (type) && is_float (e_type))) {
|
||||
} else if (is_integral (type) && is_integral (e_type)) {
|
||||
c = new_alias_expr (type, e);
|
||||
} else if (is_scalar (type) && is_scalar (e_type)) {
|
||||
c = new_unary_expr ('C', e);
|
||||
c->e.expr.type = type;
|
||||
} else if (e->type == ex_uexpr && e->e.expr.op == '.') {
|
||||
|
|
|
@ -151,6 +151,10 @@ check_types_compatible (expr_t *dst, expr_t *src)
|
|||
|
||||
if (type_assignable (dst_type, src_type)) {
|
||||
if (is_scalar (dst_type) && is_scalar (src_type)) {
|
||||
if (is_double (src_type)) {
|
||||
warning (dst, "assignment of double to %s (use a cast)\n",
|
||||
dst_type->name);
|
||||
}
|
||||
// the types are different but cast-compatible
|
||||
expr_t *new = cast_expr (dst_type, src);
|
||||
// the cast was a no-op, so the types are compatible at the
|
||||
|
|
|
@ -47,6 +47,7 @@ typedef struct {
|
|||
|
||||
static expr_t *pointer_arithmetic (int op, expr_t *e1, expr_t *e2);
|
||||
static expr_t *inverse_multiply (int op, expr_t *e1, expr_t *e2);
|
||||
static expr_t *double_compare (int op, expr_t *e1, expr_t *e2);
|
||||
|
||||
static expr_type_t string_string[] = {
|
||||
{'+', &type_string},
|
||||
|
@ -68,6 +69,7 @@ static expr_type_t float_float[] = {
|
|||
{'|', &type_float},
|
||||
{'^', &type_float},
|
||||
{'%', &type_float},
|
||||
{MOD, &type_float},
|
||||
{SHL, &type_float},
|
||||
{SHR, &type_float},
|
||||
{EQ, &type_integer},
|
||||
|
@ -86,7 +88,6 @@ static expr_type_t float_vector[] = {
|
|||
|
||||
static expr_type_t float_quat[] = {
|
||||
{'*', &type_quaternion},
|
||||
{'/', 0, 0, 0, inverse_multiply},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
|
@ -99,6 +100,7 @@ static expr_type_t float_integer[] = {
|
|||
{'|', &type_float, 0, &type_float},
|
||||
{'^', &type_float, 0, &type_float},
|
||||
{'%', &type_float, 0, &type_float},
|
||||
{MOD, &type_float, 0, &type_float},
|
||||
{SHL, &type_float, 0, &type_float},
|
||||
{SHR, &type_float, 0, &type_float},
|
||||
{EQ, &type_integer, 0, &type_float},
|
||||
|
@ -112,6 +114,22 @@ static expr_type_t float_integer[] = {
|
|||
#define float_uinteger float_integer
|
||||
#define float_short float_integer
|
||||
|
||||
static expr_type_t float_double[] = {
|
||||
{'+', &type_double, &type_double, 0},
|
||||
{'-', &type_double, &type_double, 0},
|
||||
{'*', &type_double, &type_double, 0},
|
||||
{'/', &type_double, &type_double, 0},
|
||||
{'%', &type_double, &type_double, 0},
|
||||
{MOD, &type_double, &type_double, 0},
|
||||
{EQ, 0, 0, 0, double_compare},
|
||||
{NE, 0, 0, 0, double_compare},
|
||||
{LE, 0, 0, 0, double_compare},
|
||||
{GE, 0, 0, 0, double_compare},
|
||||
{LT, 0, 0, 0, double_compare},
|
||||
{GT, 0, 0, 0, double_compare},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
static expr_type_t vector_float[] = {
|
||||
{'*', &type_vector},
|
||||
{'/', 0, 0, 0, inverse_multiply},
|
||||
|
@ -131,6 +149,12 @@ static expr_type_t vector_vector[] = {
|
|||
#define vector_uinteger vector_float
|
||||
#define vector_short vector_float
|
||||
|
||||
static expr_type_t vector_double[] = {
|
||||
{'*', &type_vector},
|
||||
{'/', 0, 0, 0, inverse_multiply},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
static expr_type_t entity_entity[] = {
|
||||
{EQ, &type_integer},
|
||||
{NE, &type_integer},
|
||||
|
@ -170,7 +194,7 @@ static expr_type_t pointer_integer[] = {
|
|||
|
||||
static expr_type_t quat_float[] = {
|
||||
{'*', &type_quaternion},
|
||||
{'/', &type_quaternion},
|
||||
{'/', 0, 0, 0, inverse_multiply},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
|
@ -190,12 +214,18 @@ static expr_type_t quat_quat[] = {
|
|||
|
||||
static expr_type_t quat_integer[] = {
|
||||
{'*', &type_quaternion, 0, &type_float},
|
||||
{'/', &type_quaternion, 0, &type_float},
|
||||
{'/', 0, 0, 0, inverse_multiply},
|
||||
{0, 0}
|
||||
};
|
||||
#define quat_uinteger quat_integer
|
||||
#define quat_short quat_integer
|
||||
|
||||
static expr_type_t quat_double[] = {
|
||||
{'*', &type_quaternion},
|
||||
{'/', 0, 0, 0, inverse_multiply},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
static expr_type_t integer_float[] = {
|
||||
{'+', &type_float, &type_float, 0},
|
||||
{'-', &type_float, &type_float, 0},
|
||||
|
@ -205,6 +235,7 @@ static expr_type_t integer_float[] = {
|
|||
{'|', &type_float, &type_float, 0},
|
||||
{'^', &type_float, &type_float, 0},
|
||||
{'%', &type_float, &type_float, 0},
|
||||
{MOD, &type_float, &type_float, 0},
|
||||
{SHL, &type_integer, 0, &type_integer}, //FIXME?
|
||||
{SHR, &type_integer, 0, &type_integer}, //FIXME?
|
||||
{EQ, &type_integer, &type_float, 0},
|
||||
|
@ -228,7 +259,6 @@ static expr_type_t integer_pointer[] = {
|
|||
|
||||
static expr_type_t integer_quat[] = {
|
||||
{'*', &type_quaternion, &type_float, 0},
|
||||
{'/', &type_quaternion, &type_float, 0},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
|
@ -241,6 +271,7 @@ static expr_type_t integer_integer[] = {
|
|||
{'|', &type_integer},
|
||||
{'^', &type_integer},
|
||||
{'%', &type_integer},
|
||||
{MOD, &type_integer},
|
||||
{SHL, &type_integer},
|
||||
{SHR, &type_integer},
|
||||
{EQ, &type_integer},
|
||||
|
@ -261,6 +292,7 @@ static expr_type_t integer_uinteger[] = {
|
|||
{'|', &type_integer},
|
||||
{'^', &type_integer},
|
||||
{'%', &type_integer},
|
||||
{MOD, &type_integer},
|
||||
{SHL, &type_integer},
|
||||
{SHR, &type_integer},
|
||||
{EQ, &type_integer},
|
||||
|
@ -281,6 +313,7 @@ static expr_type_t integer_short[] = {
|
|||
{'|', &type_integer, 0, &type_integer},
|
||||
{'^', &type_integer, 0, &type_integer},
|
||||
{'%', &type_integer, 0, &type_integer},
|
||||
{MOD, &type_integer, 0, &type_integer},
|
||||
{SHL, &type_integer, 0, &type_integer},
|
||||
{SHR, &type_integer, 0, &type_integer},
|
||||
{EQ, &type_integer, 0, &type_integer},
|
||||
|
@ -292,6 +325,22 @@ static expr_type_t integer_short[] = {
|
|||
{0, 0}
|
||||
};
|
||||
|
||||
static expr_type_t integer_double[] = {
|
||||
{'+', &type_double, &type_double, 0},
|
||||
{'-', &type_double, &type_double, 0},
|
||||
{'*', &type_double, &type_double, 0},
|
||||
{'/', &type_double, &type_double, 0},
|
||||
{'%', &type_double, &type_double, 0},
|
||||
{MOD, &type_double, &type_double, 0},
|
||||
{EQ, &type_integer, &type_double, 0},
|
||||
{NE, &type_integer, &type_double, 0},
|
||||
{LE, &type_integer, &type_double, 0},
|
||||
{GE, &type_integer, &type_double, 0},
|
||||
{LT, &type_integer, &type_double, 0},
|
||||
{GT, &type_integer, &type_double, 0},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
#define uinteger_float integer_float
|
||||
#define uinteger_vector integer_vector
|
||||
#define uinteger_pointer integer_pointer
|
||||
|
@ -306,6 +355,7 @@ static expr_type_t uinteger_integer[] = {
|
|||
{'|', &type_integer},
|
||||
{'^', &type_integer},
|
||||
{'%', &type_integer},
|
||||
{MOD, &type_integer},
|
||||
{SHL, &type_uinteger},
|
||||
{SHR, &type_uinteger},
|
||||
{EQ, &type_integer},
|
||||
|
@ -326,6 +376,7 @@ static expr_type_t uinteger_uinteger[] = {
|
|||
{'|', &type_uinteger},
|
||||
{'^', &type_uinteger},
|
||||
{'%', &type_uinteger},
|
||||
{MOD, &type_uinteger},
|
||||
{SHL, &type_uinteger},
|
||||
{SHR, &type_uinteger},
|
||||
{EQ, &type_integer},
|
||||
|
@ -337,6 +388,7 @@ static expr_type_t uinteger_uinteger[] = {
|
|||
{0, 0}
|
||||
};
|
||||
#define uinteger_short uinteger_integer
|
||||
#define uinteger_double integer_double
|
||||
|
||||
#define short_float integer_float
|
||||
#define short_vector integer_vector
|
||||
|
@ -352,6 +404,7 @@ static expr_type_t short_integer[] = {
|
|||
{'|', &type_integer, &type_integer, 0},
|
||||
{'^', &type_integer, &type_integer, 0},
|
||||
{'%', &type_integer, &type_integer, 0},
|
||||
{MOD, &type_integer, &type_integer, 0},
|
||||
{SHL, &type_short},
|
||||
{SHR, &type_short},
|
||||
{EQ, &type_integer, &type_integer, 0},
|
||||
|
@ -372,6 +425,7 @@ static expr_type_t short_uinteger[] = {
|
|||
{'|', &type_uinteger, &type_uinteger, 0},
|
||||
{'^', &type_uinteger, &type_uinteger, 0},
|
||||
{'%', &type_uinteger, &type_uinteger, 0},
|
||||
{MOD, &type_uinteger, &type_uinteger, 0},
|
||||
{SHL, &type_short},
|
||||
{SHR, &type_short},
|
||||
{EQ, &type_integer, &type_uinteger, 0},
|
||||
|
@ -392,6 +446,7 @@ static expr_type_t short_short[] = {
|
|||
{'|', &type_short},
|
||||
{'^', &type_short},
|
||||
{'%', &type_short},
|
||||
{MOD, &type_short},
|
||||
{SHL, &type_short},
|
||||
{SHR, &type_short},
|
||||
{EQ, &type_integer},
|
||||
|
@ -402,8 +457,69 @@ static expr_type_t short_short[] = {
|
|||
{GT, &type_integer},
|
||||
{0, 0}
|
||||
};
|
||||
#define short_double integer_double
|
||||
|
||||
static expr_type_t *string_x[] = {
|
||||
static expr_type_t double_float[] = {
|
||||
{'+', &type_double, 0, &type_double},
|
||||
{'-', &type_double, 0, &type_double},
|
||||
{'*', &type_double, 0, &type_double},
|
||||
{'/', &type_double, 0, &type_double},
|
||||
{'%', &type_double, 0, &type_double},
|
||||
{MOD, &type_double, 0, &type_double},
|
||||
{EQ, 0, 0, 0, double_compare},
|
||||
{NE, 0, 0, 0, double_compare},
|
||||
{LE, 0, 0, 0, double_compare},
|
||||
{GE, 0, 0, 0, double_compare},
|
||||
{LT, 0, 0, 0, double_compare},
|
||||
{GT, 0, 0, 0, double_compare},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
static expr_type_t double_vector[] = {
|
||||
{'*', &type_vector},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
static expr_type_t double_quat[] = {
|
||||
{'*', &type_quaternion},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
static expr_type_t double_integer[] = {
|
||||
{'+', &type_double, 0, &type_double},
|
||||
{'-', &type_double, 0, &type_double},
|
||||
{'*', &type_double, 0, &type_double},
|
||||
{'/', &type_double, 0, &type_double},
|
||||
{'%', &type_double, 0, &type_double},
|
||||
{MOD, &type_double, 0, &type_double},
|
||||
{EQ, 0, 0, 0, double_compare},
|
||||
{NE, 0, 0, 0, double_compare},
|
||||
{LE, 0, 0, 0, double_compare},
|
||||
{GE, 0, 0, 0, double_compare},
|
||||
{LT, 0, 0, 0, double_compare},
|
||||
{GT, 0, 0, 0, double_compare},
|
||||
{0, 0}
|
||||
};
|
||||
#define double_uinteger double_integer
|
||||
#define double_short double_integer
|
||||
|
||||
static expr_type_t double_double[] = {
|
||||
{'+', &type_double},
|
||||
{'-', &type_double},
|
||||
{'*', &type_double},
|
||||
{'/', &type_double},
|
||||
{'%', &type_double},
|
||||
{MOD, &type_double},
|
||||
{EQ, &type_integer},
|
||||
{NE, &type_integer},
|
||||
{LE, &type_integer},
|
||||
{GE, &type_integer},
|
||||
{LT, &type_integer},
|
||||
{GT, &type_integer},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
static expr_type_t *string_x[ev_type_count] = {
|
||||
0, // ev_void
|
||||
string_string,
|
||||
0, // ev_float
|
||||
|
@ -416,9 +532,10 @@ static expr_type_t *string_x[] = {
|
|||
0, // ev_integer
|
||||
0, // ev_uinteger
|
||||
0, // ev_short
|
||||
0, // ev_double
|
||||
};
|
||||
|
||||
static expr_type_t *float_x[] = {
|
||||
static expr_type_t *float_x[ev_type_count] = {
|
||||
0, // ev_void
|
||||
0, // ev_string
|
||||
float_float,
|
||||
|
@ -431,9 +548,10 @@ static expr_type_t *float_x[] = {
|
|||
float_integer,
|
||||
float_uinteger,
|
||||
float_short,
|
||||
float_double,
|
||||
};
|
||||
|
||||
static expr_type_t *vector_x[] = {
|
||||
static expr_type_t *vector_x[ev_type_count] = {
|
||||
0, // ev_void
|
||||
0, // ev_string
|
||||
vector_float,
|
||||
|
@ -446,9 +564,10 @@ static expr_type_t *vector_x[] = {
|
|||
vector_integer,
|
||||
vector_uinteger,
|
||||
vector_short,
|
||||
vector_double,
|
||||
};
|
||||
|
||||
static expr_type_t *entity_x[] = {
|
||||
static expr_type_t *entity_x[ev_type_count] = {
|
||||
0, // ev_void
|
||||
0, // ev_string
|
||||
0, // ev_float
|
||||
|
@ -461,9 +580,10 @@ static expr_type_t *entity_x[] = {
|
|||
0, // ev_integer
|
||||
0, // ev_uinteger
|
||||
0, // ev_short
|
||||
0, // ev_double
|
||||
};
|
||||
|
||||
static expr_type_t *field_x[] = {
|
||||
static expr_type_t *field_x[ev_type_count] = {
|
||||
0, // ev_void
|
||||
0, // ev_string
|
||||
0, // ev_float
|
||||
|
@ -476,9 +596,10 @@ static expr_type_t *field_x[] = {
|
|||
0, // ev_integer
|
||||
0, // ev_uinteger
|
||||
0, // ev_short
|
||||
0, // ev_double
|
||||
};
|
||||
|
||||
static expr_type_t *funcx[] = {
|
||||
static expr_type_t *func_x[ev_type_count] = {
|
||||
0, // ev_void
|
||||
0, // ev_string
|
||||
0, // ev_float
|
||||
|
@ -491,9 +612,10 @@ static expr_type_t *funcx[] = {
|
|||
0, // ev_integer
|
||||
0, // ev_uinteger
|
||||
0, // ev_short
|
||||
0, // ev_double
|
||||
};
|
||||
|
||||
static expr_type_t *pointer_x[] = {
|
||||
static expr_type_t *pointer_x[ev_type_count] = {
|
||||
0, // ev_void
|
||||
0, // ev_string
|
||||
0, // ev_float
|
||||
|
@ -506,9 +628,10 @@ static expr_type_t *pointer_x[] = {
|
|||
pointer_integer,
|
||||
pointer_uinteger,
|
||||
pointer_short,
|
||||
0, // ev_double
|
||||
};
|
||||
|
||||
static expr_type_t *quat_x[] = {
|
||||
static expr_type_t *quat_x[ev_type_count] = {
|
||||
0, // ev_void
|
||||
0, // ev_string
|
||||
quat_float,
|
||||
|
@ -521,9 +644,10 @@ static expr_type_t *quat_x[] = {
|
|||
quat_integer,
|
||||
quat_uinteger,
|
||||
quat_short,
|
||||
quat_double,
|
||||
};
|
||||
|
||||
static expr_type_t *integer_x[] = {
|
||||
static expr_type_t *integer_x[ev_type_count] = {
|
||||
0, // ev_void
|
||||
0, // ev_string
|
||||
integer_float,
|
||||
|
@ -536,9 +660,10 @@ static expr_type_t *integer_x[] = {
|
|||
integer_integer,
|
||||
integer_uinteger,
|
||||
integer_short,
|
||||
integer_double,
|
||||
};
|
||||
|
||||
static expr_type_t *uinteger_x[] = {
|
||||
static expr_type_t *uinteger_x[ev_type_count] = {
|
||||
0, // ev_void
|
||||
0, // ev_string
|
||||
uinteger_float,
|
||||
|
@ -551,9 +676,10 @@ static expr_type_t *uinteger_x[] = {
|
|||
uinteger_integer,
|
||||
uinteger_uinteger,
|
||||
uinteger_short,
|
||||
uinteger_double,
|
||||
};
|
||||
|
||||
static expr_type_t *short_x[] = {
|
||||
static expr_type_t *short_x[ev_type_count] = {
|
||||
0, // ev_void
|
||||
0, // ev_string
|
||||
short_float,
|
||||
|
@ -566,21 +692,39 @@ static expr_type_t *short_x[] = {
|
|||
short_integer,
|
||||
short_uinteger,
|
||||
short_short,
|
||||
short_double,
|
||||
};
|
||||
|
||||
static expr_type_t **binary_expr_types[] = {
|
||||
static expr_type_t *double_x[ev_type_count] = {
|
||||
0, // ev_void
|
||||
0, // ev_string
|
||||
double_float,
|
||||
double_vector,
|
||||
0, // ev_entity
|
||||
0, // ev_field
|
||||
0, // ev_func
|
||||
0, // ev_pointer
|
||||
double_quat,
|
||||
double_integer,
|
||||
double_uinteger,
|
||||
double_short,
|
||||
double_double,
|
||||
};
|
||||
|
||||
static expr_type_t **binary_expr_types[ev_type_count] = {
|
||||
0, // ev_void
|
||||
string_x,
|
||||
float_x,
|
||||
vector_x,
|
||||
entity_x,
|
||||
field_x,
|
||||
funcx,
|
||||
func_x,
|
||||
pointer_x,
|
||||
quat_x,
|
||||
integer_x,
|
||||
uinteger_x,
|
||||
short_x,
|
||||
double_x
|
||||
};
|
||||
|
||||
static expr_t *
|
||||
|
@ -611,6 +755,36 @@ inverse_multiply (int op, expr_t *e1, expr_t *e2)
|
|||
return binary_expr ('*', e1, binary_expr ('/', one, e2));
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
double_compare (int op, expr_t *e1, expr_t *e2)
|
||||
{
|
||||
type_t *t1 = get_type (e1);
|
||||
type_t *t2 = get_type (e2);
|
||||
expr_t *e;
|
||||
|
||||
if ((is_double (t1) && is_float (t2))
|
||||
|| (is_float (t1) && is_double (t2))) {
|
||||
}
|
||||
if (is_double (t1)) {
|
||||
if (is_float (t2)) {
|
||||
warning (e2, "comparison between double and float");
|
||||
} else if (!is_constant (e2)) {
|
||||
warning (e2, "comparison between double and integer");
|
||||
}
|
||||
e2 = cast_expr (&type_double, e2);
|
||||
} else {
|
||||
if (is_float (t1)) {
|
||||
warning (e1, "comparison between float and double");
|
||||
} else if (!is_constant (e1)) {
|
||||
warning (e1, "comparison between integer and double");
|
||||
}
|
||||
e1 = cast_expr (&type_double, e1);
|
||||
}
|
||||
e = new_binary_expr (op, e1, e2);
|
||||
e->e.expr.type = &type_double;
|
||||
return e;
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
invalid_binary_expr (int op, expr_t *e1, expr_t *e2)
|
||||
{
|
||||
|
@ -630,32 +804,14 @@ reimplement_binary_expr (int op, expr_t *e1, expr_t *e2)
|
|||
switch (op) {
|
||||
case '%':
|
||||
{
|
||||
expr_t *tmp1, *tmp2, *tmp3, *tmp4, *t1, *t2;
|
||||
expr_t *tmp1, *tmp2;
|
||||
e = new_block_expr ();
|
||||
t1 = new_temp_def_expr (&type_float);
|
||||
t2 = new_temp_def_expr (&type_float);
|
||||
tmp1 = new_temp_def_expr (&type_float);
|
||||
tmp2 = new_temp_def_expr (&type_float);
|
||||
tmp3 = new_temp_def_expr (&type_float);
|
||||
tmp4 = new_temp_def_expr (&type_float);
|
||||
|
||||
append_expr (e, assign_expr (t1, e1));
|
||||
e1 = binary_expr ('&', t1, t1);
|
||||
append_expr (e, assign_expr (tmp1, e1));
|
||||
|
||||
append_expr (e, assign_expr (t2, e2));
|
||||
e2 = binary_expr ('&', t2, t2);
|
||||
append_expr (e, assign_expr (tmp2, e2));
|
||||
|
||||
e1 = binary_expr ('/', tmp1, tmp2);
|
||||
append_expr (e, assign_expr (tmp3, e1));
|
||||
|
||||
e2 = binary_expr ('&', tmp3, tmp3);
|
||||
append_expr (e, assign_expr (tmp4, e2));
|
||||
|
||||
e1 = binary_expr ('*', tmp2, tmp4);
|
||||
e2 = binary_expr ('-', tmp1, e1);
|
||||
e->e.block.result = e2;
|
||||
append_expr (e, assign_expr (tmp1, binary_expr ('/', e1, e2)));
|
||||
append_expr (e, assign_expr (tmp2, binary_expr ('&', tmp1, tmp1)));
|
||||
e->e.block.result = binary_expr ('-', e1, binary_expr ('*', e2, tmp2));
|
||||
return e;
|
||||
}
|
||||
break;
|
||||
|
@ -798,9 +954,9 @@ binary_expr (int op, expr_t *e1, expr_t *e2)
|
|||
et1 = low_level_type (t1);
|
||||
et2 = low_level_type (t2);
|
||||
|
||||
if (et1 > ev_short || !binary_expr_types[et1])
|
||||
if (et1 >= ev_type_count || !binary_expr_types[et1])
|
||||
return invalid_binary_expr(op, e1, e2);
|
||||
if (et2 > ev_short || !binary_expr_types[et1][et2])
|
||||
if (et2 >= ev_type_count || !binary_expr_types[et1][et2])
|
||||
return invalid_binary_expr(op, e1, e2);
|
||||
expr_type = binary_expr_types[et1][et2];
|
||||
while (expr_type->op && expr_type->op != op)
|
||||
|
|
|
@ -158,6 +158,7 @@ parse_params (type_t *type, param_t *parms)
|
|||
|
||||
new = new_type ();
|
||||
new->type = ev_func;
|
||||
new->alignment = 1;
|
||||
new->t.func.type = type;
|
||||
new->t.func.num_params = 0;
|
||||
|
||||
|
@ -339,8 +340,11 @@ find_function (expr_t *fexpr, expr_t *params)
|
|||
for (func_count = 0; funcs[func_count]; func_count++)
|
||||
;
|
||||
if (func_count < 2) {
|
||||
free (funcs);
|
||||
return fexpr;
|
||||
f = (overloaded_function_t *) funcs[0];
|
||||
if (func_count && !f->overloaded) {
|
||||
free (funcs);
|
||||
return fexpr;
|
||||
}
|
||||
}
|
||||
type.t.func.type = ((overloaded_function_t *) funcs[0])->type->t.func.type;
|
||||
dummy.type = find_type (&type);
|
||||
|
|
|
@ -665,7 +665,7 @@ get_def_type (qfo_t *qfo, pointer_t type)
|
|||
return ev_invalid;
|
||||
}
|
||||
|
||||
static __attribute__((pure)) etype_t
|
||||
static __attribute__((pure)) int
|
||||
get_type_size (qfo_t *qfo, pointer_t type)
|
||||
{
|
||||
qfot_type_t *type_def;
|
||||
|
@ -701,6 +701,62 @@ get_type_size (qfo_t *qfo, pointer_t type)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
qfo_log2 (unsigned x)
|
||||
{
|
||||
int log2 = 0;
|
||||
|
||||
while (x > 1) {
|
||||
x >>= 1;
|
||||
log2++;
|
||||
}
|
||||
return log2;
|
||||
}
|
||||
|
||||
static __attribute__((pure)) int
|
||||
get_type_alignment_log (qfo_t *qfo, pointer_t type)
|
||||
{
|
||||
qfot_type_t *type_def;
|
||||
int i, alignment;
|
||||
if (type >= qfo->spaces[qfo_type_space].data_size)
|
||||
return 0;
|
||||
type_def = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, type);
|
||||
switch ((ty_meta_e)type_def->meta) {
|
||||
case ty_none:
|
||||
// field, pointer and function types store their basic type in
|
||||
// the same location.
|
||||
return qfo_log2 (ev_types[type_def->t.type]->alignment);
|
||||
case ty_struct:
|
||||
case ty_union:
|
||||
for (i = alignment = 0; i < type_def->t.strct.num_fields; i++) {
|
||||
qfot_var_t *field = type_def->t.strct.fields + i;
|
||||
int a;
|
||||
a = get_type_alignment_log (qfo, field->type);
|
||||
if (a > alignment) {
|
||||
alignment = a;
|
||||
}
|
||||
}
|
||||
return alignment;
|
||||
case ty_enum:
|
||||
return qfo_log2 (ev_types[ev_integer]->alignment);
|
||||
case ty_array:
|
||||
return get_type_alignment_log (qfo, type_def->t.array.type);
|
||||
case ty_class:
|
||||
return 0; // FIXME
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __attribute__((pure)) dparmsize_t
|
||||
get_parmsize (qfo_t *qfo, pointer_t type)
|
||||
{
|
||||
dparmsize_t parmsize = {
|
||||
get_type_size (qfo, type),
|
||||
get_type_alignment_log (qfo, type),
|
||||
};
|
||||
return parmsize;
|
||||
}
|
||||
|
||||
static void
|
||||
function_params (qfo_t *qfo, qfo_func_t *func, dfunction_t *df)
|
||||
{
|
||||
|
@ -716,8 +772,9 @@ function_params (qfo_t *qfo, qfo_func_t *func, dfunction_t *df)
|
|||
df->numparms = num_params = type->t.func.num_params;
|
||||
if (num_params < 0)
|
||||
num_params = ~num_params;
|
||||
for (i = 0; i < num_params; i++)
|
||||
df->parm_size[i] = get_type_size (qfo, type->t.func.param_types[i]);
|
||||
for (i = 0; i < num_params; i++) {
|
||||
df->parm_size[i] = get_parmsize (qfo, type->t.func.param_types[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -795,6 +852,14 @@ qfo_relocate_refs (qfo_t *qfo)
|
|||
}
|
||||
}
|
||||
|
||||
static unsigned
|
||||
align_globals_size (unsigned size)
|
||||
{
|
||||
if (options.code.progsversion == PROG_ID_VERSION)
|
||||
return size;
|
||||
return RUP (size, 16 / sizeof (pr_type_t));
|
||||
}
|
||||
|
||||
dprograms_t *
|
||||
qfo_to_progs (qfo_t *qfo, int *size)
|
||||
{
|
||||
|
@ -811,6 +876,7 @@ qfo_to_progs (qfo_t *qfo, int *size)
|
|||
dprograms_t *progs;
|
||||
qfo_def_t *types_def = 0;
|
||||
unsigned i, j;
|
||||
unsigned near_data_size = 0;
|
||||
unsigned locals_size = 0;
|
||||
int locals_start;
|
||||
unsigned big_locals = 0;
|
||||
|
@ -827,9 +893,8 @@ qfo_to_progs (qfo_t *qfo, int *size)
|
|||
progs->numfunctions = qfo->num_funcs + 1;
|
||||
progs->numstrings = qfo->spaces[qfo_strings_space].data_size;
|
||||
progs->numglobals = qfo->spaces[qfo_near_data_space].data_size;
|
||||
progs->numglobals += qfo->spaces[qfo_far_data_space].data_size;
|
||||
progs->numglobals += qfo->spaces[qfo_type_space].data_size;
|
||||
locals_start = qfo->spaces[qfo_near_data_space].data_size;
|
||||
progs->numglobals = align_globals_size (progs->numglobals);
|
||||
locals_start = progs->numglobals;
|
||||
for (i = qfo_num_spaces; i < qfo->num_spaces; i++) {
|
||||
if (options.code.local_merging) {
|
||||
if (locals_size < qfo->spaces[i].data_size) {
|
||||
|
@ -837,11 +902,14 @@ qfo_to_progs (qfo_t *qfo, int *size)
|
|||
big_locals = i;
|
||||
}
|
||||
} else {
|
||||
locals_size += qfo->spaces[i].data_size;
|
||||
locals_size += align_globals_size (qfo->spaces[i].data_size);
|
||||
}
|
||||
}
|
||||
progs->numglobals += locals_size;
|
||||
near_data_size = progs->numglobals;
|
||||
progs->numglobals = RUP (progs->numglobals, 16 / sizeof (pr_type_t));
|
||||
progs->numglobals += qfo->spaces[qfo_far_data_space].data_size;
|
||||
progs->numglobals += qfo->spaces[qfo_type_space].data_size;
|
||||
progs->entityfields = qfo->spaces[qfo_entity_space].data_size;
|
||||
*size += progs->numstatements * sizeof (dstatement_t);
|
||||
*size += progs->numglobaldefs * sizeof (ddef_t);
|
||||
|
@ -878,8 +946,8 @@ qfo_to_progs (qfo_t *qfo, int *size)
|
|||
|
||||
progs->ofs_globals = data - (byte *) progs;
|
||||
globals = (pr_type_t*) data;
|
||||
locals = globals + qfo->spaces[qfo_near_data_space].data_size;
|
||||
far_data = locals + locals_size;
|
||||
locals = globals + locals_start;
|
||||
far_data = globals + near_data_size;
|
||||
type_data = far_data + qfo->spaces[qfo_far_data_space].data_size;
|
||||
|
||||
memcpy (strings, qfo->spaces[qfo_strings_space].d.strings,
|
||||
|
@ -902,7 +970,7 @@ qfo_to_progs (qfo_t *qfo, int *size)
|
|||
for (j = 0; j < space->num_defs; j++)
|
||||
space->defs[j].offset += locals_start;
|
||||
if (!options.code.local_merging)
|
||||
locals_start += df->locals;
|
||||
locals_start += align_globals_size (df->locals);
|
||||
df->profile = 0;
|
||||
df->s_name = qf->name;
|
||||
df->s_file = qf->file;
|
||||
|
@ -936,7 +1004,7 @@ qfo_to_progs (qfo_t *qfo, int *size)
|
|||
memcpy (globals, qfo->spaces[qfo_near_data_space].d.data,
|
||||
qfo->spaces[qfo_near_data_space].data_size * sizeof (pr_type_t));
|
||||
qfo->spaces[qfo_near_data_space].d.data = globals;
|
||||
// lcear locals data
|
||||
// clear locals data
|
||||
memset (locals, 0, locals_size * sizeof (pr_type_t));
|
||||
// copy far data
|
||||
memcpy (far_data, qfo->spaces[qfo_far_data_space].d.data,
|
||||
|
@ -978,8 +1046,7 @@ qfo_to_progs (qfo_t *qfo, int *size)
|
|||
printf ("%6i global defs\n", progs->numglobaldefs);
|
||||
printf ("%6i fielddefs\n", progs->numfielddefs);
|
||||
printf ("%6i globals\n", progs->numglobals);
|
||||
printf (" %6i near globals\n",
|
||||
qfo->spaces[qfo_near_data_space].data_size + locals_size);
|
||||
printf (" %6i near globals\n", near_data_size);
|
||||
printf (" %6i locals size%s\n", locals_size, big_function);
|
||||
printf (" %6i far globals\n",
|
||||
qfo->spaces[qfo_far_data_space].data_size);
|
||||
|
|
|
@ -69,11 +69,13 @@ enum {
|
|||
OPT_PROGDEFS,
|
||||
OPT_QCCX_ESCAPES,
|
||||
OPT_TRADITIONAL,
|
||||
OPT_BUG,
|
||||
};
|
||||
|
||||
static struct option const long_options[] = {
|
||||
{"advanced", no_argument, 0, OPT_ADVANCED},
|
||||
{"block-dot", optional_argument, 0, OPT_BLOCK_DOT},
|
||||
{"bug", required_argument, 0, OPT_BUG},
|
||||
{"code", required_argument, 0, 'C'},
|
||||
{"cpp", required_argument, 0, OPT_CPP},
|
||||
{"define", required_argument, 0, 'D'},
|
||||
|
@ -139,6 +141,7 @@ usage (int status)
|
|||
"Options:\n"
|
||||
" --advanced Advanced Ruamoko mode\n"
|
||||
" default for separate compilation mode\n"
|
||||
" --bug OPTION,... Set bug options\n"
|
||||
" -C, --code OPTION,... Set code generation options\n"
|
||||
" -c Only compile, don't link\n"
|
||||
" --cpp CPPSPEC cpp execution command line\n"
|
||||
|
@ -264,6 +267,21 @@ notice_usage (void)
|
|||
exit (0);
|
||||
}
|
||||
|
||||
static void
|
||||
bug_usage (void)
|
||||
{
|
||||
printf ("%s - QuakeForge Code Compiler\n", this_program);
|
||||
printf ("Bug options\n");
|
||||
printf (
|
||||
" help Display his text.\n"
|
||||
" none Turn off all bugs (don't we wish: messages).\n"
|
||||
" die Change bugs to internal errors.\n"
|
||||
"\n"
|
||||
"This is a developer feature and thus not in the manual page\n"
|
||||
);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
static void
|
||||
add_file (const char *file)
|
||||
{
|
||||
|
@ -590,6 +608,23 @@ DecodeArgs (int argc, char **argv)
|
|||
free (opts);
|
||||
}
|
||||
break;
|
||||
case OPT_BUG:{
|
||||
char *opts = strdup (optarg);
|
||||
char *temp = strtok (opts, ",");
|
||||
|
||||
while (temp) {
|
||||
if (!strcasecmp (temp, "help")) {
|
||||
bug_usage ();
|
||||
} else if (!(strcasecmp (temp, "none"))) {
|
||||
options.bug.silent = true;
|
||||
} else if (!(strcasecmp (temp, "die"))) {
|
||||
options.bug.promote = true;
|
||||
}
|
||||
temp = strtok (NULL, ",");
|
||||
}
|
||||
free (opts);
|
||||
}
|
||||
break;
|
||||
case OPT_CPP: // --cpp=
|
||||
cpp_name = save_string (optarg);
|
||||
break;
|
||||
|
|
|
@ -39,14 +39,25 @@
|
|||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "QF/alloc.h"
|
||||
#include "QF/pr_comp.h"
|
||||
|
||||
#include "diagnostic.h"
|
||||
#include "opcodes.h"
|
||||
#include "options.h"
|
||||
#include "pragma.h"
|
||||
#include "strpool.h"
|
||||
#include "type.h"
|
||||
|
||||
typedef struct pragma_arg_s {
|
||||
struct pragma_arg_s *next;
|
||||
const char *arg;
|
||||
} pragma_arg_t;
|
||||
|
||||
static pragma_arg_t *pragma_args_freelist;
|
||||
static pragma_arg_t *pragma_args;
|
||||
static pragma_arg_t **pragma_args_tail = &pragma_args;
|
||||
|
||||
static void
|
||||
set_traditional (int traditional)
|
||||
{
|
||||
|
@ -73,20 +84,58 @@ set_traditional (int traditional)
|
|||
opcode_init (); // reset the opcode table
|
||||
}
|
||||
|
||||
void
|
||||
pragma (const char *id)
|
||||
static void
|
||||
set_bug (pragma_arg_t *args)
|
||||
{
|
||||
if (!args) {
|
||||
warning (0, "missing bug flag");
|
||||
return;
|
||||
}
|
||||
const char *flag = args->arg;
|
||||
if (!strcmp (flag, "none")) {
|
||||
options.bug.silent = true;
|
||||
} else if (!strcmp (flag, "!none")) {
|
||||
options.bug.silent = false;
|
||||
} else if (!strcmp (flag, "die")) {
|
||||
options.bug.promote = true;
|
||||
} else if (!strcmp (flag, "!die")) {
|
||||
options.bug.promote = false;
|
||||
}
|
||||
if (args->next) {
|
||||
warning (0, "pragma bug: ignoring extra arguments");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pragma_process ()
|
||||
{
|
||||
if (!pragma_args) {
|
||||
warning (0, "empty pragma");
|
||||
return;
|
||||
}
|
||||
const char *id = pragma_args->arg;
|
||||
if (!strcmp (id, "traditional")) {
|
||||
set_traditional (2);
|
||||
return;
|
||||
}
|
||||
if (!strcmp (id, "extended")) {
|
||||
} else if (!strcmp (id, "extended")) {
|
||||
set_traditional (1);
|
||||
return;
|
||||
}
|
||||
if (!strcmp (id, "advanced")) {
|
||||
} else if (!strcmp (id, "advanced")) {
|
||||
set_traditional (0);
|
||||
return;
|
||||
} else if (!strcmp (id, "bug")) {
|
||||
set_bug (pragma_args->next);
|
||||
} else {
|
||||
warning (0, "unknown pragma: '%s'", id);
|
||||
}
|
||||
warning (0, "unknown pragma: %s", id);
|
||||
*pragma_args_tail = pragma_args_freelist;
|
||||
pragma_args_tail = &pragma_args;
|
||||
pragma_args = 0;
|
||||
}
|
||||
|
||||
void
|
||||
pragma_add_arg (const char *id)
|
||||
{
|
||||
pragma_arg_t *arg;
|
||||
ALLOC (16, pragma_arg_t, pragma_args, arg);
|
||||
arg->arg = save_string (id);
|
||||
*pragma_args_tail = arg;
|
||||
pragma_args_tail = &arg->next;
|
||||
}
|
||||
|
|
|
@ -93,6 +93,8 @@ B [01]
|
|||
X [0-9a-fA-F]
|
||||
ID [a-zA-Z_][a-zA-Z_0-9]*
|
||||
FLOAT ({D}+|{D}*\.{D}+|{D}+\.{D}*)([eE]{m}?{D}+)?
|
||||
FLOATf {FLOAT}[fF]
|
||||
FLOATd {FLOAT}[dD]
|
||||
INT ({D}+|0[xX]{X}+|0[bB]{B})
|
||||
RANGE \.\.
|
||||
ELLIPSIS \.\.\.
|
||||
|
@ -136,10 +138,35 @@ STRING \"(\\.|[^"\\])*\"
|
|||
}
|
||||
|
||||
{FLOAT} {
|
||||
// advanced code defaults to double, but traditional
|
||||
// and extended code defaults to float
|
||||
if (options.traditional < 1) {
|
||||
double d = strtod (yytext, 0);
|
||||
qc_yylval.expr = new_double_expr (d);
|
||||
} else {
|
||||
float f = strtof (yytext, 0);
|
||||
qc_yylval.expr = new_float_expr (f);
|
||||
}
|
||||
return VALUE;
|
||||
}
|
||||
{FLOATf} {
|
||||
float f = strtof (yytext, 0);
|
||||
qc_yylval.expr = new_float_expr (f);
|
||||
return VALUE;
|
||||
}
|
||||
{FLOATd} {
|
||||
// advanced code defaults to double, but traditional
|
||||
// and extended code defaults to float
|
||||
if (options.traditional < 1) {
|
||||
double d = strtod (yytext, 0);
|
||||
qc_yylval.expr = new_double_expr (d);
|
||||
} else {
|
||||
float f = strtof (yytext, 0);
|
||||
qc_yylval.expr = new_float_expr (f);
|
||||
warning (0, "truncating double constant to float");
|
||||
}
|
||||
return VALUE;
|
||||
}
|
||||
|
||||
{ID} {
|
||||
int tok = keyword_or_id(yytext);
|
||||
|
@ -189,6 +216,11 @@ STRING \"(\\.|[^"\\])*\"
|
|||
return ASX;
|
||||
}
|
||||
|
||||
"%%=" {
|
||||
qc_yylval.op = MOD;
|
||||
return ASX;
|
||||
}
|
||||
|
||||
"<<=" {
|
||||
qc_yylval.op = SHL;
|
||||
return ASX;
|
||||
|
@ -204,6 +236,11 @@ STRING \"(\\.|[^"\\])*\"
|
|||
return yytext[0];
|
||||
}
|
||||
|
||||
"%%" {
|
||||
qc_yylval.pointer = 0; // ensure pointer vals are null
|
||||
return MOD;
|
||||
}
|
||||
|
||||
{ELLIPSIS} return ELLIPSIS;
|
||||
|
||||
"<<" return SHL;
|
||||
|
@ -245,9 +282,12 @@ STRING \"(\\.|[^"\\])*\"
|
|||
write_frame_macros (s);
|
||||
BEGIN (GRAB_OTHER); // ignore rest of line
|
||||
}
|
||||
<PRAGMA>{ID} { pragma (yytext); }
|
||||
<PRAGMA>{ID} { pragma_add_arg (yytext); }
|
||||
|
||||
<*>\r*\n {
|
||||
if (YY_START == PRAGMA) {
|
||||
pragma_process ();
|
||||
}
|
||||
pr.source_line++;
|
||||
BEGIN (INITIAL);
|
||||
}
|
||||
|
@ -333,6 +373,7 @@ static keyword_t at_keywords[] = {
|
|||
// be supported (sanely) by v6 progs.
|
||||
static keyword_t qf_keywords[] = {
|
||||
{"quaternion", TYPE, &type_quaternion},
|
||||
{"double", TYPE, &type_double},
|
||||
{"int", TYPE, &type_integer },
|
||||
{"unsigned", TYPE, &type_integer },//FIXME
|
||||
{"function", TYPE, &type_function },
|
||||
|
|
|
@ -135,7 +135,7 @@ int yylex (void);
|
|||
|
||||
%left SHL SHR
|
||||
%left '+' '-'
|
||||
%left '*' '/' '%'
|
||||
%left '*' '/' '%' MOD
|
||||
%right <op> SIZEOF UNARY INCOP
|
||||
%left HYPERUNARY
|
||||
%left '.' '(' '['
|
||||
|
@ -1335,6 +1335,7 @@ expr
|
|||
| expr '|' expr { $$ = binary_expr ('|', $1, $3); }
|
||||
| expr '^' expr { $$ = binary_expr ('^', $1, $3); }
|
||||
| expr '%' expr { $$ = binary_expr ('%', $1, $3); }
|
||||
| expr MOD expr { $$ = binary_expr (MOD, $1, $3); }
|
||||
;
|
||||
|
||||
texpr
|
||||
|
|
|
@ -418,8 +418,11 @@ finish_link (void)
|
|||
flags = (QFOD_GLOBAL | QFOD_CONSTANT | QFOD_INITIALIZED | QFOD_NOSAVE);
|
||||
if (options.code.progsversion != PROG_ID_VERSION) {
|
||||
pr_int_t param_size = type_size (&type_param);
|
||||
pr_int_t param_alignment = qfo_log2 (type_param.alignment);
|
||||
linker_add_def (".param_size", &type_integer, flags,
|
||||
¶m_size);
|
||||
linker_add_def (".param_alignment", &type_integer, flags,
|
||||
¶m_alignment);
|
||||
}
|
||||
|
||||
if (options.code.debug) {
|
||||
|
|
|
@ -87,6 +87,8 @@ operand_string (operand_t *op)
|
|||
case ev_string:
|
||||
return va ("\"%s\"",
|
||||
quote_string (op->o.value->v.string_val));
|
||||
case ev_double:
|
||||
return va ("%g", op->o.value->v.double_val);
|
||||
case ev_float:
|
||||
return va ("%g", op->o.value->v.float_val);
|
||||
case ev_vector:
|
||||
|
@ -159,6 +161,9 @@ print_operand (operand_t *op)
|
|||
case ev_string:
|
||||
printf ("\"%s\"", op->o.value->v.string_val);
|
||||
break;
|
||||
case ev_double:
|
||||
printf ("%g", op->o.value->v.double_val);
|
||||
break;
|
||||
case ev_float:
|
||||
printf ("%g", op->o.value->v.float_val);
|
||||
break;
|
||||
|
@ -313,6 +318,15 @@ def_operand (def_t *def, type_t *type)
|
|||
return op;
|
||||
}
|
||||
|
||||
operand_t *
|
||||
return_operand (type_t *type)
|
||||
{
|
||||
symbol_t *return_symbol;
|
||||
return_symbol = make_symbol (".return", &type_param, pr.symtab->space,
|
||||
sc_extern);
|
||||
return def_operand (return_symbol->s.def, type);
|
||||
}
|
||||
|
||||
operand_t *
|
||||
value_operand (ex_value_t *value)
|
||||
{
|
||||
|
@ -389,7 +403,7 @@ alias_operand (type_t *type, operand_t *op)
|
|||
operand_t *aop;
|
||||
|
||||
if (type_size (type) != type_size (op->type)) {
|
||||
internal_error (0, "\naliasing operand with type of diffent size"
|
||||
internal_error (0, "\naliasing operand with type of different size"
|
||||
" (%d, %d)", type_size (type), type_size (op->type));
|
||||
}
|
||||
aop = new_operand (op_alias);
|
||||
|
@ -425,6 +439,7 @@ convert_op (int op)
|
|||
case '*': return "*";
|
||||
case '/': return "/";
|
||||
case '%': return "%";
|
||||
case MOD: return "%%";
|
||||
case '&': return "&";
|
||||
case '|': return "|";
|
||||
case '^': return "^";
|
||||
|
@ -901,6 +916,8 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op)
|
|||
while (def->alias)
|
||||
def = def->alias;
|
||||
*op = def_operand (alias_def (def, type, offset), 0);
|
||||
} else if (aop->op_type == op_value) {
|
||||
*op = value_operand (aop->o.value);
|
||||
} else {
|
||||
internal_error (e, "invalid alias target: %s: %s",
|
||||
optype_str (aop->op_type), operand_string (aop));
|
||||
|
@ -953,8 +970,7 @@ expr_cast (sblock_t *sblock, expr_t *e, operand_t **op)
|
|||
statement_t *s;
|
||||
|
||||
src_type = get_type (e->e.expr.e1);
|
||||
if ((src_type->type == ev_integer && type->type == ev_float)
|
||||
|| (src_type->type == ev_float && type->type == ev_integer)) {
|
||||
if (is_scalar (src_type) && is_scalar (type)) {
|
||||
operand_t *src = 0;
|
||||
sblock = statement_subexpr (sblock, e->e.expr.e1, &src);
|
||||
*op = temp_operand (e->e.expr.type);
|
||||
|
@ -1381,8 +1397,10 @@ statement_uexpr (sblock_t *sblock, expr_t *e)
|
|||
}
|
||||
}
|
||||
s = new_statement (st_func, opcode, e);
|
||||
if (e->e.expr.e1)
|
||||
if (e->e.expr.e1) {
|
||||
s->opa = return_operand (get_type (e->e.expr.e1));
|
||||
sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa);
|
||||
}
|
||||
sblock_add_statement (sblock, s);
|
||||
sblock->next = new_sblock ();
|
||||
sblock = sblock->next;
|
||||
|
@ -1661,10 +1679,6 @@ static void
|
|||
check_final_block (sblock_t *sblock)
|
||||
{
|
||||
statement_t *s = 0;
|
||||
symbol_t *return_symbol = 0;
|
||||
def_t *return_def = 0;
|
||||
operand_t *return_operand = 0;
|
||||
const char *return_opcode = "<RETURN_V>";
|
||||
|
||||
if (!sblock)
|
||||
return;
|
||||
|
@ -1685,16 +1699,11 @@ check_final_block (sblock_t *sblock)
|
|||
sblock->next = new_sblock ();
|
||||
sblock = sblock->next;
|
||||
}
|
||||
s = new_statement (st_func, "<RETURN_V>", 0);
|
||||
if (options.traditional || options.code.progsversion == PROG_ID_VERSION) {
|
||||
return_symbol = make_symbol (".return", &type_param, pr.symtab->space,
|
||||
sc_extern);
|
||||
return_def = return_symbol->s.def;
|
||||
return_opcode = "<RETURN>";
|
||||
s->opcode = save_string ("<RETURN>");
|
||||
s->opa = return_operand (&type_void);
|
||||
}
|
||||
if (return_symbol)
|
||||
return_operand = def_operand (return_def, &type_void);
|
||||
s = new_statement (st_func, return_opcode, 0);
|
||||
s->opa = return_operand;
|
||||
sblock_add_statement (sblock, s);
|
||||
}
|
||||
|
||||
|
|
|
@ -112,6 +112,7 @@ build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type)
|
|||
{
|
||||
symbol_t *sym = find_struct (su, tag, type);
|
||||
symbol_t *s;
|
||||
int alignment = 1;
|
||||
|
||||
symtab->parent = 0; // disconnect struct's symtab from parent scope
|
||||
|
||||
|
@ -130,10 +131,14 @@ build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type)
|
|||
if (size > symtab->size)
|
||||
symtab->size = size;
|
||||
}
|
||||
if (s->type->alignment > alignment) {
|
||||
alignment = s->type->alignment;
|
||||
}
|
||||
}
|
||||
if (!type)
|
||||
sym->type = find_type (sym->type); // checks the tag, not the symtab
|
||||
sym->type->t.symtab = symtab;
|
||||
sym->type->alignment = alignment;
|
||||
if (!type && sym->type->type_def->external) //FIXME should not be necessary
|
||||
sym->type->type_def = qfo_encode_type (sym->type);
|
||||
return sym;
|
||||
|
@ -166,6 +171,7 @@ finish_enum (symbol_t *sym)
|
|||
|
||||
enum_type = sym->type = find_type (sym->type);
|
||||
enum_tab = enum_type->t.symtab;
|
||||
enum_type->alignment = 1;
|
||||
|
||||
for (name = enum_tab->symbols; name; name = name->next) {
|
||||
name->type = sym->type;
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "class.h"
|
||||
#include "codespace.h"
|
||||
#include "diagnostic.h"
|
||||
|
@ -12,9 +14,12 @@
|
|||
#include "expr.h"
|
||||
#include "function.h"
|
||||
#include "obj_file.h"
|
||||
#include "obj_type.h"
|
||||
#include "options.h"
|
||||
#include "qfcc.h"
|
||||
#include "strpool.h"
|
||||
#include "struct.h"
|
||||
#include "symtab.h"
|
||||
#include "type.h"
|
||||
#include "value.h"
|
||||
|
||||
|
@ -23,11 +28,22 @@ options_t options;
|
|||
int num_linenos;
|
||||
pr_lineno_t *linenos;
|
||||
pr_info_t pr;
|
||||
type_t type_Class;
|
||||
type_t type_SEL;
|
||||
type_t type_id;
|
||||
__attribute__((const)) string_t ReuseString (const char *str) {return 0;}
|
||||
void encode_type (struct dstring_s *str, const type_t *type) {}
|
||||
__attribute__((const)) codespace_t *codespace_new (void) {return 0;}
|
||||
void codespace_addcode (codespace_t *codespace, struct dstatement_s *code, int size) {}
|
||||
__attribute__((const)) int function_parms (function_t *f, byte *parm_size) {return 0;}
|
||||
void def_to_ddef (def_t *def, ddef_t *ddef, int aux) {}
|
||||
__attribute__((noreturn)) void _internal_error (expr_t *e, const char *file, int line, const char *fmt, ...) {abort();}
|
||||
__attribute__((const)) expr_t *_warning (expr_t *e, const char *file, int line, const char *fmt, ...) {return 0;}
|
||||
__attribute__((const)) expr_t *_error (expr_t *e, const char *file, int line, const char *fmt, ...) {return 0;}
|
||||
__attribute__((const)) symbol_t *make_structure (const char *name, int su, struct_def_t *defs, type_t *type) {return 0;}
|
||||
__attribute__((const)) symbol_t *symtab_addsymbol (symtab_t *symtab, symbol_t *symbol) {return 0;}
|
||||
__attribute__((const)) symbol_t *new_symbol_type (const char *name, type_t *type) {return 0;}
|
||||
__attribute__((const)) def_t *qfo_encode_type (type_t *type) {return 0;}
|
||||
__attribute__((const)) int obj_types_assignable (const type_t *dst, const type_t *src) {return 0;}
|
||||
void print_protocollist (struct dstring_s *dstr, protocollist_t *protocollist) {}
|
||||
int obj_is_id (const type_t *type){return type->type;}
|
||||
int compare_protocols (protocollist_t *protos1, protocollist_t *protos2){return protos1->count - protos2->count;}
|
||||
|
|
|
@ -63,30 +63,33 @@
|
|||
// simple types. function types are dynamically allocated
|
||||
type_t type_invalid = { ev_invalid, "invalid" };
|
||||
type_t type_void = { ev_void, "void" };
|
||||
type_t type_string = { ev_string, "string" };
|
||||
type_t type_float = { ev_float, "float" };
|
||||
type_t type_vector = { ev_vector, "vector" };
|
||||
type_t type_entity = { ev_entity, "entity" };
|
||||
type_t type_field = {ev_field, "field", ty_none, {{&type_void}} };
|
||||
type_t type_string = { ev_string, "string", 1 };
|
||||
type_t type_float = { ev_float, "float", 1 };
|
||||
type_t type_vector = { ev_vector, "vector", 1 };
|
||||
type_t type_entity = { ev_entity, "entity", 1 };
|
||||
type_t type_field = {ev_field, "field", 1, ty_none, {{&type_void}} };
|
||||
|
||||
// type_function is a void() function used for state defs
|
||||
type_t type_function = { ev_func, "function", ty_none, {{&type_void}} };
|
||||
type_t type_pointer = { ev_pointer, "pointer", ty_none, {{&type_void}} };
|
||||
type_t type_quaternion = { ev_quat, "quaternion" };
|
||||
type_t type_integer = { ev_integer, "int" };
|
||||
type_t type_uinteger = { ev_uinteger, "uint" };
|
||||
type_t type_short = { ev_short, "short" };
|
||||
type_t type_function = { ev_func, "function", 1, ty_none, {{&type_void}} };
|
||||
type_t type_pointer = { ev_pointer, "pointer", 1, ty_none, {{&type_void}} };
|
||||
type_t type_quaternion = { ev_quat, "quaternion", 1 };
|
||||
type_t type_integer = { ev_integer, "int", 1 };
|
||||
type_t type_uinteger = { ev_uinteger, "uint", 1 };
|
||||
type_t type_short = { ev_short, "short", 1 };
|
||||
type_t type_double = { ev_double, "double", 2 };
|
||||
|
||||
type_t *type_nil;
|
||||
type_t *type_default;
|
||||
|
||||
// these will be built up further
|
||||
type_t type_va_list = { ev_invalid, 0, ty_struct };
|
||||
type_t type_param = { ev_invalid, 0, ty_struct };
|
||||
type_t type_zero = { ev_invalid, 0, ty_struct };
|
||||
type_t type_type_encodings = { ev_invalid, "@type_encodings", ty_struct };
|
||||
type_t type_va_list = { ev_invalid, 0, 0, ty_struct };
|
||||
type_t type_param = { ev_invalid, 0, 0, ty_struct };
|
||||
type_t type_zero = { ev_invalid, 0, 0, ty_struct };
|
||||
type_t type_type_encodings = { ev_invalid, "@type_encodings", 0,
|
||||
ty_struct };
|
||||
|
||||
type_t type_floatfield = { ev_field, ".float", ty_none, {{&type_float}} };
|
||||
type_t type_floatfield = { ev_field, ".float", 1, ty_none,
|
||||
{{&type_float}} };
|
||||
|
||||
type_t *ev_types[ev_type_count] = {
|
||||
&type_void,
|
||||
|
@ -101,6 +104,7 @@ type_t *ev_types[ev_type_count] = {
|
|||
&type_integer,
|
||||
&type_uinteger,
|
||||
&type_short,
|
||||
&type_double,
|
||||
&type_invalid,
|
||||
};
|
||||
|
||||
|
@ -180,6 +184,7 @@ free_type (type_t *type)
|
|||
case ev_integer:
|
||||
case ev_uinteger:
|
||||
case ev_short:
|
||||
case ev_double:
|
||||
break;
|
||||
case ev_field:
|
||||
case ev_pointer:
|
||||
|
@ -214,19 +219,24 @@ append_type (type_t *type, type_t *new)
|
|||
case ev_integer:
|
||||
case ev_uinteger:
|
||||
case ev_short:
|
||||
case ev_double:
|
||||
internal_error (0, "append to basic type");
|
||||
case ev_field:
|
||||
case ev_pointer:
|
||||
t = &(*t)->t.fldptr.type;
|
||||
type->alignment = 1;
|
||||
break;
|
||||
case ev_func:
|
||||
t = &(*t)->t.func.type;
|
||||
type->alignment = 1;
|
||||
break;
|
||||
case ev_invalid:
|
||||
if ((*t)->meta == ty_array)
|
||||
if ((*t)->meta == ty_array) {
|
||||
t = &(*t)->t.array.type;
|
||||
else
|
||||
type->alignment = new->alignment;
|
||||
} else {
|
||||
internal_error (0, "append to object type");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -360,6 +370,7 @@ field_type (type_t *aux)
|
|||
else
|
||||
new = new_type ();
|
||||
new->type = ev_field;
|
||||
new->alignment = 1;
|
||||
new->t.fldptr.type = aux;
|
||||
if (aux)
|
||||
new = find_type (new);
|
||||
|
@ -377,6 +388,7 @@ pointer_type (type_t *aux)
|
|||
else
|
||||
new = new_type ();
|
||||
new->type = ev_pointer;
|
||||
new->alignment = 1;
|
||||
new->t.fldptr.type = aux;
|
||||
if (aux)
|
||||
new = find_type (new);
|
||||
|
@ -394,6 +406,9 @@ array_type (type_t *aux, int size)
|
|||
else
|
||||
new = new_type ();
|
||||
new->type = ev_invalid;
|
||||
if (aux) {
|
||||
new->alignment = aux->alignment;
|
||||
}
|
||||
new->meta = ty_array;
|
||||
new->t.array.type = aux;
|
||||
new->t.array.size = size;
|
||||
|
@ -413,6 +428,9 @@ based_array_type (type_t *aux, int base, int top)
|
|||
else
|
||||
new = new_type ();
|
||||
new->type = ev_invalid;
|
||||
if (aux) {
|
||||
new->alignment = aux->alignment;
|
||||
}
|
||||
new->meta = ty_array;
|
||||
new->t.array.type = aux;
|
||||
new->t.array.base = base;
|
||||
|
@ -582,6 +600,9 @@ encode_type (dstring_t *encoding, const type_t *type)
|
|||
case ev_string:
|
||||
dasprintf (encoding, "*");
|
||||
break;
|
||||
case ev_double:
|
||||
dasprintf (encoding, "d");
|
||||
break;
|
||||
case ev_float:
|
||||
dasprintf (encoding, "f");
|
||||
break;
|
||||
|
@ -685,6 +706,12 @@ is_integral (const type_t *type)
|
|||
return is_enum (type);
|
||||
}
|
||||
|
||||
int
|
||||
is_double (const type_t *type)
|
||||
{
|
||||
return type->type == ev_double;
|
||||
}
|
||||
|
||||
int
|
||||
is_float (const type_t *type)
|
||||
{
|
||||
|
@ -694,7 +721,7 @@ is_float (const type_t *type)
|
|||
int
|
||||
is_scalar (const type_t *type)
|
||||
{
|
||||
return is_float (type) || is_integral (type);
|
||||
return is_float (type) || is_integral (type) || is_double (type);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -830,6 +857,7 @@ type_size (const type_t *type)
|
|||
case ev_integer:
|
||||
case ev_uinteger:
|
||||
case ev_short:
|
||||
case ev_double:
|
||||
case ev_type_count:
|
||||
return pr_type_size[type->type];
|
||||
case ev_invalid:
|
||||
|
@ -869,6 +897,7 @@ init_types (void)
|
|||
{
|
||||
static struct_def_t zero_struct[] = {
|
||||
{"string_val", &type_string},
|
||||
{"double_val", &type_double},
|
||||
{"float_val", &type_float},
|
||||
{"entity_val", &type_entity},
|
||||
{"field_val", &type_field},
|
||||
|
@ -895,6 +924,7 @@ init_types (void)
|
|||
{"integer_val", &type_integer},
|
||||
{"uinteger_val", &type_uinteger},
|
||||
{"quaternion_val", &type_quaternion},
|
||||
{"double_val", &type_double},
|
||||
{0, 0}
|
||||
};
|
||||
static struct_def_t vector_struct[] = {
|
||||
|
@ -982,6 +1012,7 @@ chain_initial_types (void)
|
|||
chain_type (&type_integer);
|
||||
chain_type (&type_uinteger);
|
||||
chain_type (&type_short);
|
||||
chain_type (&type_double);
|
||||
}
|
||||
|
||||
chain_type (&type_param);
|
||||
|
|
|
@ -69,6 +69,7 @@ typedef struct {
|
|||
ex_pointer_t pointer;
|
||||
float quaternion_val[4];
|
||||
int integer_val;
|
||||
double double_val;
|
||||
} i;
|
||||
} immediate_t;
|
||||
|
||||
|
@ -132,6 +133,16 @@ new_string_val (const char *string_val)
|
|||
return find_value (&val);
|
||||
}
|
||||
|
||||
ex_value_t *
|
||||
new_double_val (double double_val)
|
||||
{
|
||||
ex_value_t val;
|
||||
memset (&val, 0, sizeof (val));
|
||||
set_val_type (&val, &type_double);
|
||||
val.v.double_val = double_val;
|
||||
return find_value (&val);
|
||||
}
|
||||
|
||||
ex_value_t *
|
||||
new_float_val (float float_val)
|
||||
{
|
||||
|
@ -265,6 +276,7 @@ static hashtab_t *func_imm_defs;
|
|||
static hashtab_t *pointer_imm_defs;
|
||||
static hashtab_t *quaternion_imm_defs;
|
||||
static hashtab_t *integer_imm_defs;
|
||||
static hashtab_t *double_imm_defs;
|
||||
|
||||
static void
|
||||
imm_free (void *_imm, void *unused)
|
||||
|
@ -296,6 +308,8 @@ imm_get_hash (const void *_imm, void *_tab)
|
|||
} else if (tab == &quaternion_imm_defs) {
|
||||
return Hash_Buffer (&imm->i.quaternion_val,
|
||||
sizeof (&imm->i.quaternion_val));
|
||||
} else if (tab == &double_imm_defs) {
|
||||
return Hash_Buffer (&imm->i.double_val, sizeof (&imm->i.double_val));
|
||||
} else if (tab == &integer_imm_defs) {
|
||||
return imm->i.integer_val;
|
||||
} else {
|
||||
|
@ -330,6 +344,8 @@ imm_compare (const void *_imm1, const void *_imm2, void *_tab)
|
|||
sizeof (imm1->i.pointer));
|
||||
} else if (tab == &quaternion_imm_defs) {
|
||||
return QuatCompare (imm1->i.quaternion_val, imm2->i.quaternion_val);
|
||||
} else if (tab == &double_imm_defs) {
|
||||
return imm1->i.double_val == imm2->i.double_val;
|
||||
} else if (tab == &integer_imm_defs) {
|
||||
return imm1->i.integer_val == imm2->i.integer_val;
|
||||
} else {
|
||||
|
@ -352,6 +368,24 @@ value_as_float (ex_value_t *value)
|
|||
return value->v.integer_val;
|
||||
if (value->lltype == ev_short)
|
||||
return value->v.short_val;
|
||||
if (value->lltype == ev_double)
|
||||
return value->v.double_val;
|
||||
if (value->lltype == ev_float)
|
||||
return value->v.float_val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static double
|
||||
value_as_double (ex_value_t *value)
|
||||
{
|
||||
if (value->lltype == ev_uinteger)
|
||||
return value->v.uinteger_val;
|
||||
if (value->lltype == ev_integer)
|
||||
return value->v.integer_val;
|
||||
if (value->lltype == ev_short)
|
||||
return value->v.short_val;
|
||||
if (value->lltype == ev_double)
|
||||
return value->v.double_val;
|
||||
if (value->lltype == ev_float)
|
||||
return value->v.float_val;
|
||||
return 0;
|
||||
|
@ -366,6 +400,8 @@ value_as_int (ex_value_t *value)
|
|||
return value->v.integer_val;
|
||||
if (value->lltype == ev_short)
|
||||
return value->v.short_val;
|
||||
if (value->lltype == ev_double)
|
||||
return value->v.double_val;
|
||||
if (value->lltype == ev_float)
|
||||
return value->v.float_val;
|
||||
return 0;
|
||||
|
@ -380,6 +416,8 @@ value_as_uint (ex_value_t *value)
|
|||
return value->v.integer_val;
|
||||
if (value->lltype == ev_short)
|
||||
return value->v.short_val;
|
||||
if (value->lltype == ev_double)
|
||||
return value->v.double_val;
|
||||
if (value->lltype == ev_float)
|
||||
return value->v.float_val;
|
||||
return 0;
|
||||
|
@ -395,6 +433,9 @@ convert_value (ex_value_t *value, type_t *type)
|
|||
if (is_float (type)) {
|
||||
float val = value_as_float (value);
|
||||
return new_float_val (val);
|
||||
} else if (is_double (type)) {
|
||||
double val = value_as_double (value);
|
||||
return new_double_val (val);
|
||||
} else if (type->type == ev_short) {
|
||||
int val = value_as_int (value);
|
||||
return new_short_val (val);
|
||||
|
@ -494,6 +535,10 @@ emit_value (ex_value_t *value, def_t *def)
|
|||
tab = quaternion_imm_defs;
|
||||
type = &type_quaternion;
|
||||
break;
|
||||
case ev_double:
|
||||
tab = double_imm_defs;
|
||||
type = &type_double;
|
||||
break;
|
||||
default:
|
||||
internal_error (0, 0);
|
||||
}
|
||||
|
@ -591,6 +636,7 @@ clear_immediates (void)
|
|||
Hash_FlushTable (pointer_imm_defs);
|
||||
Hash_FlushTable (quaternion_imm_defs);
|
||||
Hash_FlushTable (integer_imm_defs);
|
||||
Hash_FlushTable (double_imm_defs);
|
||||
} else {
|
||||
value_table = Hash_NewTable (16381, 0, 0, 0);
|
||||
Hash_SetHashCompare (value_table, value_get_hash, value_compare);
|
||||
|
@ -624,6 +670,10 @@ clear_immediates (void)
|
|||
integer_imm_defs =
|
||||
Hash_NewTable (16381, 0, imm_free, &integer_imm_defs);
|
||||
Hash_SetHashCompare (integer_imm_defs, imm_get_hash, imm_compare);
|
||||
|
||||
double_imm_defs =
|
||||
Hash_NewTable (16381, 0, imm_free, &double_imm_defs);
|
||||
Hash_SetHashCompare (double_imm_defs, imm_get_hash, imm_compare);
|
||||
}
|
||||
|
||||
def = make_symbol (".zero", &type_zero, 0, sc_extern)->s.def;
|
||||
|
|
|
@ -29,15 +29,19 @@ test_bins=\
|
|||
fail_bins=
|
||||
|
||||
test_progs_dat=\
|
||||
address-cast.dat \
|
||||
alignment.dat \
|
||||
chewed-alias.dat \
|
||||
chewed-return.dat \
|
||||
comma-expr.dat \
|
||||
deadbool.dat \
|
||||
double.dat \
|
||||
enum.dat \
|
||||
fordecl.dat \
|
||||
func-expr.dat \
|
||||
func-static.dat \
|
||||
infloop.dat \
|
||||
ivar-struct-return.dat \
|
||||
modulo.dat \
|
||||
paramret.dat \
|
||||
quaternion.dat \
|
||||
|
@ -57,11 +61,31 @@ test_progs_dat=\
|
|||
|
||||
fail_progs_dat=
|
||||
|
||||
test_build_errors=\
|
||||
double-demote-float.r \
|
||||
double-demote-float-ainit.r \
|
||||
double-demote-float-ginit.r \
|
||||
double-demote-float-linit.r \
|
||||
double-demote-int.r \
|
||||
double-demote-int-ainit.r \
|
||||
double-demote-int-ginit.r \
|
||||
double-demote-int-linit.r \
|
||||
double-int-compare.r \
|
||||
double-float-compare.r
|
||||
|
||||
fail_build_errors=
|
||||
|
||||
test_defspace_src=\
|
||||
tw-defspace.c tw-diagnostic.c tw-strpool.c
|
||||
|
||||
TESTS=$(test_bins) $(test_progs_dat:.dat=.run)
|
||||
XFAIL_TESTS=$(fail_bins) $(fail_progs_dat:.dat=.run)
|
||||
TESTS=\
|
||||
$(test_bins) \
|
||||
$(test_progs_dat:.dat=.run) \
|
||||
$(test_build_errors:.r=.run)
|
||||
XFAIL_TESTS=\
|
||||
$(fail_bins) \
|
||||
$(fail_progs_dat:.dat=.run) \
|
||||
$(fail_build_errors:.r=.run)
|
||||
|
||||
check_PROGRAMS=test-harness $(test_progs_dat) $(test_bins)
|
||||
|
||||
|
@ -75,6 +99,24 @@ test_harness_DEPENDENCIES= $(QFCC_TEST_DEPS)
|
|||
|
||||
r_depfiles_remade=
|
||||
|
||||
address_cast_dat_SOURCES=address-cast.r
|
||||
address_cast_obj=$(address_cast_dat_SOURCES:.r=.qfo)
|
||||
address-cast.dat$(EXEEXT): $(address_cast_obj) $(QFCC_DEP)
|
||||
$(QFCC) $(QCFLAGS) -o $@ $(address_cast_obj)
|
||||
address-cast.run: Makefile build-run
|
||||
$(srcdir)/build-run $@
|
||||
include ./$(DEPDIR)/address-cast.Qo # am--include-marker
|
||||
r_depfiles_remade += ./$(DEPDIR)/address-cast.Qo
|
||||
|
||||
alignment_dat_SOURCES=alignment.r
|
||||
alignment_obj=$(alignment_dat_SOURCES:.r=.qfo)
|
||||
alignment.dat$(EXEEXT): $(alignment_obj) $(QFCC_DEP)
|
||||
$(QFCC) $(QCFLAGS) -o $@ $(alignment_obj)
|
||||
alignment.run: Makefile build-run
|
||||
$(srcdir)/build-run $@
|
||||
include ./$(DEPDIR)/alignment.Qo # am--include-marker
|
||||
r_depfiles_remade += ./$(DEPDIR)/alignment.Qo
|
||||
|
||||
chewed_alias_dat_SOURCES=chewed-alias.r
|
||||
chewed_alias_obj=$(chewed_alias_dat_SOURCES:.r=.qfo)
|
||||
chewed-alias.dat$(EXEEXT): $(chewed_alias_obj) $(QFCC_DEP)
|
||||
|
@ -111,6 +153,45 @@ deadbool.run: Makefile build-run
|
|||
include ./$(DEPDIR)/deadbool.Qo # am--include-marker
|
||||
r_depfiles_remade += ./$(DEPDIR)/deadbool.Qo
|
||||
|
||||
double_dat_SOURCES=double.r
|
||||
double_obj=$(double_dat_SOURCES:.r=.qfo)
|
||||
double.dat$(EXEEXT): $(double_obj) $(QFCC_DEP)
|
||||
$(QFCC) $(QCFLAGS) -o $@ $(double_obj)
|
||||
double.run: Makefile build-run
|
||||
$(srcdir)/build-run $@
|
||||
include ./$(DEPDIR)/double.Qo # am--include-marker
|
||||
r_depfiles_remade += ./$(DEPDIR)/double.Qo
|
||||
|
||||
double-demote-int.run$(EXEEXT): double-demote-int.r Makefile build-compile-fail-run
|
||||
$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $<
|
||||
|
||||
double-demote-float.run$(EXEEXT): double-demote-float.r Makefile build-compile-fail-run
|
||||
$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $<
|
||||
|
||||
double-demote-int-ainit.run$(EXEEXT): double-demote-int-ainit.r Makefile build-compile-fail-run
|
||||
$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $<
|
||||
|
||||
double-demote-float-ainit.run$(EXEEXT): double-demote-float-ainit.r Makefile build-compile-fail-run
|
||||
$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $<
|
||||
|
||||
double-demote-int-ginit.run$(EXEEXT): double-demote-int-ginit.r Makefile build-compile-fail-run
|
||||
$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $<
|
||||
|
||||
double-demote-float-ginit.run$(EXEEXT): double-demote-float-ginit.r Makefile build-compile-fail-run
|
||||
$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $<
|
||||
|
||||
double-demote-int-linit.run$(EXEEXT): double-demote-int-linit.r Makefile build-compile-fail-run
|
||||
$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $<
|
||||
|
||||
double-demote-float-linit.run$(EXEEXT): double-demote-float-linit.r Makefile build-compile-fail-run
|
||||
$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $<
|
||||
|
||||
double-int-compare.run$(EXEEXT): double-int-compare.r Makefile build-compile-fail-run
|
||||
$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $<
|
||||
|
||||
double-float-compare.run$(EXEEXT): double-float-compare.r Makefile build-compile-fail-run
|
||||
$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $<
|
||||
|
||||
enum_dat_SOURCES=enum.r
|
||||
enum_obj=$(enum_dat_SOURCES:.r=.qfo)
|
||||
enum.dat$(EXEEXT): $(enum_obj) $(QFCC_DEP)
|
||||
|
@ -156,6 +237,15 @@ infloop.run: Makefile build-run
|
|||
include ./$(DEPDIR)/infloop.Qo # am--include-marker
|
||||
r_depfiles_remade += ./$(DEPDIR)/infloop.Qo
|
||||
|
||||
ivar_struct_return_dat_SOURCES=ivar-struct-return.r
|
||||
ivar_struct_return_obj=$(ivar_struct_return_dat_SOURCES:.r=.qfo)
|
||||
ivar-struct-return.dat$(EXEEXT): $(ivar_struct_return_obj) $(QFCC_DEP)
|
||||
$(QFCC) $(QCFLAGS) -o $@ $(ivar_struct_return_obj)
|
||||
ivar-struct-return.run: Makefile build-run
|
||||
$(srcdir)/build-run $@
|
||||
include ./$(DEPDIR)/ivar-struct-return.Qo # am--include-marker
|
||||
r_depfiles_remade += ./$(DEPDIR)/ivar-struct-return.Qo
|
||||
|
||||
modulo_dat_SOURCES=modulo.r
|
||||
modulo_obj=$(modulo_dat_SOURCES:.r=.qfo)
|
||||
modulo.dat$(EXEEXT): $(modulo_obj) $(QFCC_DEP)
|
||||
|
|
21
tools/qfcc/test/address-cast.r
Normal file
21
tools/qfcc/test/address-cast.r
Normal file
|
@ -0,0 +1,21 @@
|
|||
int a;
|
||||
double b;
|
||||
int c = (int) &b;
|
||||
double d;
|
||||
void printf (string fmt, ...) = #0;
|
||||
|
||||
int main()
|
||||
{
|
||||
int di = (int) &d;
|
||||
int fail = 0;
|
||||
|
||||
if (!c) {
|
||||
printf ("global init address cast fail: %d\n", c);
|
||||
fail |= 1;
|
||||
}
|
||||
if (!di) {
|
||||
printf ("local init address cast fail: %d\n", di);
|
||||
fail |= 1;
|
||||
}
|
||||
return fail;
|
||||
}
|
36
tools/qfcc/test/alignment.r
Normal file
36
tools/qfcc/test/alignment.r
Normal file
|
@ -0,0 +1,36 @@
|
|||
int a;
|
||||
double b;
|
||||
int c;
|
||||
double d;
|
||||
void printf (string fmt, ...) = #0;
|
||||
|
||||
int main()
|
||||
{
|
||||
int fail = 0;
|
||||
void *ap = &a;
|
||||
void *bp = &b;
|
||||
void *cp = &c;
|
||||
void *dp = &d;
|
||||
int aa = (int) ap;
|
||||
int ba = (int) bp;
|
||||
int ca = (int) cp;
|
||||
int da = (int) dp;
|
||||
|
||||
if (ba & 1) {
|
||||
printf ("double b is not aligned: %d\n", ba);
|
||||
fail |= 1;
|
||||
}
|
||||
if (da & 1) {
|
||||
printf ("double d is not aligned: %d\n", da);
|
||||
fail |= 1;
|
||||
}
|
||||
if (ca - aa != 1) {
|
||||
printf ("int c (%d) is not adjacant to int a (%d)\n", ca, aa);
|
||||
fail |= 1;
|
||||
}
|
||||
if (ba <= ca) {
|
||||
printf ("double b does not come after int c: %d %d\n", ba, ca);
|
||||
fail |= 1;
|
||||
}
|
||||
return fail;
|
||||
}
|
15
tools/qfcc/test/build-compile-fail-run
Executable file
15
tools/qfcc/test/build-compile-fail-run
Executable file
|
@ -0,0 +1,15 @@
|
|||
#! /bin/sh
|
||||
|
||||
script=$1
|
||||
shift
|
||||
|
||||
cat > $script <<EOF
|
||||
#! /bin/sh
|
||||
# compile must fail
|
||||
$@
|
||||
if test \$? != 1; then
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
EOF
|
||||
chmod +x $script
|
|
@ -9,7 +9,7 @@ void foo (void)
|
|||
return;
|
||||
if (!time) {
|
||||
ent = spawn ();
|
||||
ent.f = time + 0.1;
|
||||
ent.f = time + 0.1f;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
6
tools/qfcc/test/double-demote-float-ainit.r
Normal file
6
tools/qfcc/test/double-demote-float-ainit.r
Normal file
|
@ -0,0 +1,6 @@
|
|||
double a;
|
||||
int b[] = {1.0d};
|
||||
int main ()
|
||||
{
|
||||
return 1; // test fails if compile succeeds
|
||||
}
|
6
tools/qfcc/test/double-demote-float-ginit.r
Normal file
6
tools/qfcc/test/double-demote-float-ginit.r
Normal file
|
@ -0,0 +1,6 @@
|
|||
double a;
|
||||
float b = 1.0d;
|
||||
int main ()
|
||||
{
|
||||
return 1; // test fails if compile succeeds
|
||||
}
|
6
tools/qfcc/test/double-demote-float-linit.r
Normal file
6
tools/qfcc/test/double-demote-float-linit.r
Normal file
|
@ -0,0 +1,6 @@
|
|||
double a;
|
||||
int main ()
|
||||
{
|
||||
float b = a;
|
||||
return 1; // test fails if compile succeeds
|
||||
}
|
7
tools/qfcc/test/double-demote-float.r
Normal file
7
tools/qfcc/test/double-demote-float.r
Normal file
|
@ -0,0 +1,7 @@
|
|||
double a;
|
||||
float b;
|
||||
int main ()
|
||||
{
|
||||
b = a;
|
||||
return 1; // test fails if compile succeeds
|
||||
}
|
6
tools/qfcc/test/double-demote-int-ainit.r
Normal file
6
tools/qfcc/test/double-demote-int-ainit.r
Normal file
|
@ -0,0 +1,6 @@
|
|||
double a;
|
||||
int b[] = {1.0d};
|
||||
int main ()
|
||||
{
|
||||
return 1; // test fails if compile succeeds
|
||||
}
|
6
tools/qfcc/test/double-demote-int-ginit.r
Normal file
6
tools/qfcc/test/double-demote-int-ginit.r
Normal file
|
@ -0,0 +1,6 @@
|
|||
double a;
|
||||
int b = 1.0d;
|
||||
int main ()
|
||||
{
|
||||
return 1; // test fails if compile succeeds
|
||||
}
|
6
tools/qfcc/test/double-demote-int-linit.r
Normal file
6
tools/qfcc/test/double-demote-int-linit.r
Normal file
|
@ -0,0 +1,6 @@
|
|||
double a;
|
||||
int main ()
|
||||
{
|
||||
int b = a;
|
||||
return 1; // test fails if compile succeeds
|
||||
}
|
7
tools/qfcc/test/double-demote-int.r
Normal file
7
tools/qfcc/test/double-demote-int.r
Normal file
|
@ -0,0 +1,7 @@
|
|||
double a;
|
||||
int b;
|
||||
int main ()
|
||||
{
|
||||
b = a;
|
||||
return 1; // test fails if compile succeeds
|
||||
}
|
7
tools/qfcc/test/double-float-compare.r
Normal file
7
tools/qfcc/test/double-float-compare.r
Normal file
|
@ -0,0 +1,7 @@
|
|||
double a;
|
||||
float b;
|
||||
int main ()
|
||||
{
|
||||
int x = a == b;
|
||||
return 1; // test fails if compile succeeds
|
||||
}
|
7
tools/qfcc/test/double-int-compare.r
Normal file
7
tools/qfcc/test/double-int-compare.r
Normal file
|
@ -0,0 +1,7 @@
|
|||
double a;
|
||||
int b;
|
||||
int main ()
|
||||
{
|
||||
int x = a == b;
|
||||
return 1; // test fails if compile succeeds
|
||||
}
|
106
tools/qfcc/test/double.r
Normal file
106
tools/qfcc/test/double.r
Normal file
|
@ -0,0 +1,106 @@
|
|||
void printf (string fmt, ...) = #0;
|
||||
# define M_PI 3.14159265358979323846
|
||||
|
||||
union {
|
||||
double d;
|
||||
int i[2];
|
||||
} type_pun;
|
||||
|
||||
int
|
||||
test_format ()
|
||||
{
|
||||
int fail = 0;
|
||||
type_pun.d = M_PI;
|
||||
printf ("%g %08x%08x\n", type_pun.d, type_pun.i[1], type_pun.i[0]);
|
||||
// this will fail on big-endian systems
|
||||
fail = type_pun.i[0] != 0x54442d18 || type_pun.i[1] != 0x400921fb;
|
||||
return fail;
|
||||
}
|
||||
|
||||
int
|
||||
test_constant ()
|
||||
{
|
||||
int fail = 0;
|
||||
double a, b, c, d, e;
|
||||
a = 1;
|
||||
b = 2.0;
|
||||
c = 3.2f;
|
||||
d = 3.2d;
|
||||
e = 3.2;
|
||||
printf ("%.17g %.17g %.17g %.17g %.17g\n", a, b, c, d, e);
|
||||
// this will fail on big-endian systems
|
||||
fail |= c == d; // 3.2 is not exactly representable, so must be different
|
||||
fail |= c == e; // 3.2 is not exactly representable, so must be different
|
||||
fail |= d != e; // 3.2d and 3.2 are both double, so must be the same
|
||||
return fail;
|
||||
}
|
||||
|
||||
double less = 3;
|
||||
double greater_equal = 3;
|
||||
double less_equal = 5;
|
||||
double greater = 5;
|
||||
|
||||
int
|
||||
test_copare ()
|
||||
{
|
||||
int fail = 0;
|
||||
|
||||
fail |= !(less < greater);
|
||||
fail |= (less > greater);
|
||||
fail |= !(less != greater);
|
||||
fail |= (less == greater);
|
||||
fail |= !(less <= greater);
|
||||
fail |= (less >= greater);
|
||||
|
||||
fail |= (less_equal < greater);
|
||||
fail |= (less_equal > greater);
|
||||
fail |= !(less_equal == greater);
|
||||
fail |= (less_equal != greater);
|
||||
fail |= !(less_equal <= greater);
|
||||
fail |= !(less_equal >= greater);
|
||||
|
||||
fail |= (greater < less);
|
||||
fail |= !(greater > less);
|
||||
fail |= !(greater != less);
|
||||
fail |= (greater == less);
|
||||
fail |= (greater <= less);
|
||||
fail |= !(greater >= less);
|
||||
|
||||
fail |= (greater_equal < less);
|
||||
fail |= (greater_equal > less);
|
||||
fail |= !(greater_equal == less);
|
||||
fail |= (greater_equal != less);
|
||||
fail |= !(greater_equal <= less);
|
||||
fail |= !(greater_equal >= less);
|
||||
return fail;
|
||||
}
|
||||
|
||||
int
|
||||
test_ops ()
|
||||
{
|
||||
int fail = 0;
|
||||
double a = 6.25, b = 2.375;
|
||||
double c;
|
||||
|
||||
c = a + b;
|
||||
fail |= c != 8.625;
|
||||
c = a - b;
|
||||
fail |= c != 3.875;
|
||||
c = a * b;
|
||||
fail |= c != 14.84375;
|
||||
c = a / b;
|
||||
fail |= c != 50d/19d;
|
||||
c = a % b;
|
||||
fail |= c != 1.5;
|
||||
return fail;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
int fail = 0;
|
||||
fail |= test_format ();
|
||||
fail |= test_constant ();
|
||||
fail |= test_ops ();
|
||||
return fail;
|
||||
}
|
27
tools/qfcc/test/ivar-struct-return.r
Normal file
27
tools/qfcc/test/ivar-struct-return.r
Normal file
|
@ -0,0 +1,27 @@
|
|||
#pragma bug die
|
||||
|
||||
struct Point {
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
typedef struct Point Point;
|
||||
|
||||
@interface Object
|
||||
{
|
||||
int foo;
|
||||
Point origin;
|
||||
}
|
||||
-(Point) origin;
|
||||
@end
|
||||
|
||||
@implementation Object
|
||||
-(Point) origin
|
||||
{
|
||||
return origin;
|
||||
}
|
||||
@end
|
||||
void __obj_exec_class (struct obj_module *msg) = #0;
|
||||
int main()
|
||||
{
|
||||
return 0; // to survive and prevail
|
||||
}
|
|
@ -1,11 +1,34 @@
|
|||
#pragma traditional
|
||||
void printf (string ftm, ...) = #0;
|
||||
|
||||
void (...) printf = #0;
|
||||
float snafu (float a, float b)
|
||||
{
|
||||
float c = a % b;
|
||||
return c;
|
||||
}
|
||||
|
||||
int imodulo (int a, int b)
|
||||
{
|
||||
return a %% b;
|
||||
}
|
||||
|
||||
float fmodulo (float a, float b)
|
||||
{
|
||||
return a %% b;
|
||||
}
|
||||
|
||||
double dmodulo (double a, double b)
|
||||
{
|
||||
return a %% b;
|
||||
}
|
||||
|
||||
#pragma traditional
|
||||
float foo (float a, float b)
|
||||
{
|
||||
float c = a % b;
|
||||
return c;
|
||||
}
|
||||
#pragma advanced
|
||||
|
||||
float bar (float a, float b)
|
||||
{
|
||||
float c;
|
||||
|
@ -15,14 +38,35 @@ float bar (float a, float b)
|
|||
return c;
|
||||
}
|
||||
|
||||
#pragma traditional
|
||||
float baz (float a, float b)
|
||||
{
|
||||
float c = (a + b) % (a - b);
|
||||
return c;
|
||||
}
|
||||
#pragma advanced
|
||||
|
||||
float test (string name, float (func)(float a, float b),
|
||||
float a, float b, float c)
|
||||
@overload int
|
||||
test (string name, string op, int (func)(int a, int b), int a, int b, int c)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = func (a, b);
|
||||
if (ret != c) {
|
||||
if (func == baz)
|
||||
printf ("%s: (%d + %d) %% (%d - %d): %d != %d\n",
|
||||
name, a, b, a, b, ret, c);
|
||||
else
|
||||
printf ("%s: %d %s %d: %d != %d\n",
|
||||
name, a, op, b, ret, c);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@overload int
|
||||
test (string name, string op, float (func)(float a, float b),
|
||||
float a, float b, float c)
|
||||
{
|
||||
float ret;
|
||||
|
||||
|
@ -32,8 +76,27 @@ float test (string name, float (func)(float a, float b),
|
|||
printf ("%s: (%g + %g) %% (%g - %g): %g != %g\n",
|
||||
name, a, b, a, b, ret, c);
|
||||
else
|
||||
printf ("%s: %g %% %g: %g != %g\n",
|
||||
name, a, b, ret, c);
|
||||
printf ("%s: %g %s %g: %g != %g\n",
|
||||
name, a, op, b, ret, c);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@overload int
|
||||
test (string name, string op, double (func)(double a, double b),
|
||||
double a, double b, double c)
|
||||
{
|
||||
double ret;
|
||||
|
||||
ret = func (a, b);
|
||||
if (ret != c) {
|
||||
if (func == baz)
|
||||
printf ("%s: (%g + %g) %% (%g - %g): %g != %g\n",
|
||||
name, a, b, a, b, ret, c);
|
||||
else
|
||||
printf ("%s: %g %s %g: %g != %g\n",
|
||||
name, a, op, b, ret, c);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -42,20 +105,56 @@ float test (string name, float (func)(float a, float b),
|
|||
float main (void)
|
||||
{
|
||||
float res = 0;
|
||||
res |= test ("foo", foo, 5, 3, 2);
|
||||
res |= test ("bar", bar, 5, 3, 2);
|
||||
res |= test ("baz", baz, 5, 3, 0);
|
||||
res |= test ("foo", "%", foo, 5, 3, 2);
|
||||
res |= test ("bar", "%", bar, 5, 3, 2);
|
||||
res |= test ("baz", "%", baz, 5, 3, 0);
|
||||
res |= test ("snafu", "%", snafu, 5, 3, 2);
|
||||
|
||||
res |= test ("foo", foo, -5, 3, -2);
|
||||
res |= test ("bar", bar, -5, 3, -2);
|
||||
res |= test ("baz", baz, -5, 3, -2);
|
||||
res |= test ("foo", "%", foo, -5, 3, -2);
|
||||
res |= test ("bar", "%", bar, -5, 3, -2);
|
||||
res |= test ("baz", "%", baz, -5, 3, -2);
|
||||
res |= test ("snafu", "%", snafu, -5, 3, -2);
|
||||
|
||||
res |= test ("foo", foo, 5, -3, 2);
|
||||
res |= test ("bar", bar, 5, -3, 2);
|
||||
res |= test ("baz", baz, 5, -3, 2);
|
||||
res |= test ("foo", "%", foo, 5, -3, 2);
|
||||
res |= test ("bar", "%", bar, 5, -3, 2);
|
||||
res |= test ("baz", "%", baz, 5, -3, 2);
|
||||
res |= test ("snafu", "%", snafu, 5, -3, 2);
|
||||
|
||||
res |= test ("foo", foo, -5, -3, -2);
|
||||
res |= test ("bar", bar, -5, -3, -2);
|
||||
res |= test ("baz", baz, -5, -3, 0);
|
||||
res |= test ("foo", "%", foo, -5, -3, -2);
|
||||
res |= test ("bar", "%", bar, -5, -3, -2);
|
||||
res |= test ("baz", "%", baz, -5, -3, 0);
|
||||
res |= test ("snafu", "%", snafu, -5, -3, -2);
|
||||
|
||||
res |= test ("foo", "%", foo, 5, 3.5, 1.5);
|
||||
res |= test ("foo", "%", foo, -5, 3.5, -1.5);
|
||||
res |= test ("snafu", "%", snafu, 5, 3.5, 1.5);
|
||||
res |= test ("snafu", "%", snafu, -5, 3.5, -1.5);
|
||||
|
||||
res |= test ("int modulo", "%%", imodulo, 5, 3, 2);
|
||||
res |= test ("int modulo", "%%", imodulo, -5, 3, 1);
|
||||
res |= test ("int modulo", "%%", imodulo, 5, -3, -1);
|
||||
res |= test ("int modulo", "%%", imodulo, -5, -3, -2);
|
||||
res |= test ("int modulo", "%%", imodulo, 6, 3, 0);
|
||||
res |= test ("int modulo", "%%", imodulo, -6, 3, 0);
|
||||
res |= test ("int modulo", "%%", imodulo, 6, -3, 0);
|
||||
res |= test ("int modulo", "%%", imodulo, -6, -3, 0);
|
||||
|
||||
res |= test ("float modulo", "%%", fmodulo, 5, 3, 2);
|
||||
res |= test ("float modulo", "%%", fmodulo, -5, 3, 1);
|
||||
res |= test ("float modulo", "%%", fmodulo, 5, -3, -1);
|
||||
res |= test ("float modulo", "%%", fmodulo, -5, -3, -2);
|
||||
res |= test ("float modulo", "%%", fmodulo, 6, 3, 0);
|
||||
res |= test ("float modulo", "%%", fmodulo, -6, 3, 0);
|
||||
res |= test ("float modulo", "%%", fmodulo, 6, -3, 0);
|
||||
res |= test ("float modulo", "%%", fmodulo, -6, -3, 0);
|
||||
|
||||
res |= test ("double modulo", "%%", dmodulo, 5, 3, 2);
|
||||
res |= test ("double modulo", "%%", dmodulo, -5, 3, 1);
|
||||
res |= test ("double modulo", "%%", dmodulo, 5, -3, -1);
|
||||
res |= test ("double modulo", "%%", dmodulo, -5, -3, -2);
|
||||
res |= test ("double modulo", "%%", dmodulo, 6, 3, 0);
|
||||
res |= test ("double modulo", "%%", dmodulo, -6, 3, 0);
|
||||
res |= test ("double modulo", "%%", dmodulo, 6, -3, 0);
|
||||
res |= test ("double modulo", "%%", dmodulo, -6, -3, 0);
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ state0 (void)
|
|||
[$frame1, state1]
|
||||
{
|
||||
if (self.frame != $frame1 || self.think != state1
|
||||
|| self.nextthink != 0.1) {
|
||||
|| self.nextthink != 0.1f) {
|
||||
printf ("state0: %g %x %g\n", self.frame, self.think, self.nextthink);
|
||||
exit (1);
|
||||
}
|
||||
|
@ -21,10 +21,10 @@ state0 (void)
|
|||
|
||||
void
|
||||
state1 (void)
|
||||
[$frame2, state2, 0.2]
|
||||
[$frame2, state2, 0.2f]
|
||||
{
|
||||
if (self.frame != $frame2 || self.think != state2
|
||||
|| self.nextthink != 0.2) {
|
||||
|| self.nextthink != 0.2f) {
|
||||
printf ("state0: %g %x %g\n", self.frame, self.think, self.nextthink);
|
||||
exit (1);
|
||||
}
|
||||
|
@ -32,10 +32,10 @@ state1 (void)
|
|||
|
||||
void
|
||||
state2 (void)
|
||||
[$frame0, state0, 0.5]
|
||||
[$frame0, state0, 0.5f]
|
||||
{
|
||||
if (self.frame != $frame0 || self.think != state0
|
||||
|| self.nextthink != 0.5) {
|
||||
|| self.nextthink != 0.5f) {
|
||||
printf ("state0: %g %x %g\n", self.frame, self.think, self.nextthink);
|
||||
exit (1);
|
||||
}
|
||||
|
|
|
@ -135,9 +135,13 @@ init_qf (void)
|
|||
|
||||
Memory_Init (malloc (1024 * 1024), 1024 * 1024);
|
||||
|
||||
Cvar_Get ("pr_debug", "2", 0, 0, 0);
|
||||
cvar_t *debug = Cvar_Get ("pr_debug", "2", 0, 0, 0);
|
||||
Cvar_Get ("pr_boundscheck", "2", 0, 0, 0);
|
||||
|
||||
if (options.trace > 1) {
|
||||
Cvar_SetValue (debug, 4);
|
||||
}
|
||||
|
||||
pr.edicts = &edicts;
|
||||
pr.num_edicts = &num_edicts;
|
||||
pr.reserved_edicts = &reserved_edicts;
|
||||
|
@ -207,7 +211,7 @@ parse_options (int argc, char **argv)
|
|||
options.flote = 1;
|
||||
break;
|
||||
case 't':
|
||||
options.trace = 1;
|
||||
options.trace++;
|
||||
break;
|
||||
case 'h':
|
||||
usage (0);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
void printf (string fmt, ...) = #0;
|
||||
float (string s) stof = #0;
|
||||
float (float x) sqrt = #0;
|
||||
@overload float (float x) sqrt = #0;
|
||||
|
||||
float
|
||||
heron (float a, float b, float c)
|
||||
|
|
Loading…
Reference in a new issue