mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-05-31 16:51:08 +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
|
\page connection_sequence QW Connection Sequence
|
||||||
\msc
|
\msc
|
||||||
Client,Server;
|
Client [linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black],
|
||||||
Client=>Server [label = "getchallenge\n"];
|
Server [linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||||
Server=>Client [label = "c[challenge][ext]"];
|
Client=>Server [label = "getchallenge\n", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||||
Client=>Server [label = "connect [protover] [qport] [challenge] [userinfo]"];
|
Server=>Client [label = "c[challenge][ext]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||||
Server=>Client [label = "j"];
|
Client=>Server [label = "connect [protover] [qport] [challenge] [userinfo]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||||
Client->Server [label = "[clc_stringcmd]new"];
|
Server=>Client [label = "j", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||||
Server->Client [label = "[svc_serverdata][data]"];
|
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];
|
||||||
Client->Server [label = "[clc_stringcmd]soundlist [svcount] 0"];
|
||| [linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||||
--- [label = "soundlist loop start"];
|
Client->Server [label = "[clc_stringcmd]soundlist [svcount] 0", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||||
Server->Client [label = "[svc_soundlist][data][next]"];
|
--- [label = "soundlist loop start", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||||
Client->Server [label = "[clc_stringcmd]soundlist [svcount] [next]"];
|
Server->Client [label = "[svc_soundlist][data][next]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||||
--- [label = "soundlist loop end"];
|
Client->Server [label = "[clc_stringcmd]soundlist [svcount] [next]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||||
Server->Client [label = "[svc_soundlist][data]0"];
|
--- [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];
|
||||||
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"];
|
Client->Server [label = "[clc_stringcmd]modellist [svcount] 0", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||||
Server->Client [label = "[svc_modellist][data][next]"];
|
--- [label = "modellist list loop start", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||||
Client->Server [label = "[clc_stringcmd]modellist [svcount] [next]"];
|
Server->Client [label = "[svc_modellist][data][next]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||||
--- [label = "modellist list loop end"];
|
Client->Server [label = "[clc_stringcmd]modellist [svcount] [next]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||||
Server->Client [label = "[svc_modellist][data]0"];
|
--- [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];
|
||||||
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"];
|
Client->Server [label = "[clc_stringcmd]prespawn [svcount] [n=0] [wcsum]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||||
Server->Client [label = "[signon buffer n][stuffcmd]prespawn..."];
|
--- [label = "prespawn loop start", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||||
Client->Server [label = "[clc_stringcmd]prespawn [svcount] [n]"];
|
Server->Client [label = "[signon buffer n][stuffcmd]prespawn...", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||||
--- [label = "prespawn loop end"];
|
Client->Server [label = "[clc_stringcmd]prespawn [svcount] [n]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||||
Server->Client [label = "[signon buffer n][stuffcmd]spawn..."];
|
--- [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];
|
||||||
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"];
|
Client->Server [label = "[clc_stringcmd]spawn [svcount] 0", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||||
Client->Server [label = "[clc_stringcmd]begin [svcount]"];
|
Server->Client [label = "[spawn info][stuffcmd]skins", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black];
|
||||||
#... [label = "in game message sequence"];
|
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
|
\endmsc
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -30,16 +30,28 @@
|
||||||
|
|
||||||
#include "QF/qtypes.h"
|
#include "QF/qtypes.h"
|
||||||
|
|
||||||
|
/** \defgroup llist Linked lists
|
||||||
|
\ingroup utils
|
||||||
|
*/
|
||||||
|
//@{
|
||||||
|
|
||||||
typedef struct llist_node_s {
|
typedef struct llist_node_s {
|
||||||
struct llist_s *parent;
|
struct llist_s *parent; ///< The list owning this node.
|
||||||
struct llist_node_s *prev, *next;
|
struct llist_node_s *prev; ///< The previous node in the list, or null.
|
||||||
void *data;
|
struct llist_node_s *next; ///< The flowing node in the list, or null.
|
||||||
|
void *data; ///< The actual list item.
|
||||||
} llist_node_t;
|
} llist_node_t;
|
||||||
|
|
||||||
typedef struct llist_s {
|
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);
|
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;
|
void *userdata;
|
||||||
} llist_t;
|
} 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_ICAST(x) (llist_iterator_t)(x)
|
||||||
#define LLIST_DATA(node, type) ((type *)((node)->data))
|
#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);
|
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);
|
void llist_delete (llist_t *list);
|
||||||
llist_node_t *llist_append (llist_t *list, void *element);
|
llist_node_t *llist_append (llist_t *list, void *element);
|
||||||
llist_node_t *llist_prefix (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);
|
void *llist_find (llist_t *list, void *comparison);
|
||||||
llist_node_t *llist_findnode (llist_t *list, void *comparison);
|
llist_node_t *llist_findnode (llist_t *list, void *comparison);
|
||||||
void *llist_createarray (llist_t *list, size_t esize);
|
void *llist_createarray (llist_t *list, size_t esize);
|
||||||
|
|
||||||
|
//@}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -44,6 +44,7 @@ typedef enum {
|
||||||
ev_integer,
|
ev_integer,
|
||||||
ev_uinteger,
|
ev_uinteger,
|
||||||
ev_short, // value is embedded in the opcode
|
ev_short, // value is embedded in the opcode
|
||||||
|
ev_double,
|
||||||
|
|
||||||
ev_invalid, // invalid type. used for instruction checking
|
ev_invalid, // invalid type. used for instruction checking
|
||||||
ev_type_count // not a type, gives number of types
|
ev_type_count // not a type, gives number of types
|
||||||
|
@ -180,8 +181,8 @@ typedef enum {
|
||||||
OP_SHL_I,
|
OP_SHL_I,
|
||||||
OP_SHR_I,
|
OP_SHR_I,
|
||||||
|
|
||||||
OP_MOD_F,
|
OP_REM_F,
|
||||||
OP_MOD_I,
|
OP_REM_I,
|
||||||
|
|
||||||
OP_LOADB_F,
|
OP_LOADB_F,
|
||||||
OP_LOADB_V,
|
OP_LOADB_V,
|
||||||
|
@ -305,6 +306,7 @@ typedef enum {
|
||||||
OP_PUSH_P,
|
OP_PUSH_P,
|
||||||
OP_PUSH_Q,
|
OP_PUSH_Q,
|
||||||
OP_PUSH_I,
|
OP_PUSH_I,
|
||||||
|
OP_PUSH_D,
|
||||||
|
|
||||||
OP_PUSHB_S,
|
OP_PUSHB_S,
|
||||||
OP_PUSHB_F,
|
OP_PUSHB_F,
|
||||||
|
@ -315,6 +317,7 @@ typedef enum {
|
||||||
OP_PUSHB_P,
|
OP_PUSHB_P,
|
||||||
OP_PUSHB_Q,
|
OP_PUSHB_Q,
|
||||||
OP_PUSHB_I,
|
OP_PUSHB_I,
|
||||||
|
OP_PUSHB_D,
|
||||||
|
|
||||||
OP_PUSHBI_S,
|
OP_PUSHBI_S,
|
||||||
OP_PUSHBI_F,
|
OP_PUSHBI_F,
|
||||||
|
@ -325,6 +328,7 @@ typedef enum {
|
||||||
OP_PUSHBI_P,
|
OP_PUSHBI_P,
|
||||||
OP_PUSHBI_Q,
|
OP_PUSHBI_Q,
|
||||||
OP_PUSHBI_I,
|
OP_PUSHBI_I,
|
||||||
|
OP_PUSHBI_D,
|
||||||
|
|
||||||
OP_POP_S,
|
OP_POP_S,
|
||||||
OP_POP_F,
|
OP_POP_F,
|
||||||
|
@ -335,6 +339,7 @@ typedef enum {
|
||||||
OP_POP_P,
|
OP_POP_P,
|
||||||
OP_POP_Q,
|
OP_POP_Q,
|
||||||
OP_POP_I,
|
OP_POP_I,
|
||||||
|
OP_POP_D,
|
||||||
|
|
||||||
OP_POPB_S,
|
OP_POPB_S,
|
||||||
OP_POPB_F,
|
OP_POPB_F,
|
||||||
|
@ -345,6 +350,7 @@ typedef enum {
|
||||||
OP_POPB_P,
|
OP_POPB_P,
|
||||||
OP_POPB_Q,
|
OP_POPB_Q,
|
||||||
OP_POPB_I,
|
OP_POPB_I,
|
||||||
|
OP_POPB_D,
|
||||||
|
|
||||||
OP_POPBI_S,
|
OP_POPBI_S,
|
||||||
OP_POPBI_F,
|
OP_POPBI_F,
|
||||||
|
@ -355,6 +361,40 @@ typedef enum {
|
||||||
OP_POPBI_P,
|
OP_POPBI_P,
|
||||||
OP_POPBI_Q,
|
OP_POPBI_Q,
|
||||||
OP_POPBI_I,
|
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;
|
} pr_opcode_e;
|
||||||
|
|
||||||
typedef struct opcode_s {
|
typedef struct opcode_s {
|
||||||
|
@ -383,6 +423,11 @@ typedef struct ddef_s {
|
||||||
pr_int_t s_name;
|
pr_int_t s_name;
|
||||||
} ddef_t;
|
} ddef_t;
|
||||||
|
|
||||||
|
typedef struct dparmsize_s {
|
||||||
|
uint8_t size:5;
|
||||||
|
uint8_t alignment:3;
|
||||||
|
} dparmsize_t;
|
||||||
|
|
||||||
#define DEF_SAVEGLOBAL (1<<15)
|
#define DEF_SAVEGLOBAL (1<<15)
|
||||||
|
|
||||||
#define MAX_PARMS 8
|
#define MAX_PARMS 8
|
||||||
|
@ -398,7 +443,7 @@ typedef struct dfunction_s {
|
||||||
pr_int_t s_file; // source file defined in
|
pr_int_t s_file; // source file defined in
|
||||||
|
|
||||||
pr_int_t numparms;
|
pr_int_t numparms;
|
||||||
uint8_t parm_size[MAX_PARMS];
|
dparmsize_t parm_size[MAX_PARMS];
|
||||||
} dfunction_t;
|
} dfunction_t;
|
||||||
|
|
||||||
typedef union pr_type_u {
|
typedef union pr_type_u {
|
||||||
|
@ -423,7 +468,7 @@ typedef struct pr_va_list_s {
|
||||||
|(((0x##b) & 0xfff) << 12) \
|
|(((0x##b) & 0xfff) << 12) \
|
||||||
|(((0x##c) & 0xfff) << 0) )
|
|(((0x##c) & 0xfff) << 0) )
|
||||||
#define PROG_ID_VERSION 6
|
#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 {
|
typedef struct dprograms_s {
|
||||||
pr_uint_t version;
|
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)
|
#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.
|
/** Access an integer global. Can be assigned to.
|
||||||
|
|
||||||
\par QC type:
|
\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)
|
#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.
|
/** Access an integer parameter. Can be assigned to.
|
||||||
|
|
||||||
\par QC type:
|
\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)
|
#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)
|
/** Access the VM function return value as a \c ::pr_int_t (AKA int32_t)
|
||||||
|
|
||||||
\par QC type:
|
\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)
|
#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.
|
/** Access an integer entity field. Can be assigned to.
|
||||||
|
|
||||||
\par QC type:
|
\par QC type:
|
||||||
|
@ -1032,7 +1079,7 @@ typedef struct {
|
||||||
pr_int_t locals;
|
pr_int_t locals;
|
||||||
pr_int_t profile;
|
pr_int_t profile;
|
||||||
pr_int_t numparms;
|
pr_int_t numparms;
|
||||||
uint8_t parm_size[MAX_PARMS];
|
dparmsize_t parm_size[MAX_PARMS];
|
||||||
dfunction_t *descriptor;
|
dfunction_t *descriptor;
|
||||||
builtin_proc func;
|
builtin_proc func;
|
||||||
} bfunction_t;
|
} bfunction_t;
|
||||||
|
@ -1520,36 +1567,36 @@ struct progs_s {
|
||||||
int zone_size; ///< set by user
|
int zone_size; ///< set by user
|
||||||
|
|
||||||
/// \name builtin functions
|
/// \name builtin functions
|
||||||
//@{
|
///@{
|
||||||
struct hashtab_s *builtin_hash;
|
struct hashtab_s *builtin_hash;
|
||||||
struct hashtab_s *builtin_num_hash;
|
struct hashtab_s *builtin_num_hash;
|
||||||
unsigned bi_next;
|
unsigned bi_next;
|
||||||
unsigned (*bi_map) (progs_t *pr, unsigned binum);
|
unsigned (*bi_map) (progs_t *pr, unsigned binum);
|
||||||
//@}
|
///@}
|
||||||
|
|
||||||
/// \name symbol management
|
/// \name symbol management
|
||||||
//@{
|
///@{
|
||||||
struct hashtab_s *function_hash;
|
struct hashtab_s *function_hash;
|
||||||
struct hashtab_s *global_hash;
|
struct hashtab_s *global_hash;
|
||||||
struct hashtab_s *field_hash;
|
struct hashtab_s *field_hash;
|
||||||
//@}
|
///@}
|
||||||
|
|
||||||
/// \name load hooks
|
/// \name load hooks
|
||||||
//@{
|
///@{
|
||||||
int num_load_funcs;
|
int num_load_funcs;
|
||||||
int max_load_funcs;
|
int max_load_funcs;
|
||||||
pr_load_func_t **load_funcs;
|
pr_load_func_t **load_funcs;
|
||||||
|
|
||||||
/// cleared each load
|
/// cleared each load
|
||||||
//@{
|
///@{
|
||||||
int num_load_finish_funcs;
|
int num_load_finish_funcs;
|
||||||
int max_load_finish_funcs;
|
int max_load_finish_funcs;
|
||||||
pr_load_func_t **load_finish_funcs;
|
pr_load_func_t **load_finish_funcs;
|
||||||
//@}
|
///@}
|
||||||
//@}
|
///@}
|
||||||
|
|
||||||
/// \name string management
|
/// \name string management
|
||||||
//@{
|
///@{
|
||||||
struct dstring_mem_s *ds_mem;
|
struct dstring_mem_s *ds_mem;
|
||||||
strref_t *free_string_refs;
|
strref_t *free_string_refs;
|
||||||
strref_t *static_strings;
|
strref_t *static_strings;
|
||||||
|
@ -1560,10 +1607,11 @@ struct progs_s {
|
||||||
struct hashtab_s *strref_hash;
|
struct hashtab_s *strref_hash;
|
||||||
int num_strings;
|
int num_strings;
|
||||||
strref_t *pr_xtstr;
|
strref_t *pr_xtstr;
|
||||||
//@}
|
int float_promoted; ///< for PR_Sprintf
|
||||||
|
///@}
|
||||||
|
|
||||||
/// \name memory map
|
/// \name memory map
|
||||||
//@{
|
///@{
|
||||||
dfunction_t *pr_functions;
|
dfunction_t *pr_functions;
|
||||||
bfunction_t *function_table;
|
bfunction_t *function_table;
|
||||||
char *pr_strings;
|
char *pr_strings;
|
||||||
|
@ -1573,10 +1621,10 @@ struct progs_s {
|
||||||
dstatement_t *pr_statements;
|
dstatement_t *pr_statements;
|
||||||
pr_type_t *pr_globals;
|
pr_type_t *pr_globals;
|
||||||
unsigned globals_size;
|
unsigned globals_size;
|
||||||
//@}
|
///@}
|
||||||
|
|
||||||
/// \name parameter block
|
/// \name parameter block
|
||||||
//@{
|
///@{
|
||||||
pr_type_t *pr_return;
|
pr_type_t *pr_return;
|
||||||
pr_type_t *pr_params[MAX_PARMS];
|
pr_type_t *pr_params[MAX_PARMS];
|
||||||
pr_type_t *pr_real_params[MAX_PARMS];
|
pr_type_t *pr_real_params[MAX_PARMS];
|
||||||
|
@ -1584,10 +1632,11 @@ struct progs_s {
|
||||||
pr_type_t *pr_saved_params;
|
pr_type_t *pr_saved_params;
|
||||||
int pr_saved_argc;
|
int pr_saved_argc;
|
||||||
int pr_param_size; ///< covers both params and return
|
int pr_param_size; ///< covers both params and return
|
||||||
//@}
|
int pr_param_alignment; ///< covers both params and return
|
||||||
|
///@}
|
||||||
|
|
||||||
/// \name edicts
|
/// \name edicts
|
||||||
//@{
|
///@{
|
||||||
edict_t **edicts;
|
edict_t **edicts;
|
||||||
int max_edicts; ///< set by user
|
int max_edicts; ///< set by user
|
||||||
int *num_edicts;
|
int *num_edicts;
|
||||||
|
@ -1599,10 +1648,10 @@ struct progs_s {
|
||||||
int pr_edict_size; ///< in bytes
|
int pr_edict_size; ///< in bytes
|
||||||
int pr_edictareasize; ///< for bounds checking, starts at 0
|
int pr_edictareasize; ///< for bounds checking, starts at 0
|
||||||
func_t edict_parse;
|
func_t edict_parse;
|
||||||
//@}
|
///@}
|
||||||
|
|
||||||
/// \name execution state
|
/// \name execution state
|
||||||
//@{
|
///@{
|
||||||
int pr_argc;
|
int pr_argc;
|
||||||
|
|
||||||
qboolean pr_trace;
|
qboolean pr_trace;
|
||||||
|
@ -1620,24 +1669,24 @@ struct progs_s {
|
||||||
/// be considered valid if there is no .stack global.
|
/// be considered valid if there is no .stack global.
|
||||||
/// \note The return address and saved locals will not ever be on this
|
/// \note The return address and saved locals will not ever be on this
|
||||||
/// stack.
|
/// stack.
|
||||||
//@{
|
///@{
|
||||||
pr_type_t *stack;
|
pr_type_t *stack;
|
||||||
pointer_t stack_bottom;
|
pointer_t stack_bottom;
|
||||||
int stack_size; ///< set by user
|
int stack_size; ///< set by user
|
||||||
//@}
|
///@}
|
||||||
|
|
||||||
int localstack[LOCALSTACK_SIZE];
|
int localstack[LOCALSTACK_SIZE];
|
||||||
int localstack_used;
|
int localstack_used;
|
||||||
//@}
|
///@}
|
||||||
|
|
||||||
/// \name resources
|
/// \name resources
|
||||||
//@{
|
///@{
|
||||||
pr_resource_t *resources;
|
pr_resource_t *resources;
|
||||||
struct hashtab_s *resource_hash;
|
struct hashtab_s *resource_hash;
|
||||||
//@}
|
///@}
|
||||||
|
|
||||||
/// \name obj info
|
/// \name obj info
|
||||||
//@{
|
///@{
|
||||||
unsigned selector_index;
|
unsigned selector_index;
|
||||||
unsigned selector_index_max;
|
unsigned selector_index_max;
|
||||||
struct obj_list_s **selector_sels;
|
struct obj_list_s **selector_sels;
|
||||||
|
@ -1650,10 +1699,10 @@ struct progs_s {
|
||||||
struct obj_list_s *unclaimed_proto_list;
|
struct obj_list_s *unclaimed_proto_list;
|
||||||
struct obj_list_s *module_list;
|
struct obj_list_s *module_list;
|
||||||
struct obj_list_s *class_tree_list;
|
struct obj_list_s *class_tree_list;
|
||||||
//@}
|
///@}
|
||||||
|
|
||||||
/// \name debug info
|
/// \name debug info
|
||||||
//@{
|
///@{
|
||||||
const char *debugfile;
|
const char *debugfile;
|
||||||
struct pr_debug_header_s *debug;
|
struct pr_debug_header_s *debug;
|
||||||
struct pr_auxfunction_s *auxfunctions;
|
struct pr_auxfunction_s *auxfunctions;
|
||||||
|
@ -1663,10 +1712,10 @@ struct progs_s {
|
||||||
pr_type_t *watch;
|
pr_type_t *watch;
|
||||||
int wp_conditional;
|
int wp_conditional;
|
||||||
pr_type_t wp_val;
|
pr_type_t wp_val;
|
||||||
//@}
|
///@}
|
||||||
|
|
||||||
/// \name globals and fields needed by the VM
|
/// \name globals and fields needed by the VM
|
||||||
//@{
|
///@{
|
||||||
struct {
|
struct {
|
||||||
float *time; ///< required for OP_STATE
|
float *time; ///< required for OP_STATE
|
||||||
pr_int_t *self; ///< 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 think; ///< required for OP_STATE
|
||||||
pr_int_t this; ///< optional for entity<->object linking
|
pr_int_t this; ///< optional for entity<->object linking
|
||||||
} fields;
|
} fields;
|
||||||
//@}
|
///@}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \addtogroup progs_data_access
|
/** \addtogroup progs_data_access
|
||||||
|
|
|
@ -31,28 +31,110 @@
|
||||||
#ifndef __QF_segtext_h
|
#ifndef __QF_segtext_h
|
||||||
#define __QF_segtext_h
|
#define __QF_segtext_h
|
||||||
|
|
||||||
/** \defgroup segtext Segmented text files.
|
/** \defgroup segtext Segmented text files
|
||||||
\ingroup utils
|
\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 {
|
typedef struct segchunk_s {
|
||||||
struct segchunk_s *next;
|
struct segchunk_s *next;
|
||||||
const char *tag;
|
const char *tag; ///< identifying tag or null if no tag
|
||||||
const char *text;
|
const char *text; ///< nul-terminated string holding the segment
|
||||||
int start_line;
|
int start_line; ///< line number for first line of the segment
|
||||||
} segchunk_t;
|
} 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 {
|
typedef struct segtext_s {
|
||||||
struct segtext_s *next;
|
struct segtext_s *next;
|
||||||
segchunk_t *chunk_list;
|
segchunk_t *chunk_list;
|
||||||
struct hashtab_s *tab;
|
struct hashtab_s *tab;
|
||||||
} segtext_t;
|
} 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);
|
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);
|
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);
|
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);
|
const char *Segtext_Find (const segtext_t *st, const char *tag);
|
||||||
|
|
||||||
|
///@}
|
||||||
|
|
||||||
#endif//__QF_segtext_h
|
#endif//__QF_segtext_h
|
||||||
|
|
|
@ -81,6 +81,10 @@ void S_Init (int *viewentity, double *host_frametime);
|
||||||
*/
|
*/
|
||||||
void S_Init_Cvars (void);
|
void S_Init_Cvars (void);
|
||||||
|
|
||||||
|
/** Shutdown the sound engine. Allows audio output modules to shutdown
|
||||||
|
gracefully.
|
||||||
|
*/
|
||||||
|
void S_Shutdown (void);
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
/** \defgroup sound_stuff Unclassified
|
/** \defgroup sound_stuff Unclassified
|
||||||
|
|
|
@ -692,7 +692,12 @@ value_string (progs_t *pr, etype_t type, pr_type_t *val)
|
||||||
case ev_uinteger:
|
case ev_uinteger:
|
||||||
dsprintf (line, "$%08x", val->uinteger_var);
|
dsprintf (line, "$%08x", val->uinteger_var);
|
||||||
break;
|
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, "bad type %i", type);
|
||||||
dsprintf (line, "<%x %x %x %x>",
|
dsprintf (line, "<%x %x %x %x>",
|
||||||
val[0].integer_var, val[1].integer_var,
|
val[0].integer_var, val[1].integer_var,
|
||||||
|
|
|
@ -142,6 +142,21 @@ PR_PopFrame (progs_t *pr)
|
||||||
pr->pr_xtstr = frame->tstr;
|
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
|
/** Setup the stackframe prior to calling a progs function. Saves all local
|
||||||
data the called function will trample on and copies the parameters used
|
data the called function will trample on and copies the parameters used
|
||||||
by the function into the function's local data space.
|
by the function into the function's local data space.
|
||||||
|
@ -153,39 +168,44 @@ PR_PopFrame (progs_t *pr)
|
||||||
static void
|
static void
|
||||||
PR_EnterFunction (progs_t *pr, bfunction_t *f)
|
PR_EnterFunction (progs_t *pr, bfunction_t *f)
|
||||||
{
|
{
|
||||||
pr_int_t i, j, c, o;
|
pr_int_t i;
|
||||||
pr_int_t k;
|
pr_type_t *dstParams[MAX_PARMS];
|
||||||
pr_int_t count = 0;
|
pointer_t paramofs = 0;
|
||||||
int size[2] = {0, 0};
|
|
||||||
long paramofs = 0;
|
|
||||||
long offs;
|
|
||||||
|
|
||||||
PR_PushFrame (pr);
|
PR_PushFrame (pr);
|
||||||
|
|
||||||
if (f->numparms > 0) {
|
if (f->numparms > 0) {
|
||||||
for (i = 0; i < 2 && i < f->numparms; i++) {
|
paramofs = f->parm_start;
|
||||||
paramofs += f->parm_size[i];
|
for (i = 0; i < f->numparms; i++) {
|
||||||
size[i] = f->parm_size[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) {
|
} else if (f->numparms < 0) {
|
||||||
for (i = 0; i < 2 && i < -f->numparms - 1; i++) {
|
paramofs = f->parm_start + 2; // argc and argv
|
||||||
paramofs += f->parm_size[i];
|
for (i = 0; i < -f->numparms - 1; i++) {
|
||||||
size[i] = f->parm_size[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++) {
|
dparmsize_t parmsize = { pr->pr_param_size, pr->pr_param_alignment };
|
||||||
paramofs += pr->pr_param_size;
|
paramofs = align_offset (paramofs, parmsize );
|
||||||
size[i] = pr->pr_param_size;
|
if (i < MAX_PARMS) {
|
||||||
|
dstParams[i] = pr->pr_globals + paramofs;
|
||||||
}
|
}
|
||||||
count = 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],
|
||||||
for (i = 0; i < count && i < pr->pr_argc; i++) {
|
parmsize.size);
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,44 +214,36 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f)
|
||||||
pr->pr_xstatement = f->first_statement - 1; // offset the st++
|
pr->pr_xstatement = f->first_statement - 1; // offset the st++
|
||||||
|
|
||||||
// save off any locals that the new function steps on
|
// save off any locals that the new function steps on
|
||||||
c = f->locals;
|
if (pr->localstack_used + f->locals > LOCALSTACK_SIZE)
|
||||||
if (pr->localstack_used + c > LOCALSTACK_SIZE)
|
|
||||||
PR_RunError (pr, "PR_EnterFunction: locals stack overflow");
|
PR_RunError (pr, "PR_EnterFunction: locals stack overflow");
|
||||||
|
|
||||||
memcpy (&pr->localstack[pr->localstack_used],
|
memcpy (&pr->localstack[pr->localstack_used],
|
||||||
&pr->pr_globals[f->parm_start],
|
&pr->pr_globals[f->parm_start],
|
||||||
sizeof (pr_type_t) * c);
|
sizeof (pr_type_t) * f->locals);
|
||||||
pr->localstack_used += c;
|
pr->localstack_used += f->locals;
|
||||||
|
|
||||||
if (pr_deadbeef_locals->int_val)
|
if (pr_deadbeef_locals->int_val)
|
||||||
for (k = f->parm_start; k < f->parm_start + c; k++)
|
for (i = f->parm_start; i < f->parm_start + f->locals; i++)
|
||||||
pr->pr_globals[k].integer_var = 0xdeadbeef;
|
pr->pr_globals[i].integer_var = 0xdeadbeef;
|
||||||
|
|
||||||
// copy parameters
|
// copy parameters
|
||||||
o = f->parm_start;
|
|
||||||
if (f->numparms >= 0) {
|
if (f->numparms >= 0) {
|
||||||
for (i = 0; i < f->numparms; i++) {
|
for (i = 0; i < f->numparms; i++) {
|
||||||
for (j = 0; j < f->parm_size[i]; j++) {
|
copy_param (dstParams[i], pr->pr_params[i], f->parm_size[i].size);
|
||||||
memcpy (&pr->pr_globals[o], &P_INT (pr, i) + j,
|
|
||||||
sizeof (pr_type_t));
|
|
||||||
o++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pr_type_t *argc = &pr->pr_globals[o++];
|
int copy_args;
|
||||||
pr_type_t *argv = &pr->pr_globals[o++];
|
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 (i = 0; i < -f->numparms - 1; i++) {
|
||||||
for (j = 0; j < f->parm_size[i]; j++) {
|
copy_param (dstParams[i], pr->pr_params[i], f->parm_size[i].size);
|
||||||
memcpy (&pr->pr_globals[o], &P_INT (pr, i) + j,
|
|
||||||
sizeof (pr_type_t));
|
|
||||||
o++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
argc->integer_var = pr->pr_argc - i;
|
copy_args = pr->pr_argc - i;
|
||||||
argv->integer_var = o;
|
argc->integer_var = copy_args;
|
||||||
|
argv->integer_var = dstParams[i] - pr->pr_globals;
|
||||||
if (i < MAX_PARMS) {
|
if (i < MAX_PARMS) {
|
||||||
memcpy (&pr->pr_globals[o], &P_INT (pr, i),
|
memcpy (dstParams[i], pr->pr_params[i],
|
||||||
(MAX_PARMS - i) * pr->pr_param_size * sizeof (pr_type_t));
|
(copy_args * pr->pr_param_size) * sizeof (pr_type_t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -239,19 +251,18 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f)
|
||||||
static void
|
static void
|
||||||
PR_LeaveFunction (progs_t *pr)
|
PR_LeaveFunction (progs_t *pr)
|
||||||
{
|
{
|
||||||
int c;
|
|
||||||
bfunction_t *f = pr->pr_xfunction;
|
bfunction_t *f = pr->pr_xfunction;
|
||||||
|
|
||||||
PR_PopFrame (pr);
|
PR_PopFrame (pr);
|
||||||
|
|
||||||
// restore locals from the stack
|
// restore locals from the stack
|
||||||
c = f->locals;
|
pr->localstack_used -= f->locals;
|
||||||
pr->localstack_used -= c;
|
|
||||||
if (pr->localstack_used < 0)
|
if (pr->localstack_used < 0)
|
||||||
PR_RunError (pr, "PR_LeaveFunction: locals stack underflow");
|
PR_RunError (pr, "PR_LeaveFunction: locals stack underflow");
|
||||||
|
|
||||||
memcpy (&pr->pr_globals[f->parm_start],
|
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
|
VISIBLE void
|
||||||
|
@ -280,12 +291,15 @@ PR_BoundsCheck (progs_t *pr, int addr, etype_t type)
|
||||||
#define OPB (*op_b)
|
#define OPB (*op_b)
|
||||||
#define OPC (*op_c)
|
#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
|
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.
|
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
|
static int
|
||||||
signal_hook (int sig, void *data)
|
signal_hook (int sig, void *data)
|
||||||
|
@ -317,6 +331,8 @@ signal_hook (int sig, void *data)
|
||||||
return 1;
|
return 1;
|
||||||
case OP_MOD_I:
|
case OP_MOD_I:
|
||||||
case OP_MOD_F:
|
case OP_MOD_F:
|
||||||
|
case OP_REM_I:
|
||||||
|
case OP_REM_F:
|
||||||
OPC.integer_var = 0x00000000;
|
OPC.integer_var = 0x00000000;
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
|
@ -421,6 +437,9 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
||||||
PR_PrintStatement (pr, st, 1);
|
PR_PrintStatement (pr, st, 1);
|
||||||
|
|
||||||
switch (st->op) {
|
switch (st->op) {
|
||||||
|
case OP_ADD_D:
|
||||||
|
OPC_double_var = OPA_double_var + OPB_double_var;
|
||||||
|
break;
|
||||||
case OP_ADD_F:
|
case OP_ADD_F:
|
||||||
OPC.float_var = OPA.float_var + OPB.float_var;
|
OPC.float_var = OPA.float_var + OPB.float_var;
|
||||||
break;
|
break;
|
||||||
|
@ -437,6 +456,9 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
||||||
PR_GetString (pr,
|
PR_GetString (pr,
|
||||||
OPB.string_var));
|
OPB.string_var));
|
||||||
break;
|
break;
|
||||||
|
case OP_SUB_D:
|
||||||
|
OPC_double_var = OPA_double_var - OPB_double_var;
|
||||||
|
break;
|
||||||
case OP_SUB_F:
|
case OP_SUB_F:
|
||||||
OPC.float_var = OPA.float_var - OPB.float_var;
|
OPC.float_var = OPA.float_var - OPB.float_var;
|
||||||
break;
|
break;
|
||||||
|
@ -446,12 +468,31 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
||||||
case OP_SUB_Q:
|
case OP_SUB_Q:
|
||||||
QuatSubtract (OPA.quat_var, OPB.quat_var, OPC.quat_var);
|
QuatSubtract (OPA.quat_var, OPB.quat_var, OPC.quat_var);
|
||||||
break;
|
break;
|
||||||
|
case OP_MUL_D:
|
||||||
|
OPC_double_var = OPA_double_var * OPB_double_var;
|
||||||
|
break;
|
||||||
case OP_MUL_F:
|
case OP_MUL_F:
|
||||||
OPC.float_var = OPA.float_var * OPB.float_var;
|
OPC.float_var = OPA.float_var * OPB.float_var;
|
||||||
break;
|
break;
|
||||||
case OP_MUL_V:
|
case OP_MUL_V:
|
||||||
OPC.float_var = DotProduct (OPA.vector_var, OPB.vector_var);
|
OPC.float_var = DotProduct (OPA.vector_var, OPB.vector_var);
|
||||||
break;
|
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:
|
case OP_MUL_FV:
|
||||||
{
|
{
|
||||||
// avoid issues with the likes of x = x.x * x;
|
// 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:
|
case OP_MUL_QV:
|
||||||
QuatMultVec (OPA.quat_var, OPB.vector_var, OPC.vector_var);
|
QuatMultVec (OPA.quat_var, OPB.vector_var, OPC.vector_var);
|
||||||
break;
|
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:
|
case OP_MUL_FQ:
|
||||||
{
|
{
|
||||||
// avoid issues with the likes of x = x.s * x;
|
// 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:
|
case OP_CONJ_Q:
|
||||||
QuatConj (OPA.quat_var, OPC.quat_var);
|
QuatConj (OPA.quat_var, OPC.quat_var);
|
||||||
break;
|
break;
|
||||||
|
case OP_DIV_D:
|
||||||
|
OPC_double_var = OPA_double_var / OPB_double_var;
|
||||||
|
break;
|
||||||
case OP_DIV_F:
|
case OP_DIV_F:
|
||||||
OPC.float_var = OPA.float_var / OPB.float_var;
|
OPC.float_var = OPA.float_var / OPB.float_var;
|
||||||
break;
|
break;
|
||||||
|
@ -630,6 +690,9 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
||||||
case OP_STORE_Q:
|
case OP_STORE_Q:
|
||||||
QuatCopy (OPA.quat_var, OPB.quat_var);
|
QuatCopy (OPA.quat_var, OPB.quat_var);
|
||||||
break;
|
break;
|
||||||
|
case OP_STORE_D:
|
||||||
|
OPB_double_var = OPA_double_var;
|
||||||
|
break;
|
||||||
|
|
||||||
case OP_STOREP_F:
|
case OP_STOREP_F:
|
||||||
case OP_STOREP_ENT:
|
case OP_STOREP_ENT:
|
||||||
|
@ -661,6 +724,14 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
||||||
ptr = pr->pr_globals + pointer;
|
ptr = pr->pr_globals + pointer;
|
||||||
QuatCopy (OPA.quat_var, ptr->quat_var);
|
QuatCopy (OPA.quat_var, ptr->quat_var);
|
||||||
break;
|
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:
|
case OP_ADDRESS:
|
||||||
if (pr_boundscheck->int_val) {
|
if (pr_boundscheck->int_val) {
|
||||||
|
@ -687,6 +758,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
||||||
case OP_ADDRESS_FN:
|
case OP_ADDRESS_FN:
|
||||||
case OP_ADDRESS_I:
|
case OP_ADDRESS_I:
|
||||||
case OP_ADDRESS_P:
|
case OP_ADDRESS_P:
|
||||||
|
case OP_ADDRESS_D:
|
||||||
OPC.integer_var = st->a;
|
OPC.integer_var = st->a;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -735,6 +807,19 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
||||||
ed = PROG_TO_EDICT (pr, OPA.entity_var);
|
ed = PROG_TO_EDICT (pr, OPA.entity_var);
|
||||||
memcpy (&OPC, &ed->v[OPB.integer_var], 4 * sizeof (OPC));
|
memcpy (&OPC, &ed->v[OPB.integer_var], 4 * sizeof (OPC));
|
||||||
break;
|
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_F:
|
||||||
case OP_LOADB_S:
|
case OP_LOADB_S:
|
||||||
|
@ -766,6 +851,14 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
||||||
ptr = pr->pr_globals + pointer;
|
ptr = pr->pr_globals + pointer;
|
||||||
QuatCopy (ptr->quat_var, OPC.quat_var);
|
QuatCopy (ptr->quat_var, OPC.quat_var);
|
||||||
break;
|
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_F:
|
||||||
case OP_LOADBI_S:
|
case OP_LOADBI_S:
|
||||||
|
@ -797,6 +890,14 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
||||||
ptr = pr->pr_globals + pointer;
|
ptr = pr->pr_globals + pointer;
|
||||||
QuatCopy (ptr->quat_var, OPC.quat_var);
|
QuatCopy (ptr->quat_var, OPC.quat_var);
|
||||||
break;
|
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:
|
case OP_LEA:
|
||||||
pointer = OPA.integer_var + OPB.integer_var;
|
pointer = OPA.integer_var + OPB.integer_var;
|
||||||
|
@ -838,6 +939,14 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
||||||
ptr = pr->pr_globals + pointer;
|
ptr = pr->pr_globals + pointer;
|
||||||
QuatCopy (OPA.quat_var, ptr->quat_var);
|
QuatCopy (OPA.quat_var, ptr->quat_var);
|
||||||
break;
|
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_F:
|
||||||
case OP_STOREBI_S:
|
case OP_STOREBI_S:
|
||||||
|
@ -869,6 +978,14 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
||||||
ptr = pr->pr_globals + pointer;
|
ptr = pr->pr_globals + pointer;
|
||||||
QuatCopy (OPA.quat_var, ptr->quat_var);
|
QuatCopy (OPA.quat_var, ptr->quat_var);
|
||||||
break;
|
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_F:
|
||||||
case OP_PUSH_FLD:
|
case OP_PUSH_FLD:
|
||||||
|
@ -1322,22 +1439,58 @@ op_call:
|
||||||
case OP_MUL_I:
|
case OP_MUL_I:
|
||||||
OPC.integer_var = OPA.integer_var * OPB.integer_var;
|
OPC.integer_var = OPA.integer_var * OPB.integer_var;
|
||||||
break;
|
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:
|
case OP_DIV_I:
|
||||||
OPC.integer_var = OPA.integer_var / OPB.integer_var;
|
OPC.integer_var = OPA.integer_var / OPB.integer_var;
|
||||||
break;
|
break;
|
||||||
case OP_MOD_I:
|
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;
|
OPC.integer_var = OPA.integer_var % OPB.integer_var;
|
||||||
break;
|
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:
|
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;
|
break;
|
||||||
case OP_CONV_IF:
|
case OP_CONV_IF:
|
||||||
OPC.float_var = OPA.integer_var;
|
OPC.float_var = OPA.integer_var;
|
||||||
|
@ -1428,6 +1581,41 @@ op_call:
|
||||||
st->b * 4);
|
st->b * 4);
|
||||||
break;
|
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
|
// LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized
|
||||||
/*
|
/*
|
||||||
case OP_BOUNDCHECK:
|
case OP_BOUNDCHECK:
|
||||||
|
|
|
@ -202,6 +202,8 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size)
|
||||||
base -= sizeof (progs); // offsets are from file start
|
base -= sizeof (progs); // offsets are from file start
|
||||||
heap = ((byte *) pr->progs + pr->progs_size + pr->pr_edictareasize);
|
heap = ((byte *) pr->progs + pr->progs_size + pr->pr_edictareasize);
|
||||||
|
|
||||||
|
pr->float_promoted = progs.version == PROG_VERSION;
|
||||||
|
|
||||||
if (pr->edicts) {
|
if (pr->edicts) {
|
||||||
*pr->edicts = (edict_t *)((byte *) pr->progs + pr->progs_size);
|
*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_integer
|
||||||
1, // ev_uinteger
|
1, // ev_uinteger
|
||||||
0, // ev_short value in opcode
|
0, // ev_short value in opcode
|
||||||
|
2, // ev_double
|
||||||
};
|
};
|
||||||
|
|
||||||
VISIBLE const char *pr_type_name[ev_type_count] = {
|
VISIBLE const char *pr_type_name[ev_type_count] = {
|
||||||
|
@ -76,6 +77,7 @@ VISIBLE const char *pr_type_name[ev_type_count] = {
|
||||||
"integer",
|
"integer",
|
||||||
"uinteger",
|
"uinteger",
|
||||||
"short",
|
"short",
|
||||||
|
"double",
|
||||||
"invalid",
|
"invalid",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -102,6 +104,10 @@ VISIBLE opcode_t pr_opcodes[] = {
|
||||||
"%Va",
|
"%Va",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{"*", "mul.d", OP_MUL_D, false,
|
||||||
|
ev_double, ev_double, ev_double,
|
||||||
|
PROG_VERSION,
|
||||||
|
},
|
||||||
{"*", "mul.f", OP_MUL_F, false,
|
{"*", "mul.f", OP_MUL_F, false,
|
||||||
ev_float, ev_float, ev_float,
|
ev_float, ev_float, ev_float,
|
||||||
PROG_ID_VERSION,
|
PROG_ID_VERSION,
|
||||||
|
@ -118,6 +124,14 @@ VISIBLE opcode_t pr_opcodes[] = {
|
||||||
ev_vector, ev_float, ev_vector,
|
ev_vector, ev_float, ev_vector,
|
||||||
PROG_ID_VERSION,
|
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,
|
{"*", "mul.q", OP_MUL_Q, false,
|
||||||
ev_quat, ev_quat, ev_quat,
|
ev_quat, ev_quat, ev_quat,
|
||||||
PROG_VERSION,
|
PROG_VERSION,
|
||||||
|
@ -130,6 +144,14 @@ VISIBLE opcode_t pr_opcodes[] = {
|
||||||
ev_quat, ev_float, ev_quat,
|
ev_quat, ev_float, ev_quat,
|
||||||
PROG_VERSION,
|
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,
|
{"*", "mul.qv", OP_MUL_QV, false,
|
||||||
ev_quat, ev_vector, ev_vector,
|
ev_quat, ev_vector, ev_vector,
|
||||||
PROG_VERSION,
|
PROG_VERSION,
|
||||||
|
@ -145,7 +167,23 @@ VISIBLE opcode_t pr_opcodes[] = {
|
||||||
ev_float, ev_float, ev_float,
|
ev_float, ev_float, ev_float,
|
||||||
PROG_ID_VERSION,
|
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,
|
{"+", "add.f", OP_ADD_F, false,
|
||||||
ev_float, ev_float, ev_float,
|
ev_float, ev_float, ev_float,
|
||||||
PROG_ID_VERSION,
|
PROG_ID_VERSION,
|
||||||
|
@ -163,6 +201,10 @@ VISIBLE opcode_t pr_opcodes[] = {
|
||||||
PROG_VERSION,
|
PROG_VERSION,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{"-", "sub.d", OP_SUB_D, false,
|
||||||
|
ev_double, ev_double, ev_double,
|
||||||
|
PROG_VERSION,
|
||||||
|
},
|
||||||
{"-", "sub.f", OP_SUB_F, false,
|
{"-", "sub.f", OP_SUB_F, false,
|
||||||
ev_float, ev_float, ev_float,
|
ev_float, ev_float, ev_float,
|
||||||
PROG_ID_VERSION,
|
PROG_ID_VERSION,
|
||||||
|
@ -176,6 +218,10 @@ VISIBLE opcode_t pr_opcodes[] = {
|
||||||
PROG_VERSION,
|
PROG_VERSION,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{"==", "eq.d", OP_EQ_D, false,
|
||||||
|
ev_double, ev_double, ev_integer,
|
||||||
|
PROG_VERSION,
|
||||||
|
},
|
||||||
{"==", "eq.f", OP_EQ_F, false,
|
{"==", "eq.f", OP_EQ_F, false,
|
||||||
ev_float, ev_float, ev_integer,
|
ev_float, ev_float, ev_integer,
|
||||||
PROG_ID_VERSION,
|
PROG_ID_VERSION,
|
||||||
|
@ -201,6 +247,10 @@ VISIBLE opcode_t pr_opcodes[] = {
|
||||||
PROG_ID_VERSION,
|
PROG_ID_VERSION,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{"!=", "ne.d", OP_NE_D, false,
|
||||||
|
ev_double, ev_double, ev_integer,
|
||||||
|
PROG_VERSION,
|
||||||
|
},
|
||||||
{"!=", "ne.f", OP_NE_F, false,
|
{"!=", "ne.f", OP_NE_F, false,
|
||||||
ev_float, ev_float, ev_integer,
|
ev_float, ev_float, ev_integer,
|
||||||
PROG_ID_VERSION,
|
PROG_ID_VERSION,
|
||||||
|
@ -226,10 +276,18 @@ VISIBLE opcode_t pr_opcodes[] = {
|
||||||
PROG_ID_VERSION,
|
PROG_ID_VERSION,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{"<=", "le.d", OP_LE_D, false,
|
||||||
|
ev_double, ev_double, ev_integer,
|
||||||
|
PROG_VERSION,
|
||||||
|
},
|
||||||
{"<=", "le.f", OP_LE_F, false,
|
{"<=", "le.f", OP_LE_F, false,
|
||||||
ev_float, ev_float, ev_integer,
|
ev_float, ev_float, ev_integer,
|
||||||
PROG_ID_VERSION,
|
PROG_ID_VERSION,
|
||||||
},
|
},
|
||||||
|
{">=", "ge.d", OP_GE_D, false,
|
||||||
|
ev_double, ev_double, ev_integer,
|
||||||
|
PROG_VERSION,
|
||||||
|
},
|
||||||
{">=", "ge.f", OP_GE_F, false,
|
{">=", "ge.f", OP_GE_F, false,
|
||||||
ev_float, ev_float, ev_integer,
|
ev_float, ev_float, ev_integer,
|
||||||
PROG_ID_VERSION,
|
PROG_ID_VERSION,
|
||||||
|
@ -242,10 +300,18 @@ VISIBLE opcode_t pr_opcodes[] = {
|
||||||
ev_string, ev_string, ev_integer,
|
ev_string, ev_string, ev_integer,
|
||||||
PROG_VERSION,
|
PROG_VERSION,
|
||||||
},
|
},
|
||||||
|
{"<", "lt.d", OP_LT_D, false,
|
||||||
|
ev_double, ev_double, ev_integer,
|
||||||
|
PROG_VERSION,
|
||||||
|
},
|
||||||
{"<", "lt.f", OP_LT_F, false,
|
{"<", "lt.f", OP_LT_F, false,
|
||||||
ev_float, ev_float, ev_integer,
|
ev_float, ev_float, ev_integer,
|
||||||
PROG_ID_VERSION,
|
PROG_ID_VERSION,
|
||||||
},
|
},
|
||||||
|
{">", "gt.d", OP_GT_D, false,
|
||||||
|
ev_double, ev_double, ev_integer,
|
||||||
|
PROG_VERSION,
|
||||||
|
},
|
||||||
{">", "gt.f", OP_GT_F, false,
|
{">", "gt.f", OP_GT_F, false,
|
||||||
ev_float, ev_float, ev_integer,
|
ev_float, ev_float, ev_integer,
|
||||||
PROG_ID_VERSION,
|
PROG_ID_VERSION,
|
||||||
|
@ -264,6 +330,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
||||||
PROG_ID_VERSION,
|
PROG_ID_VERSION,
|
||||||
"%Ga.%Gb(%Ec), %gc",//FIXME %E more flexible?
|
"%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,
|
{".", "load.v", OP_LOAD_V, false,
|
||||||
ev_entity, ev_field, ev_vector,
|
ev_entity, ev_field, ev_vector,
|
||||||
PROG_ID_VERSION,
|
PROG_ID_VERSION,
|
||||||
|
@ -305,6 +376,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
||||||
"%Ga.%Gb(%Ec), %gc",
|
"%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,
|
{".", "loadb.f", OP_LOADB_F, false,
|
||||||
ev_pointer, ev_integer, ev_float,
|
ev_pointer, ev_integer, ev_float,
|
||||||
PROG_VERSION,
|
PROG_VERSION,
|
||||||
|
@ -351,6 +427,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
||||||
"*(%Ga + %Gb), %gc",
|
"*(%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,
|
{".", "loadbi.f", OP_LOADBI_F, false,
|
||||||
ev_pointer, ev_short, ev_float,
|
ev_pointer, ev_short, ev_float,
|
||||||
PROG_VERSION,
|
PROG_VERSION,
|
||||||
|
@ -408,6 +489,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
||||||
PROG_VERSION,
|
PROG_VERSION,
|
||||||
"%Ga, %gc",
|
"%Ga, %gc",
|
||||||
},
|
},
|
||||||
|
{"&", "address.d", OP_ADDRESS_D, false,
|
||||||
|
ev_double, ev_invalid, ev_pointer,
|
||||||
|
PROG_VERSION,
|
||||||
|
"%Ga, %gc",
|
||||||
|
},
|
||||||
{"&", "address.f", OP_ADDRESS_F, false,
|
{"&", "address.f", OP_ADDRESS_F, false,
|
||||||
ev_float, ev_invalid, ev_pointer,
|
ev_float, ev_invalid, ev_pointer,
|
||||||
PROG_VERSION,
|
PROG_VERSION,
|
||||||
|
@ -475,7 +561,32 @@ VISIBLE opcode_t pr_opcodes[] = {
|
||||||
PROG_VERSION,
|
PROG_VERSION,
|
||||||
"%Ga, %gc",
|
"%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,
|
{"=", "store.f", OP_STORE_F, true,
|
||||||
ev_float, ev_float, ev_invalid,
|
ev_float, ev_float, ev_invalid,
|
||||||
PROG_ID_VERSION,
|
PROG_ID_VERSION,
|
||||||
|
@ -522,6 +633,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
||||||
"%Ga, %gb",
|
"%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,
|
{".=", "storep.f", OP_STOREP_F, true,
|
||||||
ev_float, ev_pointer, ev_invalid,
|
ev_float, ev_pointer, ev_invalid,
|
||||||
PROG_ID_VERSION,
|
PROG_ID_VERSION,
|
||||||
|
@ -568,6 +684,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
||||||
"%Ga, *%Gb",
|
"%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,
|
{".=", "storeb.f", OP_STOREB_F, true,
|
||||||
ev_float, ev_pointer, ev_integer,
|
ev_float, ev_pointer, ev_integer,
|
||||||
PROG_VERSION,
|
PROG_VERSION,
|
||||||
|
@ -614,6 +735,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
||||||
"%Ga, *(%Gb + %Gc)",
|
"%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,
|
{".=", "storebi.f", OP_STOREBI_F, true,
|
||||||
ev_float, ev_pointer, ev_short,
|
ev_float, ev_pointer, ev_short,
|
||||||
PROG_VERSION,
|
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,
|
{"!", "not.f", OP_NOT_F, false,
|
||||||
ev_float, ev_invalid, ev_integer,
|
ev_float, ev_invalid, ev_integer,
|
||||||
PROG_ID_VERSION,
|
PROG_ID_VERSION,
|
||||||
|
@ -909,7 +1040,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
||||||
ev_integer, ev_integer, ev_integer,
|
ev_integer, ev_integer, ev_integer,
|
||||||
PROG_VERSION,
|
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,
|
ev_integer, ev_integer, ev_integer,
|
||||||
PROG_VERSION,
|
PROG_VERSION,
|
||||||
},
|
},
|
||||||
|
@ -922,7 +1057,12 @@ VISIBLE opcode_t pr_opcodes[] = {
|
||||||
PROG_VERSION,
|
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,
|
ev_float, ev_float, ev_float,
|
||||||
PROG_VERSION,
|
PROG_VERSION,
|
||||||
},
|
},
|
||||||
|
|
|
@ -122,6 +122,7 @@ PR_ResolveGlobals (progs_t *pr)
|
||||||
pr->pr_params[6] = &pr->pr_globals[OFS_PARM6];
|
pr->pr_params[6] = &pr->pr_globals[OFS_PARM6];
|
||||||
pr->pr_params[7] = &pr->pr_globals[OFS_PARM7];
|
pr->pr_params[7] = &pr->pr_globals[OFS_PARM7];
|
||||||
pr->pr_param_size = OFS_PARM1 - OFS_PARM0;
|
pr->pr_param_size = OFS_PARM1 - OFS_PARM0;
|
||||||
|
pr->pr_param_alignment = 0; // log2
|
||||||
} else {
|
} else {
|
||||||
if (!(def = PR_FindGlobal (pr, sym = ".return")))
|
if (!(def = PR_FindGlobal (pr, sym = ".return")))
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -134,6 +135,9 @@ PR_ResolveGlobals (progs_t *pr)
|
||||||
if (!(def = PR_FindGlobal (pr, sym = ".param_size")))
|
if (!(def = PR_FindGlobal (pr, sym = ".param_size")))
|
||||||
goto error;
|
goto error;
|
||||||
pr->pr_param_size = G_INT (pr, def->ofs);
|
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)
|
if (pr->pr_saved_params)
|
||||||
free (pr->pr_saved_params);
|
free (pr->pr_saved_params);
|
||||||
|
|
|
@ -70,6 +70,7 @@ struct strref_s {
|
||||||
#define FMT_ADDSIGN (1<<3)
|
#define FMT_ADDSIGN (1<<3)
|
||||||
#define FMT_ADDBLANK (1<<4)
|
#define FMT_ADDBLANK (1<<4)
|
||||||
#define FMT_HEX (1<<5)
|
#define FMT_HEX (1<<5)
|
||||||
|
#define FMT_LONG (1<<6)
|
||||||
|
|
||||||
typedef struct fmt_item_s {
|
typedef struct fmt_item_s {
|
||||||
byte type;
|
byte type;
|
||||||
|
@ -81,6 +82,7 @@ typedef struct fmt_item_s {
|
||||||
int integer_var;
|
int integer_var;
|
||||||
unsigned uinteger_var;
|
unsigned uinteger_var;
|
||||||
float float_var;
|
float float_var;
|
||||||
|
double double_var;
|
||||||
} data;
|
} data;
|
||||||
struct fmt_item_s *next;
|
struct fmt_item_s *next;
|
||||||
} fmt_item_t;
|
} fmt_item_t;
|
||||||
|
@ -596,11 +598,19 @@ I_DoPrint (dstring_t *result, fmt_item_t *formatting)
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
dstring_appendstr (tmp, "f");
|
dstring_appendstr (tmp, "f");
|
||||||
PRINT (float);
|
if (current->flags & FMT_LONG) {
|
||||||
|
PRINT (double);
|
||||||
|
} else {
|
||||||
|
PRINT (float);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
dstring_appendstr (tmp, "g");
|
dstring_appendstr (tmp, "g");
|
||||||
PRINT (float);
|
if (current->flags & FMT_LONG) {
|
||||||
|
PRINT (double);
|
||||||
|
} else {
|
||||||
|
PRINT (float);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -639,6 +649,8 @@ free_fmt_item (fmt_item_t *fi)
|
||||||
|
|
||||||
#undef P_var
|
#undef P_var
|
||||||
#define P_var(p,n,t) (args[n]->t##_var)
|
#define P_var(p,n,t) (args[n]->t##_var)
|
||||||
|
#undef P_DOUBLE
|
||||||
|
#define P_DOUBLE(p,n) (*(double *) (args[n]))
|
||||||
VISIBLE void
|
VISIBLE void
|
||||||
PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
|
PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
|
||||||
const char *format, int count, pr_type_t **args)
|
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;
|
int fmt_count = 0;
|
||||||
|
|
||||||
if (!name)
|
if (!name)
|
||||||
name = "PF_InternalSprintf";
|
name = "PR_Sprintf";
|
||||||
|
|
||||||
*fi = new_fmt_item ();
|
*fi = new_fmt_item ();
|
||||||
c = l = format;
|
c = l = format;
|
||||||
|
@ -742,12 +754,19 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
|
||||||
fi = &(*fi)->next;
|
fi = &(*fi)->next;
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
// float
|
// float or double
|
||||||
case 'g':
|
case 'g':
|
||||||
// float, no trailing zeroes, trim "." if nothing
|
// float or double, no trailing zeroes, trim "."
|
||||||
// after
|
// if nothing after
|
||||||
(*fi)->type = *c;
|
(*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++;
|
fmt_count++;
|
||||||
(*fi)->next = new_fmt_item ();
|
(*fi)->next = new_fmt_item ();
|
||||||
|
|
|
@ -42,55 +42,55 @@
|
||||||
#include "rua_internal.h"
|
#include "rua_internal.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bi_sin (progs_t *pr)
|
bi_sinf (progs_t *pr)
|
||||||
{
|
{
|
||||||
R_FLOAT (pr) = sinf (P_FLOAT (pr, 0));
|
R_FLOAT (pr) = sinf (P_FLOAT (pr, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bi_cos (progs_t *pr)
|
bi_cosf (progs_t *pr)
|
||||||
{
|
{
|
||||||
R_FLOAT (pr) = cosf (P_FLOAT (pr, 0));
|
R_FLOAT (pr) = cosf (P_FLOAT (pr, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bi_tan (progs_t *pr)
|
bi_tanf (progs_t *pr)
|
||||||
{
|
{
|
||||||
R_FLOAT (pr) = tanf (P_FLOAT (pr, 0));
|
R_FLOAT (pr) = tanf (P_FLOAT (pr, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bi_asin (progs_t *pr)
|
bi_asinf (progs_t *pr)
|
||||||
{
|
{
|
||||||
R_FLOAT (pr) = asinf (P_FLOAT (pr, 0));
|
R_FLOAT (pr) = asinf (P_FLOAT (pr, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bi_acos (progs_t *pr)
|
bi_acosf (progs_t *pr)
|
||||||
{
|
{
|
||||||
R_FLOAT (pr) = acosf (P_FLOAT (pr, 0));
|
R_FLOAT (pr) = acosf (P_FLOAT (pr, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bi_atan (progs_t *pr)
|
bi_atanf (progs_t *pr)
|
||||||
{
|
{
|
||||||
R_FLOAT (pr) = atanf (P_FLOAT (pr, 0));
|
R_FLOAT (pr) = atanf (P_FLOAT (pr, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bi_atan2 (progs_t *pr)
|
bi_atan2f (progs_t *pr)
|
||||||
{
|
{
|
||||||
R_FLOAT (pr) = atan2f (P_FLOAT (pr, 0), P_FLOAT (pr, 1));
|
R_FLOAT (pr) = atan2f (P_FLOAT (pr, 0), P_FLOAT (pr, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bi_log (progs_t *pr)
|
bi_logf (progs_t *pr)
|
||||||
{
|
{
|
||||||
R_FLOAT (pr) = logf (P_FLOAT (pr, 0));
|
R_FLOAT (pr) = logf (P_FLOAT (pr, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bi_log2 (progs_t *pr)
|
bi_log2f (progs_t *pr)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_LOG2F
|
#ifdef HAVE_LOG2F
|
||||||
R_FLOAT (pr) = log2f (P_FLOAT (pr, 0));
|
R_FLOAT (pr) = log2f (P_FLOAT (pr, 0));
|
||||||
|
@ -100,95 +100,259 @@ bi_log2 (progs_t *pr)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bi_log10 (progs_t *pr)
|
bi_log10f (progs_t *pr)
|
||||||
{
|
{
|
||||||
R_FLOAT (pr) = log10f (P_FLOAT (pr, 0));
|
R_FLOAT (pr) = log10f (P_FLOAT (pr, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bi_pow (progs_t *pr)
|
bi_powf (progs_t *pr)
|
||||||
{
|
{
|
||||||
R_FLOAT (pr) = powf (P_FLOAT (pr, 0), P_FLOAT (pr, 1));
|
R_FLOAT (pr) = powf (P_FLOAT (pr, 0), P_FLOAT (pr, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bi_sqrt (progs_t *pr)
|
bi_sqrtf (progs_t *pr)
|
||||||
{
|
{
|
||||||
R_FLOAT (pr) = sqrtf (P_FLOAT (pr, 0));
|
R_FLOAT (pr) = sqrtf (P_FLOAT (pr, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bi_cbrt (progs_t *pr)
|
bi_cbrtf (progs_t *pr)
|
||||||
{
|
{
|
||||||
R_FLOAT (pr) = cbrtf (P_FLOAT (pr, 0));
|
R_FLOAT (pr) = cbrtf (P_FLOAT (pr, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bi_hypot (progs_t *pr)
|
bi_hypotf (progs_t *pr)
|
||||||
{
|
{
|
||||||
R_FLOAT (pr) = hypotf (P_FLOAT (pr, 0), P_FLOAT (pr, 1));
|
R_FLOAT (pr) = hypotf (P_FLOAT (pr, 0), P_FLOAT (pr, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bi_sinh (progs_t *pr)
|
bi_sinhf (progs_t *pr)
|
||||||
{
|
{
|
||||||
R_FLOAT (pr) = sinhf (P_FLOAT (pr, 0));
|
R_FLOAT (pr) = sinhf (P_FLOAT (pr, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bi_cosh (progs_t *pr)
|
bi_coshf (progs_t *pr)
|
||||||
{
|
{
|
||||||
R_FLOAT (pr) = coshf (P_FLOAT (pr, 0));
|
R_FLOAT (pr) = coshf (P_FLOAT (pr, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bi_tanh (progs_t *pr)
|
bi_tanhf (progs_t *pr)
|
||||||
{
|
{
|
||||||
R_FLOAT (pr) = tanhf (P_FLOAT (pr, 0));
|
R_FLOAT (pr) = tanhf (P_FLOAT (pr, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bi_asinh (progs_t *pr)
|
bi_asinhf (progs_t *pr)
|
||||||
{
|
{
|
||||||
double y = P_FLOAT (pr, 0);
|
double y = P_FLOAT (pr, 0);
|
||||||
R_FLOAT (pr) = logf (y + sqrtf (y * y + 1));
|
R_FLOAT (pr) = logf (y + sqrtf (y * y + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bi_acosh (progs_t *pr)
|
bi_acoshf (progs_t *pr)
|
||||||
{
|
{
|
||||||
double y = P_FLOAT (pr, 0);
|
double y = P_FLOAT (pr, 0);
|
||||||
R_FLOAT (pr) = logf (y + sqrtf (y * y - 1));
|
R_FLOAT (pr) = logf (y + sqrtf (y * y - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bi_atanh (progs_t *pr)
|
bi_atanhf (progs_t *pr)
|
||||||
{
|
{
|
||||||
double y = P_FLOAT (pr, 0);
|
double y = P_FLOAT (pr, 0);
|
||||||
R_FLOAT (pr) = logf ((1 + y) / (1 - y)) / 2;
|
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[] = {
|
static builtin_t builtins[] = {
|
||||||
{"sin", bi_sin, -1},
|
{"sin|f", bi_sinf, -1},
|
||||||
{"cos", bi_cos, -1},
|
{"cos|f", bi_cosf, -1},
|
||||||
{"tan", bi_tan, -1},
|
{"tan|f", bi_tanf, -1},
|
||||||
{"asin", bi_asin, -1},
|
{"asin|f", bi_asinf, -1},
|
||||||
{"acos", bi_acos, -1},
|
{"acos|f", bi_acosf, -1},
|
||||||
{"atan", bi_atan, -1},
|
{"atan|f", bi_atanf, -1},
|
||||||
{"atan2", bi_atan2, -1},
|
{"atan2|ff",bi_atan2f, -1},
|
||||||
{"log", bi_log, -1},
|
{"log|f", bi_logf, -1},
|
||||||
{"log2", bi_log2, -1},
|
{"log2|f", bi_log2f, -1},
|
||||||
{"log10", bi_log10, -1},
|
{"log10|f", bi_log10f, -1},
|
||||||
{"pow", bi_pow, -1},
|
{"pow|ff", bi_powf, -1},
|
||||||
{"sqrt", bi_sqrt, -1},
|
{"sqrt|f", bi_sqrtf, -1},
|
||||||
{"cbrt", bi_cbrt, -1},
|
{"cbrt|f", bi_cbrtf, -1},
|
||||||
{"hypot", bi_hypot, -1},
|
{"hypot|ff",bi_hypotf, -1},
|
||||||
{"sinh", bi_sinh, -1},
|
{"sinh|f", bi_sinhf, -1},
|
||||||
{"cosh", bi_cosh, -1},
|
{"cosh|f", bi_coshf, -1},
|
||||||
{"tanh", bi_tanh, -1},
|
{"tanh|f", bi_tanhf, -1},
|
||||||
{"asinh", bi_asinh, -1},
|
{"asinh|f", bi_asinhf, -1},
|
||||||
{"acosh", bi_acosh, -1},
|
{"acosh|f", bi_acoshf, -1},
|
||||||
{"atanh", bi_atanh, -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}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -439,19 +439,23 @@ X11_SetVidMode (int width, int height)
|
||||||
&vidmodes);
|
&vidmodes);
|
||||||
XF86VidModeGetModeLine (x_disp, x_screen, &dotclock, &orig_data);
|
XF86VidModeGetModeLine (x_disp, x_screen, &dotclock, &orig_data);
|
||||||
|
|
||||||
if (developer->int_val & SYS_VID) {
|
Sys_MaskPrintf (SYS_VID, "VID: %d modes\n", nummodes);
|
||||||
Sys_Printf ("VID: %d modes\n", nummodes);
|
original_mode = -1;
|
||||||
for (i = 0; i < nummodes; i++) {
|
|
||||||
Sys_Printf ("VID: %xx%d\n", vidmodes[i]->hdisplay,
|
|
||||||
vidmodes[i]->vdisplay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < nummodes; i++) {
|
for (i = 0; i < nummodes; i++) {
|
||||||
if ((vidmodes[i]->hdisplay == orig_data.hdisplay) &&
|
if (original_mode == -1
|
||||||
(vidmodes[i]->vdisplay == orig_data.vdisplay)) {
|
&& (vidmodes[i]->hdisplay == orig_data.hdisplay) &&
|
||||||
|
(vidmodes[i]->vdisplay == orig_data.vdisplay)) {
|
||||||
original_mode = i;
|
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",
|
Sys_MaskPrintf (SYS_VID, "VID: Chose video mode: %dx%d\n",
|
||||||
viddef.width, viddef.height);
|
viddef.width, viddef.height);
|
||||||
|
|
||||||
|
if (0) {
|
||||||
XF86VidModeSwitchToMode (x_disp, x_screen,
|
XF86VidModeSwitchToMode (x_disp, x_screen,
|
||||||
vidmodes[best_mode]);
|
vidmodes[best_mode]);
|
||||||
|
}
|
||||||
vidmode_active = true;
|
vidmode_active = true;
|
||||||
X11_SetScreenSaver ();
|
X11_SetScreenSaver ();
|
||||||
} else {
|
} else {
|
||||||
|
@ -594,7 +600,7 @@ X11_RestoreVidMode (void)
|
||||||
#ifdef HAVE_VIDMODE
|
#ifdef HAVE_VIDMODE
|
||||||
if (vidmode_active) {
|
if (vidmode_active) {
|
||||||
X11_RestoreScreenSaver ();
|
X11_RestoreScreenSaver ();
|
||||||
XF86VidModeSwitchToMode (x_disp, x_screen, vidmodes[original_mode]);
|
//XF86VidModeSwitchToMode (x_disp, x_screen, vidmodes[original_mode]);
|
||||||
XFree (vidmodes);
|
XFree (vidmodes);
|
||||||
vidmode_active = false;
|
vidmode_active = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -210,6 +210,11 @@ extern progs_t sv_pr_state;
|
||||||
#define SVentity(e,f) SVFIELD (e, f, entity)
|
#define SVentity(e,f) SVFIELD (e, f, entity)
|
||||||
#define SVvector(e,f) SVFIELD (e, f, vector)
|
#define SVvector(e,f) SVFIELD (e, f, vector)
|
||||||
#define SVinteger(e,f) SVFIELD (e, f, integer)
|
#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 {
|
typedef struct edict_leaf_s {
|
||||||
struct edict_leaf_s *next;
|
struct edict_leaf_s *next;
|
||||||
|
|
|
@ -361,6 +361,9 @@ set_address (sv_def_t *def, void *address)
|
||||||
case ev_quat:
|
case ev_quat:
|
||||||
*(float **)def->field = (float *) address;
|
*(float **)def->field = (float *) address;
|
||||||
break;
|
break;
|
||||||
|
case ev_double:
|
||||||
|
*(double **)def->field = (double *) address;
|
||||||
|
break;
|
||||||
case ev_string:
|
case ev_string:
|
||||||
case ev_entity:
|
case ev_entity:
|
||||||
case ev_field:
|
case ev_field:
|
||||||
|
|
|
@ -195,6 +195,11 @@ extern progs_t sv_pr_state;
|
||||||
#define SVentity(e,f) SVFIELD (e, f, entity)
|
#define SVentity(e,f) SVFIELD (e, f, entity)
|
||||||
#define SVvector(e,f) SVFIELD (e, f, vector)
|
#define SVvector(e,f) SVFIELD (e, f, vector)
|
||||||
#define SVinteger(e,f) SVFIELD (e, f, integer)
|
#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 {
|
typedef struct edict_leaf_s {
|
||||||
struct edict_leaf_s *next;
|
struct edict_leaf_s *next;
|
||||||
|
|
|
@ -371,6 +371,9 @@ set_address (sv_def_t *def, void *address)
|
||||||
case ev_quat:
|
case ev_quat:
|
||||||
*(float **)def->field = (float *) address;
|
*(float **)def->field = (float *) address;
|
||||||
break;
|
break;
|
||||||
|
case ev_double:
|
||||||
|
*(double **)def->field = (double *) address;
|
||||||
|
break;
|
||||||
case ev_string:
|
case ev_string:
|
||||||
case ev_entity:
|
case ev_entity:
|
||||||
case ev_field:
|
case ev_field:
|
||||||
|
|
|
@ -166,7 +166,7 @@ int HUDHandleClass;
|
||||||
if (looping)
|
if (looping)
|
||||||
currentFrame = 0;
|
currentFrame = 0;
|
||||||
else {
|
else {
|
||||||
nextFrameTime = 0.0;
|
nextFrameTime = 0.0f;
|
||||||
currentFrame = 0;
|
currentFrame = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -201,7 +201,7 @@ int HUDHandleClass;
|
||||||
|
|
||||||
- (void) stop
|
- (void) stop
|
||||||
{
|
{
|
||||||
nextFrameTime = 0.0;
|
nextFrameTime = 0.0f;
|
||||||
currentFrame = 0;
|
currentFrame = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
- (id) init
|
- (id) init
|
||||||
{
|
{
|
||||||
[super init];
|
[super init];
|
||||||
damage = (deathmatch > 3) ? 75.0 : 20.0;
|
damage = (deathmatch > 3) ? 75.0f : 20.0f;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
source = s.origin + '0 0 16';
|
source = s.origin + '0 0 16';
|
||||||
|
|
||||||
traceline (source, source + v_forward * 64, NO, s);
|
traceline (source, source + v_forward * 64, NO, s);
|
||||||
if (trace_fraction == 1.0)
|
if (trace_fraction == 1.0f)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
org = trace_endpos - v_forward * 4;
|
org = trace_endpos - v_forward * 4;
|
||||||
|
|
|
@ -60,17 +60,20 @@
|
||||||
/**
|
/**
|
||||||
Returns \a f, rounded down to the next lower integer
|
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
|
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
|
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
|
///\name Exponentials and Logarithms
|
||||||
|
@ -78,32 +81,38 @@
|
||||||
/**
|
/**
|
||||||
Returns the natural log of \a x.
|
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.
|
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.
|
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
|
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
|
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
|
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
|
///\name Trigonometric functions
|
||||||
|
@ -112,40 +121,52 @@
|
||||||
/**
|
/**
|
||||||
Returns the sine of \a x.
|
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.
|
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.
|
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.
|
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.
|
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.
|
Returns the arctangent of \a x.
|
||||||
*/
|
*/
|
||||||
@extern float atan (float x);
|
@extern @overload float atan (float x);
|
||||||
@extern float atan2 (float y, 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
|
Returns the length of the hypotenuse of a right triangle with sides \a x
|
||||||
and \a y. That is, this function returns
|
and \a y. That is, this function returns
|
||||||
<code>sqrt (\a x*\a x + \a y*\a y)</code>.
|
<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
|
///\name Hyperbolic functions
|
||||||
|
@ -153,32 +174,38 @@
|
||||||
/**
|
/**
|
||||||
Returns the hyperbolic sine of \a x
|
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
|
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
|
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
|
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
|
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
|
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
|
///\name Vector Functions
|
||||||
|
|
|
@ -34,3 +34,27 @@ float (float x) atanh = #0;
|
||||||
float (float x) sqrt = #0;
|
float (float x) sqrt = #0;
|
||||||
float (float x) cbrt = #0;
|
float (float x) cbrt = #0;
|
||||||
float (float x, float y) hypot = #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 = {
|
bl_info = {
|
||||||
"name": "Quake MDL format",
|
"name": "Quake MDL format",
|
||||||
"author": "Bill Currie",
|
"author": "Bill Currie",
|
||||||
"blender": (2, 6, 3),
|
"blender": (2, 80, 0),
|
||||||
"api": 35622,
|
"api": 35622,
|
||||||
"location": "File > Import-Export",
|
"location": "File > Import-Export",
|
||||||
"description": "Import-Export Quake MDL (version 6) files. (.mdl)",
|
"description": "Import-Export Quake MDL (version 6) files. (.mdl)",
|
||||||
"warning": "not even alpha",
|
"warning": "still work in progress",
|
||||||
"wiki_url": "",
|
"wiki_url": "",
|
||||||
"tracker_url": "",
|
"tracker_url": "",
|
||||||
# "support": 'OFFICIAL',
|
# "support": 'OFFICIAL',
|
||||||
"category": "Import-Export"}
|
"category": "Import-Export"}
|
||||||
|
|
||||||
# To support reload properly, try to access a package var, if it's there,
|
# To support reload properly, try to access a package var, if it's there,
|
||||||
|
@ -66,28 +66,33 @@ EFFECTS=(
|
||||||
)
|
)
|
||||||
|
|
||||||
class QFMDLSettings(bpy.types.PropertyGroup):
|
class QFMDLSettings(bpy.types.PropertyGroup):
|
||||||
eyeposition = FloatVectorProperty(
|
eyeposition : FloatVectorProperty(
|
||||||
name="Eye Position",
|
name="Eye Position",
|
||||||
description="View possion relative to object origin")
|
description="View possion relative to object origin")
|
||||||
synctype = EnumProperty(
|
synctype : EnumProperty(
|
||||||
items=SYNCTYPE,
|
items=SYNCTYPE,
|
||||||
name="Sync Type",
|
name="Sync Type",
|
||||||
description="Add random time offset for automatic animations")
|
description="Add random time offset for automatic animations")
|
||||||
rotate = BoolProperty(
|
rotate : BoolProperty(
|
||||||
name="Rotate",
|
name="Rotate",
|
||||||
description="Rotate automatically (for pickup items)")
|
description="Rotate automatically (for pickup items)")
|
||||||
effects = EnumProperty(
|
effects : EnumProperty(
|
||||||
items=EFFECTS,
|
items=EFFECTS,
|
||||||
name="Effects",
|
name="Effects",
|
||||||
description="Particle trail effects")
|
description="Particle trail effects")
|
||||||
#doesn't work :(
|
|
||||||
#script = PointerProperty(
|
script : PointerProperty(
|
||||||
# type=bpy.types.Object,
|
type=bpy.types.Text,
|
||||||
# name="Script",
|
|
||||||
# description="Script for animating frames and skins")
|
|
||||||
script = StringProperty(
|
|
||||||
name="Script",
|
name="Script",
|
||||||
description="Script for animating frames and skins")
|
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(
|
xform = BoolProperty(
|
||||||
name="Auto transform",
|
name="Auto transform",
|
||||||
description="Auto-apply location/rotation/scale when exporting",
|
description="Auto-apply location/rotation/scale when exporting",
|
||||||
|
@ -102,7 +107,7 @@ class ImportMDL6(bpy.types.Operator, ImportHelper):
|
||||||
bl_label = "Import MDL"
|
bl_label = "Import MDL"
|
||||||
|
|
||||||
filename_ext = ".mdl"
|
filename_ext = ".mdl"
|
||||||
filter_glob = StringProperty(default="*.mdl", options={'HIDDEN'})
|
filter_glob : StringProperty(default="*.mdl", options={'HIDDEN'})
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
from . import import_mdl
|
from . import import_mdl
|
||||||
|
@ -116,7 +121,7 @@ class ExportMDL6(bpy.types.Operator, ExportHelper):
|
||||||
bl_label = "Export MDL"
|
bl_label = "Export MDL"
|
||||||
|
|
||||||
filename_ext = ".mdl"
|
filename_ext = ".mdl"
|
||||||
filter_glob = StringProperty(default="*.mdl", options={'HIDDEN'})
|
filter_glob : StringProperty(default="*.mdl", options={'HIDDEN'})
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
|
@ -129,10 +134,11 @@ class ExportMDL6(bpy.types.Operator, ExportHelper):
|
||||||
return export_mdl.export_mdl(self, context, **keywords)
|
return export_mdl.export_mdl(self, context, **keywords)
|
||||||
|
|
||||||
class OBJECT_PT_MDLPanel(bpy.types.Panel):
|
class OBJECT_PT_MDLPanel(bpy.types.Panel):
|
||||||
|
bl_label = "MDL Properties"
|
||||||
bl_space_type = 'PROPERTIES'
|
bl_space_type = 'PROPERTIES'
|
||||||
bl_region_type = 'WINDOW'
|
bl_region_type = 'WINDOW'
|
||||||
bl_context = 'object'
|
bl_context = 'object'
|
||||||
bl_label = 'QF MDL'
|
bl_options = {'DEFAULT_CLOSED'}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
|
@ -157,21 +163,28 @@ def menu_func_import(self, context):
|
||||||
def menu_func_export(self, context):
|
def menu_func_export(self, context):
|
||||||
self.layout.operator(ExportMDL6.bl_idname, text="Quake MDL (.mdl)")
|
self.layout.operator(ExportMDL6.bl_idname, text="Quake MDL (.mdl)")
|
||||||
|
|
||||||
|
classes = (
|
||||||
|
QFMDLSettings,
|
||||||
|
OBJECT_PT_MDLPanel,
|
||||||
|
ImportMDL6,
|
||||||
|
ExportMDL6
|
||||||
|
)
|
||||||
|
|
||||||
def register():
|
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.Object.qfmdl = PointerProperty(type=QFMDLSettings)
|
||||||
|
|
||||||
bpy.types.INFO_MT_file_import.append(menu_func_import)
|
bpy.types.TOPBAR_MT_file_import.append(menu_func_import)
|
||||||
bpy.types.INFO_MT_file_export.append(menu_func_export)
|
bpy.types.TOPBAR_MT_file_export.append(menu_func_export)
|
||||||
|
|
||||||
|
|
||||||
def unregister():
|
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.TOPBAR_MT_file_import.remove(menu_func_import)
|
||||||
bpy.types.INFO_MT_file_export.remove(menu_func_export)
|
bpy.types.TOPBAR_MT_file_export.remove(menu_func_export)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
register()
|
register()
|
||||||
|
|
|
@ -27,6 +27,7 @@ from .qfplist import pldata, PListError
|
||||||
from .quakepal import palette
|
from .quakepal import palette
|
||||||
from .quakenorm import map_normal
|
from .quakenorm import map_normal
|
||||||
from .mdl import MDL
|
from .mdl import MDL
|
||||||
|
from .__init__ import SYNCTYPE, EFFECTS
|
||||||
|
|
||||||
def check_faces(mesh):
|
def check_faces(mesh):
|
||||||
#Check that all faces are tris because mdl does not support anything else.
|
#Check that all faces are tris because mdl does not support anything else.
|
||||||
|
@ -35,17 +36,17 @@ def check_faces(mesh):
|
||||||
faces_ok = True
|
faces_ok = True
|
||||||
save_select = []
|
save_select = []
|
||||||
for f in mesh.polygons:
|
for f in mesh.polygons:
|
||||||
save_select.append(f.select)
|
save_select.append(f.select_get())
|
||||||
f.select = False
|
f.select_set('DESELECT')
|
||||||
if len(f.vertices) > 3:
|
if len(f.vertices) > 3:
|
||||||
f.select = True
|
f.select_set('SELECT')
|
||||||
faces_ok = False
|
faces_ok = False
|
||||||
if not faces_ok:
|
if not faces_ok:
|
||||||
mesh.update()
|
mesh.update()
|
||||||
return False
|
return False
|
||||||
#reset selection to what it was before the check.
|
#reset selection to what it was before the check.
|
||||||
for f, s in map(lambda x, y: (x, y), mesh.polygons, save_select):
|
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()
|
mesh.update()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -85,7 +86,7 @@ def null_skin(size):
|
||||||
return skin
|
return skin
|
||||||
|
|
||||||
def active_uv(mesh):
|
def active_uv(mesh):
|
||||||
for uvt in mesh.uv_textures:
|
for uvt in mesh.uv_layers:
|
||||||
if uvt.active:
|
if uvt.active:
|
||||||
return uvt
|
return uvt
|
||||||
return None
|
return None
|
||||||
|
@ -94,6 +95,40 @@ def make_skin(operator, mdl, mesh):
|
||||||
uvt = active_uv(mesh)
|
uvt = active_uv(mesh)
|
||||||
mdl.skinwidth, mdl.skinheight = (4, 4)
|
mdl.skinwidth, mdl.skinheight = (4, 4)
|
||||||
skin = null_skin((mdl.skinwidth, mdl.skinheight))
|
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):
|
if (uvt and uvt.data and uvt.data[0].image):
|
||||||
image = uvt.data[0].image
|
image = uvt.data[0].image
|
||||||
if (uvt.data[0].image.size[0] and uvt.data[0].image.size[1]):
|
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:
|
else:
|
||||||
operator.report({'WARNING'},
|
operator.report({'WARNING'},
|
||||||
"Texture '%s' invalid (missing?)." % image.name)
|
"Texture '%s' invalid (missing?)." % image.name)
|
||||||
|
|
||||||
mdl.skins.append(skin)
|
mdl.skins.append(skin)
|
||||||
|
'''
|
||||||
|
|
||||||
def build_tris(mesh):
|
def build_tris(mesh):
|
||||||
# mdl files have a 1:1 relationship between stverts and 3d verts.
|
# 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)
|
a = Vector(verts[0].r) - Vector(verts[1].r)
|
||||||
b = Vector(verts[2].r) - Vector(verts[1].r)
|
b = Vector(verts[2].r) - Vector(verts[1].r)
|
||||||
c = a.cross(b)
|
c = a.cross(b)
|
||||||
totalarea += (c * c) ** 0.5 / 2.0
|
totalarea += (c @ c) ** 0.5 / 2.0
|
||||||
return totalarea / len(mdl.tris)
|
return totalarea / len(mdl.tris)
|
||||||
|
|
||||||
def get_properties(operator, mdl, obj):
|
def get_properties(operator, mdl, obj):
|
||||||
|
@ -192,16 +229,11 @@ def get_properties(operator, mdl, obj):
|
||||||
| MDL.EFFECTS[obj.qfmdl.effects])
|
| MDL.EFFECTS[obj.qfmdl.effects])
|
||||||
if obj.qfmdl.md16:
|
if obj.qfmdl.md16:
|
||||||
mdl.ident = "MD16"
|
mdl.ident = "MD16"
|
||||||
|
|
||||||
script = obj.qfmdl.script
|
script = obj.qfmdl.script
|
||||||
mdl.script = None
|
mdl.script = None
|
||||||
if script:
|
if script:
|
||||||
try:
|
pl = pldata(script.as_string())
|
||||||
script = bpy.data.texts[script].as_string()
|
|
||||||
except KeyError:
|
|
||||||
operator.report({'ERROR'},
|
|
||||||
"Script '%s' not found." % script)
|
|
||||||
return False
|
|
||||||
pl = pldata(script)
|
|
||||||
try:
|
try:
|
||||||
mdl.script = pl.parse()
|
mdl.script = pl.parse()
|
||||||
except PListError as err:
|
except PListError as err:
|
||||||
|
@ -268,17 +300,29 @@ def process_frame(mdl, scene, frame, vertmap, ingroup = False,
|
||||||
return fr
|
return fr
|
||||||
mdl.frames += fr.frames[:-1]
|
mdl.frames += fr.frames[:-1]
|
||||||
return fr.frames[-1]
|
return fr.frames[-1]
|
||||||
scene.frame_set(int(frameno), frameno - int(frameno))
|
scene.frame_set(int(frameno), subframe = frameno - int(frameno))
|
||||||
mesh = mdl.obj.to_mesh(scene, True, 'PREVIEW') #wysiwyg?
|
depsgraph = bpy.context.evaluated_depsgraph_get()
|
||||||
|
mesh = mdl.obj.evaluated_get(depsgraph).to_mesh() #wysiwyg?
|
||||||
if mdl.obj.qfmdl.xform:
|
if mdl.obj.qfmdl.xform:
|
||||||
mesh.transform(mdl.obj.matrix_world)
|
mesh.transform(mdl.obj.matrix_world)
|
||||||
fr = make_frame(mesh, vertmap)
|
fr = make_frame(mesh, vertmap)
|
||||||
fr.name = name
|
fr.name = name
|
||||||
return fr
|
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):
|
def export_mdl(operator, context, filepath):
|
||||||
obj = context.active_object
|
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):
|
#if not check_faces(mesh):
|
||||||
# operator.report({'ERROR'},
|
# operator.report({'ERROR'},
|
||||||
# "Mesh has faces with more than 3 vertices.")
|
# "Mesh has faces with more than 3 vertices.")
|
||||||
|
@ -287,6 +331,7 @@ def export_mdl(operator, context, filepath):
|
||||||
mdl.obj = obj
|
mdl.obj = obj
|
||||||
if not get_properties(operator, mdl, obj):
|
if not get_properties(operator, mdl, obj):
|
||||||
return {'CANCELLED'}
|
return {'CANCELLED'}
|
||||||
|
|
||||||
mdl.tris, mdl.stverts, vertmap = build_tris(mesh)
|
mdl.tris, mdl.stverts, vertmap = build_tris(mesh)
|
||||||
if mdl.script:
|
if mdl.script:
|
||||||
if 'skins' in mdl.script:
|
if 'skins' in mdl.script:
|
||||||
|
@ -299,13 +344,19 @@ def export_mdl(operator, context, filepath):
|
||||||
if not mdl.skins:
|
if not mdl.skins:
|
||||||
make_skin(operator, mdl, mesh)
|
make_skin(operator, mdl, mesh)
|
||||||
if not mdl.frames:
|
if not mdl.frames:
|
||||||
curframe = context.scene.frame_current
|
scene = context.scene
|
||||||
for fno in range(1, curframe + 1):
|
for fno in range(scene.frame_start, scene.frame_end + 1):
|
||||||
context.scene.frame_set(fno)
|
context.scene.frame_set(fno)
|
||||||
mesh = obj.to_mesh(context.scene, True, 'PREVIEW') #wysiwyg?
|
obj.update_from_editmode()
|
||||||
if mdl.obj.qfmdl.xform:
|
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)
|
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)
|
convert_stverts(mdl, mdl.stverts)
|
||||||
mdl.size = calc_average_area(mdl)
|
mdl.size = calc_average_area(mdl)
|
||||||
scale_verts(mdl)
|
scale_verts(mdl)
|
||||||
|
|
|
@ -39,7 +39,7 @@ def make_verts(mdl, framenum, subframenum=0):
|
||||||
( 0, 0,s.z,o.z),
|
( 0, 0,s.z,o.z),
|
||||||
( 0, 0, 0, 1)))
|
( 0, 0, 0, 1)))
|
||||||
for v in frame.verts:
|
for v in frame.verts:
|
||||||
verts.append(m * Vector(v.r))
|
verts.append(m @ Vector(v.r))
|
||||||
return verts
|
return verts
|
||||||
|
|
||||||
def make_faces(mdl):
|
def make_faces(mdl):
|
||||||
|
@ -87,7 +87,7 @@ def load_skins(mdl):
|
||||||
p[l + 2] = c[2] / 255.0
|
p[l + 2] = c[2] / 255.0
|
||||||
p[l + 3] = 1.0
|
p[l + 3] = 1.0
|
||||||
img.pixels[:] = p[:]
|
img.pixels[:] = p[:]
|
||||||
img.pack(True)
|
img.pack()
|
||||||
img.use_fake_user = True
|
img.use_fake_user = True
|
||||||
|
|
||||||
mdl.images=[]
|
mdl.images=[]
|
||||||
|
@ -98,30 +98,80 @@ def load_skins(mdl):
|
||||||
else:
|
else:
|
||||||
load_skin(skin, "%s_%d" % (mdl.name, i))
|
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):
|
def setup_skins(mdl, uvs):
|
||||||
load_skins(mdl)
|
load_skins(mdl)
|
||||||
img = mdl.images[0] # use the first skin for now
|
# img = mdl.images[0] # use the first skin for now
|
||||||
uvlay = mdl.mesh.uv_textures.new(mdl.name)
|
# uvlay = mdl.mesh.uv_textures.new(mdl.name)
|
||||||
uvloop = mdl.mesh.uv_layers[0]
|
# uvloop = mdl.mesh.uv_layers[0]
|
||||||
for i, texpoly in enumerate(uvlay.data):
|
# 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]
|
poly = mdl.mesh.polygons[i]
|
||||||
mdl_uv = uvs[i]
|
mdl_uv = uvs[i]
|
||||||
texpoly.image = img
|
# texpoly.image = img # TODO: commented out by jazz
|
||||||
for j,k in enumerate(poly.loop_indices):
|
for j,k in enumerate(poly.loop_indices):
|
||||||
uvloop.data[k].uv = mdl_uv[j]
|
uvloop.data[k].uv = mdl_uv[j]
|
||||||
mat = bpy.data.materials.new(mdl.name)
|
|
||||||
mat.diffuse_color = (1,1,1)
|
#Load all skins
|
||||||
mat.use_raytrace = False
|
img_counter = 0
|
||||||
tex = bpy.data.textures.new(mdl.name, 'IMAGE')
|
for i, skin in enumerate(mdl.skins):
|
||||||
tex.extension = 'CLIP'
|
if skin.type:
|
||||||
tex.use_preview_alpha = True
|
mat = setup_main_material(mdl)
|
||||||
tex.image = img
|
emissionNode = mat.node_tree.nodes.new("ShaderNodeEmission")
|
||||||
mat.texture_slots.add()
|
shaderOut = mat.node_tree.nodes["Material Output"]
|
||||||
ts = mat.texture_slots[0]
|
mat.node_tree.nodes.remove(mat.node_tree.nodes["Principled BSDF"])
|
||||||
ts.texture = tex
|
|
||||||
ts.use_map_alpha = True
|
emissionNode.location = (0, 0)
|
||||||
ts.texture_coords = 'UV'
|
shaderOut.location = (200, 0)
|
||||||
mdl.mesh.materials.append(mat)
|
|
||||||
|
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):
|
def make_shape_key(mdl, framenum, subframenum=0):
|
||||||
frame = mdl.frames[framenum]
|
frame = mdl.frames[framenum]
|
||||||
|
@ -133,7 +183,7 @@ def make_shape_key(mdl, framenum, subframenum=0):
|
||||||
name = frame.name
|
name = frame.name
|
||||||
else:
|
else:
|
||||||
frame.name = name
|
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
|
frame.key.value = 0.0
|
||||||
mdl.keys.append(frame.key)
|
mdl.keys.append(frame.key)
|
||||||
s = Vector(mdl.scale)
|
s = Vector(mdl.scale)
|
||||||
|
@ -143,20 +193,25 @@ def make_shape_key(mdl, framenum, subframenum=0):
|
||||||
( 0, 0,s.z,o.z),
|
( 0, 0,s.z,o.z),
|
||||||
( 0, 0, 0, 1)))
|
( 0, 0, 0, 1)))
|
||||||
for i, v in enumerate(frame.verts):
|
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):
|
def build_shape_keys(mdl):
|
||||||
mdl.keys = []
|
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.mesh.shape_keys.name = mdl.name
|
||||||
mdl.obj.active_shape_key_index = 0
|
mdl.obj.active_shape_key_index = 0
|
||||||
|
bpy.context.scene.frame_end = 0
|
||||||
for i, frame in enumerate(mdl.frames):
|
for i, frame in enumerate(mdl.frames):
|
||||||
frame = mdl.frames[i]
|
frame = mdl.frames[i]
|
||||||
if frame.type:
|
if frame.type:
|
||||||
for j in range(len(frame.frames)):
|
for j in range(len(frame.frames)):
|
||||||
make_shape_key(mdl, i, j)
|
make_shape_key(mdl, i, j)
|
||||||
|
bpy.context.scene.frame_end += 1
|
||||||
else:
|
else:
|
||||||
make_shape_key(mdl, i)
|
make_shape_key(mdl, i)
|
||||||
|
bpy.context.scene.frame_end += 1
|
||||||
|
|
||||||
|
bpy.context.scene.frame_start = 1
|
||||||
|
|
||||||
def set_keys(act, data):
|
def set_keys(act, data):
|
||||||
for d in data:
|
for d in data:
|
||||||
|
@ -241,8 +296,8 @@ def write_text(mdl):
|
||||||
/* This script represents the animation data within the model file. It
|
/* This script represents the animation data within the model file. It
|
||||||
is generated automatically on import, and is optional when exporting.
|
is generated automatically on import, and is optional when exporting.
|
||||||
If no script is used when exporting, frames will be exported one per
|
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
|
blender frame from the scene start frame to the scene end frame
|
||||||
one skin will be exported.
|
(inclusive), and one skin per teximage node will be exported.
|
||||||
|
|
||||||
The fundamental format of the script is documented at
|
The fundamental format of the script is documented at
|
||||||
http://quakeforge.net/doxygen/property-list.html
|
http://quakeforge.net/doxygen/property-list.html
|
||||||
|
@ -335,14 +390,14 @@ def set_properties(mdl):
|
||||||
mdl.obj.qfmdl.synctype = 'ST_SYNC'
|
mdl.obj.qfmdl.synctype = 'ST_SYNC'
|
||||||
mdl.obj.qfmdl.rotate = (mdl.flags & MDL.EF_ROTATE) and True or False
|
mdl.obj.qfmdl.rotate = (mdl.flags & MDL.EF_ROTATE) and True or False
|
||||||
mdl.obj.qfmdl.effects = parse_flags(mdl.flags)
|
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")
|
mdl.obj.qfmdl.md16 = (mdl.ident == "MD16")
|
||||||
|
|
||||||
def import_mdl(operator, context, filepath):
|
def import_mdl(operator, context, filepath, **opts):
|
||||||
bpy.context.user_preferences.edit.use_global_undo = False
|
bpy.context.preferences.edit.use_global_undo = False
|
||||||
|
|
||||||
for obj in bpy.context.scene.objects:
|
for obj in bpy.context.scene.collection.objects:
|
||||||
obj.select = False
|
obj.select_set(False)
|
||||||
|
|
||||||
mdl = MDL()
|
mdl = MDL()
|
||||||
if not mdl.read(filepath):
|
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 = bpy.data.meshes.new(mdl.name)
|
||||||
mdl.mesh.from_pydata(verts, [], faces)
|
mdl.mesh.from_pydata(verts, [], faces)
|
||||||
mdl.obj = bpy.data.objects.new(mdl.name, mdl.mesh)
|
mdl.obj = bpy.data.objects.new(mdl.name, mdl.mesh)
|
||||||
bpy.context.scene.objects.link(mdl.obj)
|
|
||||||
bpy.context.scene.objects.active = mdl.obj
|
bpy.context.scene.collection.objects.link(mdl.obj)
|
||||||
mdl.obj.select = True
|
mdl.obj.select_set(True)
|
||||||
|
bpy.context.view_layer.objects.active = mdl.obj
|
||||||
setup_skins(mdl, uvs)
|
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:
|
if len(mdl.frames) > 1 or mdl.frames[0].type:
|
||||||
build_shape_keys(mdl)
|
build_shape_keys(mdl)
|
||||||
merge_frames(mdl)
|
merge_frames(mdl)
|
||||||
|
@ -367,5 +426,5 @@ def import_mdl(operator, context, filepath):
|
||||||
|
|
||||||
mdl.mesh.update()
|
mdl.mesh.update()
|
||||||
|
|
||||||
bpy.context.user_preferences.edit.use_global_undo = True
|
bpy.context.preferences.edit.use_global_undo = True
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
|
@ -109,6 +109,27 @@ defspace_t *defspace_new (ds_type_t type);
|
||||||
*/
|
*/
|
||||||
int defspace_alloc_loc (defspace_t *space, int size);
|
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.
|
/** 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
|
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;
|
etype_t lltype;
|
||||||
union {
|
union {
|
||||||
const char *string_val; ///< string constant
|
const char *string_val; ///< string constant
|
||||||
|
double double_val; ///< double constant
|
||||||
float float_val; ///< float constant
|
float float_val; ///< float constant
|
||||||
float vector_val[3]; ///< vector constant
|
float vector_val[3]; ///< vector constant
|
||||||
int entity_val; ///< entity 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);
|
expr_t *new_string_expr (const char *string_val);
|
||||||
const char *expr_string (expr_t *e) __attribute__((pure));
|
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.
|
/** Create a new float constant expression node.
|
||||||
|
|
||||||
\param float_val The float constant being represented.
|
\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)
|
#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.
|
/** Access a float variable in the object file. Can be assigned to.
|
||||||
|
|
||||||
\par QC type:
|
\par QC type:
|
||||||
|
@ -484,6 +497,8 @@ qfo_t *qfo_new (void);
|
||||||
*/
|
*/
|
||||||
void qfo_delete (qfo_t *qfo);
|
void qfo_delete (qfo_t *qfo);
|
||||||
|
|
||||||
|
__attribute__((const)) int qfo_log2 (unsigned x);
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
#endif//__obj_file_h
|
#endif//__obj_file_h
|
||||||
|
|
|
@ -70,6 +70,11 @@ typedef struct {
|
||||||
qboolean silent; // don't even bother (overrides promote)
|
qboolean silent; // don't even bother (overrides promote)
|
||||||
} notice_options_t;
|
} 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 {
|
typedef struct {
|
||||||
qboolean initial;
|
qboolean initial;
|
||||||
qboolean thread;
|
qboolean thread;
|
||||||
|
@ -88,6 +93,7 @@ typedef struct {
|
||||||
code_options_t code; // Code generation options
|
code_options_t code; // Code generation options
|
||||||
warn_options_t warnings; // Warning options
|
warn_options_t warnings; // Warning options
|
||||||
notice_options_t notices; // Notice options
|
notice_options_t notices; // Notice options
|
||||||
|
bug_options_t bug; // Bug options
|
||||||
blockdot_options_t block_dot; // Statement block flow diagrams
|
blockdot_options_t block_dot; // Statement block flow diagrams
|
||||||
|
|
||||||
int verbosity; // 0=silent, goes up to 2 currently
|
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 GETSTR(s) (pr.strings->strings + (s))
|
||||||
#define D_var(t, d) ((d)->space->data[(d)->offset].t##_var)
|
#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_FLOAT(d) D_var (float, d)
|
||||||
#define D_INT(d) D_var (integer, d)
|
#define D_INT(d) D_var (integer, d)
|
||||||
#define D_VECTOR(d) D_var (vector, 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));
|
const char *optype_str (op_type_e type) __attribute__((const));
|
||||||
|
|
||||||
operand_t *def_operand (struct def_s *def, struct type_s *type);
|
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);
|
operand_t *value_operand (struct ex_value_s *value);
|
||||||
int tempop_overlap (tempop_t *t1, tempop_t *t2) __attribute__((pure));
|
int tempop_overlap (tempop_t *t1, tempop_t *t2) __attribute__((pure));
|
||||||
operand_t *temp_operand (struct type_s *type);
|
operand_t *temp_operand (struct type_s *type);
|
||||||
|
|
|
@ -63,6 +63,7 @@ typedef enum {
|
||||||
typedef struct type_s {
|
typedef struct type_s {
|
||||||
etype_t type; ///< ev_invalid means structure/array etc
|
etype_t type; ///< ev_invalid means structure/array etc
|
||||||
const char *name;
|
const char *name;
|
||||||
|
int alignment; ///< required alignment for instances
|
||||||
/// function/pointer/array/struct types are more complex
|
/// function/pointer/array/struct types are more complex
|
||||||
ty_meta_e meta;
|
ty_meta_e meta;
|
||||||
union {
|
union {
|
||||||
|
@ -98,6 +99,7 @@ typedef struct {
|
||||||
extern type_t type_invalid;
|
extern type_t type_invalid;
|
||||||
extern type_t type_void;
|
extern type_t type_void;
|
||||||
extern type_t type_string;
|
extern type_t type_string;
|
||||||
|
extern type_t type_double;
|
||||||
extern type_t type_float;
|
extern type_t type_float;
|
||||||
extern type_t type_vector;
|
extern type_t type_vector;
|
||||||
extern type_t type_entity;
|
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_void (const type_t *type) __attribute__((pure));
|
||||||
int is_enum (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_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_float (const type_t *type) __attribute__((pure));
|
||||||
int is_scalar (const type_t *type) __attribute__((pure));
|
int is_scalar (const type_t *type) __attribute__((pure));
|
||||||
int is_vector (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 type_s;
|
||||||
|
|
||||||
struct ex_value_s *new_string_val (const char *string_val);
|
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_float_val (float float_val);
|
||||||
struct ex_value_s *new_vector_val (const float *vector_val);
|
struct ex_value_s *new_vector_val (const float *vector_val);
|
||||||
struct ex_value_s *new_entity_val (int entity_val);
|
struct ex_value_s *new_entity_val (int entity_val);
|
||||||
|
|
|
@ -53,7 +53,7 @@ qfcc_DEPENDENCIES= $(QFCC_DEPS)
|
||||||
|
|
||||||
qfprogs_SOURCES= \
|
qfprogs_SOURCES= \
|
||||||
disassemble.c dump_globals.c dump_lines.c dump_modules.c dump_strings.c \
|
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_LDADD= $(QFCC_LIBS)
|
||||||
qfprogs_DEPENDENCIES= $(QFCC_DEPS)
|
qfprogs_DEPENDENCIES= $(QFCC_DEPS)
|
||||||
|
|
||||||
|
|
|
@ -68,28 +68,29 @@ static hashtab_t *category_hash;
|
||||||
static hashtab_t *protocol_hash;
|
static hashtab_t *protocol_hash;
|
||||||
|
|
||||||
// these will be built up further
|
// these will be built up further
|
||||||
type_t type_obj_selector = { ev_invalid, 0, ty_struct};
|
type_t type_obj_selector = { ev_invalid, 0, 0, ty_struct};
|
||||||
type_t type_SEL = { ev_pointer, "SEL", ty_none, {{&type_obj_selector}}};
|
type_t type_SEL = { ev_pointer, "SEL", 1, ty_none, {{&type_obj_selector}}};
|
||||||
type_t type_IMP = { ev_func, "IMP", ty_none,
|
type_t type_IMP = { ev_func, "IMP", 1, ty_none,
|
||||||
{{&type_id, -3, {&type_id, &type_SEL}}}};
|
{{&type_id, -3, {&type_id, &type_SEL}}}};
|
||||||
type_t type_obj_super = { ev_invalid, 0 };
|
type_t type_obj_super = { ev_invalid, 0, 0 };
|
||||||
type_t type_SuperPtr = { ev_pointer, 0, ty_none, {{&type_obj_super}}};
|
type_t type_SuperPtr = { ev_pointer, 0, 1, ty_none, {{&type_obj_super}}};
|
||||||
type_t type_supermsg = { ev_func, ".supermsg", ty_none,
|
type_t type_supermsg = { ev_func, ".supermsg", 1, ty_none,
|
||||||
{{&type_id, -3, {&type_SuperPtr, &type_SEL}}}};
|
{{&type_id, -3, {&type_SuperPtr, &type_SEL}}}};
|
||||||
type_t type_obj_method = { ev_invalid, 0, ty_struct };
|
type_t type_obj_method = { ev_invalid, 0, 0, ty_struct };
|
||||||
type_t type_obj_method_description = { ev_invalid, 0, ty_struct };
|
type_t type_obj_method_description = { ev_invalid, 0, 0, ty_struct };
|
||||||
type_t type_obj_category = { ev_invalid, 0, ty_struct};
|
type_t type_obj_category = { ev_invalid, 0, 0, ty_struct};
|
||||||
type_t type_obj_ivar = { ev_invalid, 0, ty_struct};
|
type_t type_obj_ivar = { ev_invalid, 0, 0, ty_struct};
|
||||||
type_t type_obj_module = { ev_invalid, 0, ty_struct};
|
type_t type_obj_module = { ev_invalid, 0, 0, ty_struct};
|
||||||
type_t type_moduleptr = { ev_pointer, 0, ty_none, {{&type_obj_module}}};
|
type_t type_moduleptr = { ev_pointer, 0, 1, ty_none,
|
||||||
type_t type_obj_exec_class = { ev_func, 0, ty_none,
|
{{&type_obj_module}}};
|
||||||
|
type_t type_obj_exec_class = { ev_func, 0, 1, ty_none,
|
||||||
{{&type_void, 1, { &type_moduleptr }}}};
|
{{&type_void, 1, { &type_moduleptr }}}};
|
||||||
|
|
||||||
type_t type_obj_object = {ev_invalid, 0, ty_struct};
|
type_t type_obj_object = {ev_invalid, 0, 0, ty_struct};
|
||||||
type_t type_id = { ev_pointer, "id", ty_none, {{&type_obj_object}}};
|
type_t type_id = { ev_pointer, "id", 1, ty_none, {{&type_obj_object}}};
|
||||||
type_t type_obj_class = { ev_invalid, 0, ty_struct};
|
type_t type_obj_class = { ev_invalid, 0, 0, ty_struct};
|
||||||
type_t type_Class = { ev_pointer, 0, ty_none, {{&type_obj_class}}};
|
type_t type_Class = { ev_pointer, 0, 1, ty_none, {{&type_obj_class}}};
|
||||||
type_t type_obj_protocol = { ev_invalid, 0, ty_struct};
|
type_t type_obj_protocol = { ev_invalid, 0, 0, ty_struct};
|
||||||
|
|
||||||
int obj_initialized = 0;
|
int obj_initialized = 0;
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#include "qfcc.h"
|
#include "qfcc.h"
|
||||||
#include "strpool.h"
|
#include "strpool.h"
|
||||||
#include "type.h"
|
#include "type.h"
|
||||||
|
#include "value.h"
|
||||||
#include "qc-parse.h"
|
#include "qc-parse.h"
|
||||||
|
|
||||||
typedef expr_t *(*operation_t) (int op, expr_t *e, expr_t *e1, expr_t *e2);
|
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 *
|
static expr_t *
|
||||||
do_op_float (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
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;
|
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 *
|
static expr_t *
|
||||||
do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
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);
|
return do_op_struct (op, e, e1, e2);
|
||||||
if (is_scalar (t1) && is_scalar (t2)) {
|
if (is_scalar (t1) && is_scalar (t2)) {
|
||||||
if (is_enum (t1)) {
|
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_float (op, e, e1, e2);
|
||||||
return do_op_integer (op, e, e1, e2);
|
return do_op_integer (op, e, e1, e2);
|
||||||
}
|
}
|
||||||
if (is_enum (t2)) {
|
if (is_enum (t2)) {
|
||||||
|
if (t1->type == ev_double)
|
||||||
|
return do_op_double (op, e, e1, e2);
|
||||||
if (t1->type == ev_float)
|
if (t1->type == ev_float)
|
||||||
return do_op_float (op, e, e1, e2);
|
return do_op_float (op, e, e1, e2);
|
||||||
return do_op_integer (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_integer
|
||||||
do_op_invalid, // ev_uinteger
|
do_op_invalid, // ev_uinteger
|
||||||
do_op_invalid, // ev_short
|
do_op_invalid, // ev_short
|
||||||
|
do_op_invalid, // ev_double
|
||||||
do_op_invalid, // ev_invalid
|
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_integer
|
||||||
do_op_invalid, // ev_uinteger
|
do_op_invalid, // ev_uinteger
|
||||||
do_op_invalid, // ev_short
|
do_op_invalid, // ev_short
|
||||||
|
do_op_invalid, // ev_double
|
||||||
do_op_invalid, // ev_invalid
|
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_integer
|
||||||
do_op_float, // ev_uinteger
|
do_op_float, // ev_uinteger
|
||||||
do_op_float, // ev_short
|
do_op_float, // ev_short
|
||||||
|
do_op_double, // ev_double
|
||||||
do_op_invalid, // ev_invalid
|
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_integer
|
||||||
do_op_vector, // ev_uinteger
|
do_op_vector, // ev_uinteger
|
||||||
do_op_vector, // ev_short
|
do_op_vector, // ev_short
|
||||||
|
do_op_vector, // ev_double
|
||||||
do_op_invalid, // ev_invalid
|
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_integer
|
||||||
do_op_invalid, // ev_uinteger
|
do_op_invalid, // ev_uinteger
|
||||||
do_op_invalid, // ev_short
|
do_op_invalid, // ev_short
|
||||||
|
do_op_invalid, // ev_double
|
||||||
do_op_invalid, // ev_invalid
|
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_integer
|
||||||
do_op_invalid, // ev_uinteger
|
do_op_invalid, // ev_uinteger
|
||||||
do_op_invalid, // ev_short
|
do_op_invalid, // ev_short
|
||||||
|
do_op_invalid, // ev_double
|
||||||
do_op_invalid, // ev_invalid
|
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_integer
|
||||||
do_op_func, // ev_uinteger
|
do_op_func, // ev_uinteger
|
||||||
do_op_func, // ev_short
|
do_op_func, // ev_short
|
||||||
|
do_op_func, // ev_double
|
||||||
do_op_func, // ev_invalid
|
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_integer
|
||||||
do_op_pointer, // ev_uinteger
|
do_op_pointer, // ev_uinteger
|
||||||
do_op_pointer, // ev_short
|
do_op_pointer, // ev_short
|
||||||
|
do_op_pointer, // ev_double
|
||||||
do_op_pointer, // ev_invalid
|
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_integer
|
||||||
do_op_quaternion, // ev_uinteger
|
do_op_quaternion, // ev_uinteger
|
||||||
do_op_quaternion, // ev_short
|
do_op_quaternion, // ev_short
|
||||||
|
do_op_quaternion, // ev_double
|
||||||
do_op_invalid, // ev_invalid
|
do_op_invalid, // ev_invalid
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1091,6 +1244,7 @@ static operation_t op_integer[ev_type_count] = {
|
||||||
do_op_integer, // ev_integer
|
do_op_integer, // ev_integer
|
||||||
do_op_uinteger, // ev_uinteger
|
do_op_uinteger, // ev_uinteger
|
||||||
do_op_integer, // ev_short
|
do_op_integer, // ev_short
|
||||||
|
do_op_double, // ev_double
|
||||||
do_op_invalid, // ev_invalid
|
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_integer
|
||||||
do_op_uinteger, // ev_uinteger
|
do_op_uinteger, // ev_uinteger
|
||||||
do_op_uinteger, // ev_short
|
do_op_uinteger, // ev_short
|
||||||
|
do_op_double, // ev_double
|
||||||
do_op_invalid, // ev_invalid
|
do_op_invalid, // ev_invalid
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1123,6 +1278,24 @@ static operation_t op_short[ev_type_count] = {
|
||||||
do_op_integer, // ev_integer
|
do_op_integer, // ev_integer
|
||||||
do_op_uinteger, // ev_uinteger
|
do_op_uinteger, // ev_uinteger
|
||||||
do_op_short, // ev_short
|
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
|
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_integer
|
||||||
do_op_compound, // ev_uinteger
|
do_op_compound, // ev_uinteger
|
||||||
do_op_compound, // ev_short
|
do_op_compound, // ev_short
|
||||||
|
do_op_compound, // ev_double
|
||||||
do_op_compound, // ev_invalid
|
do_op_compound, // ev_invalid
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1155,6 +1329,7 @@ static operation_t *do_op[ev_type_count] = {
|
||||||
op_integer, // ev_integer
|
op_integer, // ev_integer
|
||||||
op_uinteger, // ev_uinteger
|
op_uinteger, // ev_uinteger
|
||||||
op_short, // ev_short
|
op_short, // ev_short
|
||||||
|
op_double, // ev_double
|
||||||
op_compound, // ev_invalid
|
op_compound, // ev_invalid
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1203,13 +1378,15 @@ static expr_t *
|
||||||
uop_float (int op, expr_t *e, expr_t *e1)
|
uop_float (int op, expr_t *e, expr_t *e1)
|
||||||
{
|
{
|
||||||
static int valid[] = { '+', '-', '!', '~', 'C', 0 };
|
static int valid[] = { '+', '-', '!', '~', 'C', 0 };
|
||||||
|
type_t *type;
|
||||||
|
|
||||||
if (!valid_op (op, valid))
|
if (!valid_op (op, valid))
|
||||||
return error (e1, "invalid unary operator for float: %s",
|
return error (e1, "invalid unary operator for float: %s",
|
||||||
get_op_string (op));
|
get_op_string (op));
|
||||||
if (op == '+')
|
if (op == '+')
|
||||||
return e1;
|
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");
|
return error (e1, "invalid cast of float");
|
||||||
if (!is_constant (e1))
|
if (!is_constant (e1))
|
||||||
return e;
|
return e;
|
||||||
|
@ -1222,7 +1399,11 @@ uop_float (int op, expr_t *e, expr_t *e1)
|
||||||
case '~':
|
case '~':
|
||||||
return new_float_expr (~(int) expr_float (e1));
|
return new_float_expr (~(int) expr_float (e1));
|
||||||
case 'C':
|
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");
|
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");
|
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 *
|
static expr_t *
|
||||||
uop_compound (int op, expr_t *e, expr_t *e1)
|
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_integer, // ev_integer
|
||||||
uop_uinteger, // ev_uinteger
|
uop_uinteger, // ev_uinteger
|
||||||
uop_short, // ev_short
|
uop_short, // ev_short
|
||||||
|
uop_double, // ev_double
|
||||||
uop_compound, // ev_invalid
|
uop_compound, // ev_invalid
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1487,7 +1701,7 @@ fold_constants (expr_t *e)
|
||||||
|
|
||||||
if (t1 >= ev_type_count || t2 >= ev_type_count
|
if (t1 >= ev_type_count || t2 >= ev_type_count
|
||||||
|| !do_op[t1] || !do_op[t1][t2])
|
|| !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 do_op[t1][t2] (op, e, e1, e2);
|
||||||
}
|
}
|
||||||
return e;
|
return e;
|
||||||
|
|
|
@ -148,11 +148,17 @@ new_def (const char *name, type_t *type, defspace_t *space,
|
||||||
|
|
||||||
if (storage != sc_extern) {
|
if (storage != sc_extern) {
|
||||||
int size = type_size (type);
|
int size = type_size (type);
|
||||||
|
int alignment = type->alignment;
|
||||||
|
|
||||||
if (!size) {
|
if (!size) {
|
||||||
error (0, "%s has incomplete type", name);
|
error (0, "%s has incomplete type", name);
|
||||||
size = 1;
|
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;
|
return def;
|
||||||
|
@ -199,16 +205,20 @@ temp_def (type_t *type)
|
||||||
def_t *temp;
|
def_t *temp;
|
||||||
defspace_t *space = current_func->symtab->space;
|
defspace_t *space = current_func->symtab->space;
|
||||||
int size = type_size (type);
|
int size = type_size (type);
|
||||||
|
int alignment = type->alignment;
|
||||||
|
|
||||||
if (size < 1 || size > 4) {
|
if (size < 1 || size > 4) {
|
||||||
internal_error (0, "%d invalid size for temp def", size);
|
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])) {
|
if ((temp = current_func->temp_defs[size - 1])) {
|
||||||
current_func->temp_defs[size - 1] = temp->temp_next;
|
current_func->temp_defs[size - 1] = temp->temp_next;
|
||||||
temp->temp_next = 0;
|
temp->temp_next = 0;
|
||||||
} else {
|
} else {
|
||||||
ALLOC (16384, def_t, defs, temp);
|
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;
|
||||||
space->def_tail = &temp->next;
|
space->def_tail = &temp->next;
|
||||||
temp->name = save_string (va (".tmp%d", current_func->temp_num++));
|
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);
|
init_elements (sym->s.def, init);
|
||||||
sym->s.def->initialized = 1;
|
sym->s.def->initialized = 1;
|
||||||
} else {
|
} 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");
|
error (init, "type mismatch in initializer");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -575,8 +586,20 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space,
|
||||||
// fold_constants takes care of int/float conversions
|
// fold_constants takes care of int/float conversions
|
||||||
append_expr (local_expr, fold_constants (init));
|
append_expr (local_expr, fold_constants (init));
|
||||||
} else {
|
} 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
|
if (init->type != ex_value) { //FIXME enum etc
|
||||||
error (0, "non-constant initializier");
|
internal_error (0, "initializier not a value");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (init->e.value->lltype == ev_pointer
|
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);
|
reloc_def_field (init->e.value->v.pointer.def, sym->s.def);
|
||||||
} else {
|
} else {
|
||||||
ex_value_t *v = init->e.value;
|
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))
|
if (is_scalar (sym->type))
|
||||||
v = convert_value (v, sym->type);
|
v = convert_value (v, sym->type);
|
||||||
if (v->lltype == ev_string) {
|
if (v->lltype == ev_string) {
|
||||||
|
|
|
@ -63,6 +63,33 @@ typedef struct locref_s {
|
||||||
static defspace_t *spaces_freelist;
|
static defspace_t *spaces_freelist;
|
||||||
static locref_t *locrefs_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
|
#define GROW 1024
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -98,9 +125,8 @@ grow_space_virtual (defspace_t *space)
|
||||||
defspace_t *
|
defspace_t *
|
||||||
defspace_new (ds_type_t type)
|
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->def_tail = &space->defs;
|
||||||
space->type = type;
|
space->type = type;
|
||||||
if (type == ds_backed) {
|
if (type == ds_backed) {
|
||||||
|
@ -116,33 +142,59 @@ defspace_new (ds_type_t type)
|
||||||
int
|
int
|
||||||
defspace_alloc_loc (defspace_t *space, int size)
|
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 *loc;
|
||||||
locref_t **l = &space->free_locs;
|
locref_t **l = &space->free_locs;
|
||||||
|
|
||||||
if (size <= 0)
|
if (size <= 0)
|
||||||
internal_error (0, "invalid number of words requested: %d", size);
|
internal_error (0, "invalid number of words requested: %d", size);
|
||||||
while (*l && (*l)->size < size)
|
if (alignment <= 0)
|
||||||
l = &(*l)->next;
|
internal_error (0, "invalid alignment requested: %d", alignment);
|
||||||
if ((loc = *l)) {
|
while ((loc = *l)) {
|
||||||
ofs = (*l)->ofs;
|
ofs = loc->ofs;
|
||||||
if ((*l)->size == size) {
|
pad = alignment * ((ofs + alignment - 1) / alignment) - ofs;
|
||||||
loc = *l;
|
// exact fit, so just shrink the block or remove it if there is no
|
||||||
*l = (*l)->next;
|
// padding (any padding remains free)
|
||||||
FREE (locrefs, loc);
|
if (size + pad == loc->size) {
|
||||||
} else {
|
if (!pad) {
|
||||||
(*l)->ofs += size;
|
*l = loc->next;
|
||||||
(*l)->size -= size;
|
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;
|
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->size > space->max_size) {
|
||||||
if (!space->grow || !space->grow (space))
|
if (!space->grow || !space->grow (space))
|
||||||
internal_error (0, "unable to allocate %d words", size);
|
internal_error (0, "unable to allocate %d words", size);
|
||||||
}
|
}
|
||||||
return ofs;
|
if (pad) {
|
||||||
|
*l = new_locref (ofs, pad, 0);
|
||||||
|
}
|
||||||
|
return ofs + pad;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -184,17 +236,13 @@ defspace_free_loc (defspace_t *space, int ofs, int size)
|
||||||
loc->size += loc->next->size;
|
loc->size += loc->next->size;
|
||||||
loc = loc->next;
|
loc = loc->next;
|
||||||
*l = loc->next;
|
*l = loc->next;
|
||||||
FREE (locrefs, loc);
|
del_locref (loc);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// insert a new free block for the location to be freed
|
// insert a new free block for the location to be freed
|
||||||
ALLOC (1024, locref_t, locrefs, loc);
|
*l = new_locref (ofs, size, *l);
|
||||||
loc->ofs = ofs;
|
|
||||||
loc->size = size;
|
|
||||||
loc->next = *l;
|
|
||||||
*l = loc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -141,17 +141,39 @@ _debug (expr_t *e, const char *file, int line, const char *fmt, ...)
|
||||||
va_end (args);
|
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
|
void
|
||||||
_bug (expr_t *e, const char *file, int line, const char *fmt, ...)
|
_bug (expr_t *e, const char *file, int line, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
report_function (e);
|
if (options.bug.silent)
|
||||||
|
return;
|
||||||
|
|
||||||
va_start (args, fmt);
|
va_start (args, fmt);
|
||||||
|
if (options.bug.promote) {
|
||||||
|
__internal_error (e, file, line, fmt, args);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
dstring_t *message = dstring_new ();
|
dstring_t *message = dstring_new ();
|
||||||
|
|
||||||
|
report_function (e);
|
||||||
|
|
||||||
format_message (message, "BUG", e, fmt, args);
|
format_message (message, "BUG", e, fmt, args);
|
||||||
dasprintf (message, " (%s:%d)", file, line);
|
dasprintf (message, " (%s:%d)", file, line);
|
||||||
if (bug_hook) {
|
if (bug_hook) {
|
||||||
|
@ -211,19 +233,9 @@ _internal_error (expr_t *e, const char *file, int line, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
report_function (e);
|
|
||||||
|
|
||||||
va_start (args, fmt);
|
va_start (args, fmt);
|
||||||
{
|
__internal_error (e, file, line, fmt, args);
|
||||||
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);
|
|
||||||
}
|
|
||||||
va_end (args);
|
va_end (args);
|
||||||
abort ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_t *
|
expr_t *
|
||||||
|
|
|
@ -88,6 +88,7 @@ get_op_string (int op)
|
||||||
case '*': return "*";
|
case '*': return "*";
|
||||||
case '/': return "/";
|
case '/': return "/";
|
||||||
case '%': return "%";
|
case '%': return "%";
|
||||||
|
case MOD: return "%%";
|
||||||
case '&': return "&";
|
case '&': return "&";
|
||||||
case '|': 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:
|
case ev_string:
|
||||||
label = va ("\\\"%s\\\"", quote_string (e->e.value->v.string_val));
|
label = va ("\\\"%s\\\"", quote_string (e->e.value->v.string_val));
|
||||||
break;
|
break;
|
||||||
|
case ev_double:
|
||||||
|
label = va ("f %g", e->e.value->v.double_val);
|
||||||
|
break;
|
||||||
case ev_float:
|
case ev_float:
|
||||||
label = va ("f %g", e->e.value->v.float_val);
|
label = va ("f %g", e->e.value->v.float_val);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -97,6 +97,9 @@ dump_def (progs_t *pr, ddef_t *def, int indent)
|
||||||
case ev_float:
|
case ev_float:
|
||||||
comment = va (" %g", G_FLOAT (pr, offset));
|
comment = va (" %g", G_FLOAT (pr, offset));
|
||||||
break;
|
break;
|
||||||
|
case ev_double:
|
||||||
|
comment = va (" %.17g", G_DOUBLE (pr, offset));
|
||||||
|
break;
|
||||||
case ev_vector:
|
case ev_vector:
|
||||||
comment = va (" '%g %g %g'",
|
comment = va (" '%g %g %g'",
|
||||||
G_VECTOR (pr, offset)[0],
|
G_VECTOR (pr, offset)[0],
|
||||||
|
@ -214,7 +217,8 @@ dump_functions (progs_t *pr)
|
||||||
else
|
else
|
||||||
count = func->numparms;
|
count = func->numparms;
|
||||||
for (j = 0; j < count; j++)
|
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);
|
printf (") %d @ %x", func->locals, func->parm_start);
|
||||||
puts ("");
|
puts ("");
|
||||||
if (pr->debug) {
|
if (pr->debug) {
|
||||||
|
|
|
@ -611,6 +611,15 @@ new_string_expr (const char *string_val)
|
||||||
return e;
|
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 *
|
expr_t *
|
||||||
new_float_expr (float float_val)
|
new_float_expr (float float_val)
|
||||||
{
|
{
|
||||||
|
@ -768,6 +777,10 @@ new_short_expr (short short_val)
|
||||||
int
|
int
|
||||||
is_constant (expr_t *e)
|
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
|
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_const)
|
||||||
|| (e->type == ex_symbol && e->e.symbol->sy_type == sy_var
|
|| (e->type == ex_symbol && e->e.symbol->sy_type == sy_var
|
||||||
|
@ -845,6 +858,23 @@ is_float_val (expr_t *e)
|
||||||
return 0;
|
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
|
float
|
||||||
expr_float (expr_t *e)
|
expr_float (expr_t *e)
|
||||||
{
|
{
|
||||||
|
@ -1024,8 +1054,6 @@ new_alias_expr (type_t *type, expr_t *expr)
|
||||||
{
|
{
|
||||||
expr_t *alias;
|
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 = new_unary_expr ('A', expr);
|
||||||
alias->e.expr.type = type;
|
alias->e.expr.type = type;
|
||||||
//if (expr->type == ex_uexpr && expr->e.expr.op == 'A')
|
//if (expr->type == ex_uexpr && expr->e.expr.op == 'A')
|
||||||
|
@ -1276,6 +1304,9 @@ test_expr (expr_t *e)
|
||||||
}
|
}
|
||||||
new = new_float_expr (0);
|
new = new_float_expr (0);
|
||||||
break;
|
break;
|
||||||
|
case ev_double:
|
||||||
|
new = new_double_expr (0);
|
||||||
|
break;
|
||||||
case ev_vector:
|
case ev_vector:
|
||||||
new = new_vector_expr (zero);
|
new = new_vector_expr (zero);
|
||||||
break;
|
break;
|
||||||
|
@ -1610,6 +1641,8 @@ unary_expr (int op, expr_t *e)
|
||||||
case ev_func:
|
case ev_func:
|
||||||
case ev_pointer:
|
case ev_pointer:
|
||||||
internal_error (e, "type check failed!");
|
internal_error (e, "type check failed!");
|
||||||
|
case ev_double:
|
||||||
|
return new_double_expr (-expr_double (e));
|
||||||
case ev_float:
|
case ev_float:
|
||||||
return new_float_expr (-expr_float (e));
|
return new_float_expr (-expr_float (e));
|
||||||
case ev_vector:
|
case ev_vector:
|
||||||
|
@ -1676,6 +1709,8 @@ unary_expr (int op, expr_t *e)
|
||||||
case ev_string:
|
case ev_string:
|
||||||
s = expr_string (e);
|
s = expr_string (e);
|
||||||
return new_integer_expr (!s || !s[0]);
|
return new_integer_expr (!s || !s[0]);
|
||||||
|
case ev_double:
|
||||||
|
return new_integer_expr (!expr_double (e));
|
||||||
case ev_float:
|
case ev_float:
|
||||||
return new_integer_expr (!expr_float (e));
|
return new_integer_expr (!expr_float (e));
|
||||||
case ev_vector:
|
case ev_vector:
|
||||||
|
@ -1735,6 +1770,7 @@ unary_expr (int op, expr_t *e)
|
||||||
case ev_func:
|
case ev_func:
|
||||||
case ev_pointer:
|
case ev_pointer:
|
||||||
case ev_vector:
|
case ev_vector:
|
||||||
|
case ev_double:
|
||||||
return error (e, "invalid type for unary ~");
|
return error (e, "invalid type for unary ~");
|
||||||
case ev_float:
|
case ev_float:
|
||||||
return new_float_expr (~(int) expr_float (e));
|
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)
|
if (is_integer_val (e)
|
||||||
&& options.code.progsversion == PROG_ID_VERSION)
|
&& options.code.progsversion == PROG_ID_VERSION)
|
||||||
convert_int (e);
|
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)
|
if (is_integer_val (e) && options.warnings.vararg_integer)
|
||||||
warning (e, "passing integer constant into ... function");
|
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;
|
e = e1->e.expr.e2;
|
||||||
break;
|
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 &");
|
return error (e1, "invalid type for unary &");
|
||||||
case ex_uexpr:
|
case ex_uexpr:
|
||||||
if (e1->e.expr.op == '.') {
|
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->e.value = convert_value (val, type);
|
||||||
e->type = ex_value;
|
e->type = ex_value;
|
||||||
c = e;
|
c = e;
|
||||||
} else if ((is_float (type) && is_integral (e_type))
|
} else if (is_integral (type) && is_integral (e_type)) {
|
||||||
|| (is_integral (type) && is_float (e_type))) {
|
c = new_alias_expr (type, e);
|
||||||
|
} else if (is_scalar (type) && is_scalar (e_type)) {
|
||||||
c = new_unary_expr ('C', e);
|
c = new_unary_expr ('C', e);
|
||||||
c->e.expr.type = type;
|
c->e.expr.type = type;
|
||||||
} else if (e->type == ex_uexpr && e->e.expr.op == '.') {
|
} 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 (type_assignable (dst_type, src_type)) {
|
||||||
if (is_scalar (dst_type) && is_scalar (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
|
// the types are different but cast-compatible
|
||||||
expr_t *new = cast_expr (dst_type, src);
|
expr_t *new = cast_expr (dst_type, src);
|
||||||
// the cast was a no-op, so the types are compatible at the
|
// 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 *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 *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[] = {
|
static expr_type_t string_string[] = {
|
||||||
{'+', &type_string},
|
{'+', &type_string},
|
||||||
|
@ -68,6 +69,7 @@ static expr_type_t float_float[] = {
|
||||||
{'|', &type_float},
|
{'|', &type_float},
|
||||||
{'^', &type_float},
|
{'^', &type_float},
|
||||||
{'%', &type_float},
|
{'%', &type_float},
|
||||||
|
{MOD, &type_float},
|
||||||
{SHL, &type_float},
|
{SHL, &type_float},
|
||||||
{SHR, &type_float},
|
{SHR, &type_float},
|
||||||
{EQ, &type_integer},
|
{EQ, &type_integer},
|
||||||
|
@ -86,7 +88,6 @@ static expr_type_t float_vector[] = {
|
||||||
|
|
||||||
static expr_type_t float_quat[] = {
|
static expr_type_t float_quat[] = {
|
||||||
{'*', &type_quaternion},
|
{'*', &type_quaternion},
|
||||||
{'/', 0, 0, 0, inverse_multiply},
|
|
||||||
{0, 0}
|
{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},
|
{'^', &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},
|
{SHL, &type_float, 0, &type_float},
|
||||||
{SHR, &type_float, 0, &type_float},
|
{SHR, &type_float, 0, &type_float},
|
||||||
{EQ, &type_integer, 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_uinteger float_integer
|
||||||
#define float_short 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[] = {
|
static expr_type_t vector_float[] = {
|
||||||
{'*', &type_vector},
|
{'*', &type_vector},
|
||||||
{'/', 0, 0, 0, inverse_multiply},
|
{'/', 0, 0, 0, inverse_multiply},
|
||||||
|
@ -131,6 +149,12 @@ static expr_type_t vector_vector[] = {
|
||||||
#define vector_uinteger vector_float
|
#define vector_uinteger vector_float
|
||||||
#define vector_short 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[] = {
|
static expr_type_t entity_entity[] = {
|
||||||
{EQ, &type_integer},
|
{EQ, &type_integer},
|
||||||
{NE, &type_integer},
|
{NE, &type_integer},
|
||||||
|
@ -170,7 +194,7 @@ static expr_type_t pointer_integer[] = {
|
||||||
|
|
||||||
static expr_type_t quat_float[] = {
|
static expr_type_t quat_float[] = {
|
||||||
{'*', &type_quaternion},
|
{'*', &type_quaternion},
|
||||||
{'/', &type_quaternion},
|
{'/', 0, 0, 0, inverse_multiply},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -190,12 +214,18 @@ static expr_type_t quat_quat[] = {
|
||||||
|
|
||||||
static expr_type_t quat_integer[] = {
|
static expr_type_t quat_integer[] = {
|
||||||
{'*', &type_quaternion, 0, &type_float},
|
{'*', &type_quaternion, 0, &type_float},
|
||||||
{'/', &type_quaternion, 0, &type_float},
|
{'/', 0, 0, 0, inverse_multiply},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
#define quat_uinteger quat_integer
|
#define quat_uinteger quat_integer
|
||||||
#define quat_short 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[] = {
|
static expr_type_t integer_float[] = {
|
||||||
{'+', &type_float, &type_float, 0},
|
{'+', &type_float, &type_float, 0},
|
||||||
{'-', &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},
|
{'^', &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?
|
{SHL, &type_integer, 0, &type_integer}, //FIXME?
|
||||||
{SHR, &type_integer, 0, &type_integer}, //FIXME?
|
{SHR, &type_integer, 0, &type_integer}, //FIXME?
|
||||||
{EQ, &type_integer, &type_float, 0},
|
{EQ, &type_integer, &type_float, 0},
|
||||||
|
@ -228,7 +259,6 @@ static expr_type_t integer_pointer[] = {
|
||||||
|
|
||||||
static expr_type_t integer_quat[] = {
|
static expr_type_t integer_quat[] = {
|
||||||
{'*', &type_quaternion, &type_float, 0},
|
{'*', &type_quaternion, &type_float, 0},
|
||||||
{'/', &type_quaternion, &type_float, 0},
|
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -241,6 +271,7 @@ static expr_type_t integer_integer[] = {
|
||||||
{'|', &type_integer},
|
{'|', &type_integer},
|
||||||
{'^', &type_integer},
|
{'^', &type_integer},
|
||||||
{'%', &type_integer},
|
{'%', &type_integer},
|
||||||
|
{MOD, &type_integer},
|
||||||
{SHL, &type_integer},
|
{SHL, &type_integer},
|
||||||
{SHR, &type_integer},
|
{SHR, &type_integer},
|
||||||
{EQ, &type_integer},
|
{EQ, &type_integer},
|
||||||
|
@ -261,6 +292,7 @@ static expr_type_t integer_uinteger[] = {
|
||||||
{'|', &type_integer},
|
{'|', &type_integer},
|
||||||
{'^', &type_integer},
|
{'^', &type_integer},
|
||||||
{'%', &type_integer},
|
{'%', &type_integer},
|
||||||
|
{MOD, &type_integer},
|
||||||
{SHL, &type_integer},
|
{SHL, &type_integer},
|
||||||
{SHR, &type_integer},
|
{SHR, &type_integer},
|
||||||
{EQ, &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},
|
{'^', &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},
|
{SHL, &type_integer, 0, &type_integer},
|
||||||
{SHR, &type_integer, 0, &type_integer},
|
{SHR, &type_integer, 0, &type_integer},
|
||||||
{EQ, &type_integer, 0, &type_integer},
|
{EQ, &type_integer, 0, &type_integer},
|
||||||
|
@ -292,6 +325,22 @@ static expr_type_t integer_short[] = {
|
||||||
{0, 0}
|
{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_float integer_float
|
||||||
#define uinteger_vector integer_vector
|
#define uinteger_vector integer_vector
|
||||||
#define uinteger_pointer integer_pointer
|
#define uinteger_pointer integer_pointer
|
||||||
|
@ -306,6 +355,7 @@ static expr_type_t uinteger_integer[] = {
|
||||||
{'|', &type_integer},
|
{'|', &type_integer},
|
||||||
{'^', &type_integer},
|
{'^', &type_integer},
|
||||||
{'%', &type_integer},
|
{'%', &type_integer},
|
||||||
|
{MOD, &type_integer},
|
||||||
{SHL, &type_uinteger},
|
{SHL, &type_uinteger},
|
||||||
{SHR, &type_uinteger},
|
{SHR, &type_uinteger},
|
||||||
{EQ, &type_integer},
|
{EQ, &type_integer},
|
||||||
|
@ -326,6 +376,7 @@ static expr_type_t uinteger_uinteger[] = {
|
||||||
{'|', &type_uinteger},
|
{'|', &type_uinteger},
|
||||||
{'^', &type_uinteger},
|
{'^', &type_uinteger},
|
||||||
{'%', &type_uinteger},
|
{'%', &type_uinteger},
|
||||||
|
{MOD, &type_uinteger},
|
||||||
{SHL, &type_uinteger},
|
{SHL, &type_uinteger},
|
||||||
{SHR, &type_uinteger},
|
{SHR, &type_uinteger},
|
||||||
{EQ, &type_integer},
|
{EQ, &type_integer},
|
||||||
|
@ -337,6 +388,7 @@ static expr_type_t uinteger_uinteger[] = {
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
#define uinteger_short uinteger_integer
|
#define uinteger_short uinteger_integer
|
||||||
|
#define uinteger_double integer_double
|
||||||
|
|
||||||
#define short_float integer_float
|
#define short_float integer_float
|
||||||
#define short_vector integer_vector
|
#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},
|
{'^', &type_integer, &type_integer, 0},
|
||||||
{'%', &type_integer, &type_integer, 0},
|
{'%', &type_integer, &type_integer, 0},
|
||||||
|
{MOD, &type_integer, &type_integer, 0},
|
||||||
{SHL, &type_short},
|
{SHL, &type_short},
|
||||||
{SHR, &type_short},
|
{SHR, &type_short},
|
||||||
{EQ, &type_integer, &type_integer, 0},
|
{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},
|
{'^', &type_uinteger, &type_uinteger, 0},
|
||||||
{'%', &type_uinteger, &type_uinteger, 0},
|
{'%', &type_uinteger, &type_uinteger, 0},
|
||||||
|
{MOD, &type_uinteger, &type_uinteger, 0},
|
||||||
{SHL, &type_short},
|
{SHL, &type_short},
|
||||||
{SHR, &type_short},
|
{SHR, &type_short},
|
||||||
{EQ, &type_integer, &type_uinteger, 0},
|
{EQ, &type_integer, &type_uinteger, 0},
|
||||||
|
@ -392,6 +446,7 @@ static expr_type_t short_short[] = {
|
||||||
{'|', &type_short},
|
{'|', &type_short},
|
||||||
{'^', &type_short},
|
{'^', &type_short},
|
||||||
{'%', &type_short},
|
{'%', &type_short},
|
||||||
|
{MOD, &type_short},
|
||||||
{SHL, &type_short},
|
{SHL, &type_short},
|
||||||
{SHR, &type_short},
|
{SHR, &type_short},
|
||||||
{EQ, &type_integer},
|
{EQ, &type_integer},
|
||||||
|
@ -402,8 +457,69 @@ static expr_type_t short_short[] = {
|
||||||
{GT, &type_integer},
|
{GT, &type_integer},
|
||||||
{0, 0}
|
{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
|
0, // ev_void
|
||||||
string_string,
|
string_string,
|
||||||
0, // ev_float
|
0, // ev_float
|
||||||
|
@ -416,9 +532,10 @@ static expr_type_t *string_x[] = {
|
||||||
0, // ev_integer
|
0, // ev_integer
|
||||||
0, // ev_uinteger
|
0, // ev_uinteger
|
||||||
0, // ev_short
|
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_void
|
||||||
0, // ev_string
|
0, // ev_string
|
||||||
float_float,
|
float_float,
|
||||||
|
@ -431,9 +548,10 @@ static expr_type_t *float_x[] = {
|
||||||
float_integer,
|
float_integer,
|
||||||
float_uinteger,
|
float_uinteger,
|
||||||
float_short,
|
float_short,
|
||||||
|
float_double,
|
||||||
};
|
};
|
||||||
|
|
||||||
static expr_type_t *vector_x[] = {
|
static expr_type_t *vector_x[ev_type_count] = {
|
||||||
0, // ev_void
|
0, // ev_void
|
||||||
0, // ev_string
|
0, // ev_string
|
||||||
vector_float,
|
vector_float,
|
||||||
|
@ -446,9 +564,10 @@ static expr_type_t *vector_x[] = {
|
||||||
vector_integer,
|
vector_integer,
|
||||||
vector_uinteger,
|
vector_uinteger,
|
||||||
vector_short,
|
vector_short,
|
||||||
|
vector_double,
|
||||||
};
|
};
|
||||||
|
|
||||||
static expr_type_t *entity_x[] = {
|
static expr_type_t *entity_x[ev_type_count] = {
|
||||||
0, // ev_void
|
0, // ev_void
|
||||||
0, // ev_string
|
0, // ev_string
|
||||||
0, // ev_float
|
0, // ev_float
|
||||||
|
@ -461,9 +580,10 @@ static expr_type_t *entity_x[] = {
|
||||||
0, // ev_integer
|
0, // ev_integer
|
||||||
0, // ev_uinteger
|
0, // ev_uinteger
|
||||||
0, // ev_short
|
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_void
|
||||||
0, // ev_string
|
0, // ev_string
|
||||||
0, // ev_float
|
0, // ev_float
|
||||||
|
@ -476,9 +596,10 @@ static expr_type_t *field_x[] = {
|
||||||
0, // ev_integer
|
0, // ev_integer
|
||||||
0, // ev_uinteger
|
0, // ev_uinteger
|
||||||
0, // ev_short
|
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_void
|
||||||
0, // ev_string
|
0, // ev_string
|
||||||
0, // ev_float
|
0, // ev_float
|
||||||
|
@ -491,9 +612,10 @@ static expr_type_t *funcx[] = {
|
||||||
0, // ev_integer
|
0, // ev_integer
|
||||||
0, // ev_uinteger
|
0, // ev_uinteger
|
||||||
0, // ev_short
|
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_void
|
||||||
0, // ev_string
|
0, // ev_string
|
||||||
0, // ev_float
|
0, // ev_float
|
||||||
|
@ -506,9 +628,10 @@ static expr_type_t *pointer_x[] = {
|
||||||
pointer_integer,
|
pointer_integer,
|
||||||
pointer_uinteger,
|
pointer_uinteger,
|
||||||
pointer_short,
|
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_void
|
||||||
0, // ev_string
|
0, // ev_string
|
||||||
quat_float,
|
quat_float,
|
||||||
|
@ -521,9 +644,10 @@ static expr_type_t *quat_x[] = {
|
||||||
quat_integer,
|
quat_integer,
|
||||||
quat_uinteger,
|
quat_uinteger,
|
||||||
quat_short,
|
quat_short,
|
||||||
|
quat_double,
|
||||||
};
|
};
|
||||||
|
|
||||||
static expr_type_t *integer_x[] = {
|
static expr_type_t *integer_x[ev_type_count] = {
|
||||||
0, // ev_void
|
0, // ev_void
|
||||||
0, // ev_string
|
0, // ev_string
|
||||||
integer_float,
|
integer_float,
|
||||||
|
@ -536,9 +660,10 @@ static expr_type_t *integer_x[] = {
|
||||||
integer_integer,
|
integer_integer,
|
||||||
integer_uinteger,
|
integer_uinteger,
|
||||||
integer_short,
|
integer_short,
|
||||||
|
integer_double,
|
||||||
};
|
};
|
||||||
|
|
||||||
static expr_type_t *uinteger_x[] = {
|
static expr_type_t *uinteger_x[ev_type_count] = {
|
||||||
0, // ev_void
|
0, // ev_void
|
||||||
0, // ev_string
|
0, // ev_string
|
||||||
uinteger_float,
|
uinteger_float,
|
||||||
|
@ -551,9 +676,10 @@ static expr_type_t *uinteger_x[] = {
|
||||||
uinteger_integer,
|
uinteger_integer,
|
||||||
uinteger_uinteger,
|
uinteger_uinteger,
|
||||||
uinteger_short,
|
uinteger_short,
|
||||||
|
uinteger_double,
|
||||||
};
|
};
|
||||||
|
|
||||||
static expr_type_t *short_x[] = {
|
static expr_type_t *short_x[ev_type_count] = {
|
||||||
0, // ev_void
|
0, // ev_void
|
||||||
0, // ev_string
|
0, // ev_string
|
||||||
short_float,
|
short_float,
|
||||||
|
@ -566,21 +692,39 @@ static expr_type_t *short_x[] = {
|
||||||
short_integer,
|
short_integer,
|
||||||
short_uinteger,
|
short_uinteger,
|
||||||
short_short,
|
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
|
0, // ev_void
|
||||||
string_x,
|
string_x,
|
||||||
float_x,
|
float_x,
|
||||||
vector_x,
|
vector_x,
|
||||||
entity_x,
|
entity_x,
|
||||||
field_x,
|
field_x,
|
||||||
funcx,
|
func_x,
|
||||||
pointer_x,
|
pointer_x,
|
||||||
quat_x,
|
quat_x,
|
||||||
integer_x,
|
integer_x,
|
||||||
uinteger_x,
|
uinteger_x,
|
||||||
short_x,
|
short_x,
|
||||||
|
double_x
|
||||||
};
|
};
|
||||||
|
|
||||||
static expr_t *
|
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));
|
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 *
|
static expr_t *
|
||||||
invalid_binary_expr (int op, expr_t *e1, expr_t *e2)
|
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) {
|
switch (op) {
|
||||||
case '%':
|
case '%':
|
||||||
{
|
{
|
||||||
expr_t *tmp1, *tmp2, *tmp3, *tmp4, *t1, *t2;
|
expr_t *tmp1, *tmp2;
|
||||||
e = new_block_expr ();
|
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);
|
tmp1 = new_temp_def_expr (&type_float);
|
||||||
tmp2 = 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));
|
append_expr (e, assign_expr (tmp1, binary_expr ('/', e1, e2)));
|
||||||
e1 = binary_expr ('&', t1, t1);
|
append_expr (e, assign_expr (tmp2, binary_expr ('&', tmp1, tmp1)));
|
||||||
append_expr (e, assign_expr (tmp1, e1));
|
e->e.block.result = binary_expr ('-', e1, binary_expr ('*', e2, tmp2));
|
||||||
|
|
||||||
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;
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -798,9 +954,9 @@ binary_expr (int op, expr_t *e1, expr_t *e2)
|
||||||
et1 = low_level_type (t1);
|
et1 = low_level_type (t1);
|
||||||
et2 = low_level_type (t2);
|
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);
|
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);
|
return invalid_binary_expr(op, e1, e2);
|
||||||
expr_type = binary_expr_types[et1][et2];
|
expr_type = binary_expr_types[et1][et2];
|
||||||
while (expr_type->op && expr_type->op != op)
|
while (expr_type->op && expr_type->op != op)
|
||||||
|
|
|
@ -158,6 +158,7 @@ parse_params (type_t *type, param_t *parms)
|
||||||
|
|
||||||
new = new_type ();
|
new = new_type ();
|
||||||
new->type = ev_func;
|
new->type = ev_func;
|
||||||
|
new->alignment = 1;
|
||||||
new->t.func.type = type;
|
new->t.func.type = type;
|
||||||
new->t.func.num_params = 0;
|
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++)
|
for (func_count = 0; funcs[func_count]; func_count++)
|
||||||
;
|
;
|
||||||
if (func_count < 2) {
|
if (func_count < 2) {
|
||||||
free (funcs);
|
f = (overloaded_function_t *) funcs[0];
|
||||||
return fexpr;
|
if (func_count && !f->overloaded) {
|
||||||
|
free (funcs);
|
||||||
|
return fexpr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
type.t.func.type = ((overloaded_function_t *) funcs[0])->type->t.func.type;
|
type.t.func.type = ((overloaded_function_t *) funcs[0])->type->t.func.type;
|
||||||
dummy.type = find_type (&type);
|
dummy.type = find_type (&type);
|
||||||
|
|
|
@ -665,7 +665,7 @@ get_def_type (qfo_t *qfo, pointer_t type)
|
||||||
return ev_invalid;
|
return ev_invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __attribute__((pure)) etype_t
|
static __attribute__((pure)) int
|
||||||
get_type_size (qfo_t *qfo, pointer_t type)
|
get_type_size (qfo_t *qfo, pointer_t type)
|
||||||
{
|
{
|
||||||
qfot_type_t *type_def;
|
qfot_type_t *type_def;
|
||||||
|
@ -701,6 +701,62 @@ get_type_size (qfo_t *qfo, pointer_t type)
|
||||||
return 0;
|
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
|
static void
|
||||||
function_params (qfo_t *qfo, qfo_func_t *func, dfunction_t *df)
|
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;
|
df->numparms = num_params = type->t.func.num_params;
|
||||||
if (num_params < 0)
|
if (num_params < 0)
|
||||||
num_params = ~num_params;
|
num_params = ~num_params;
|
||||||
for (i = 0; i < num_params; i++)
|
for (i = 0; i < num_params; i++) {
|
||||||
df->parm_size[i] = get_type_size (qfo, type->t.func.param_types[i]);
|
df->parm_size[i] = get_parmsize (qfo, type->t.func.param_types[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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 *
|
dprograms_t *
|
||||||
qfo_to_progs (qfo_t *qfo, int *size)
|
qfo_to_progs (qfo_t *qfo, int *size)
|
||||||
{
|
{
|
||||||
|
@ -811,6 +876,7 @@ qfo_to_progs (qfo_t *qfo, int *size)
|
||||||
dprograms_t *progs;
|
dprograms_t *progs;
|
||||||
qfo_def_t *types_def = 0;
|
qfo_def_t *types_def = 0;
|
||||||
unsigned i, j;
|
unsigned i, j;
|
||||||
|
unsigned near_data_size = 0;
|
||||||
unsigned locals_size = 0;
|
unsigned locals_size = 0;
|
||||||
int locals_start;
|
int locals_start;
|
||||||
unsigned big_locals = 0;
|
unsigned big_locals = 0;
|
||||||
|
@ -827,9 +893,8 @@ qfo_to_progs (qfo_t *qfo, int *size)
|
||||||
progs->numfunctions = qfo->num_funcs + 1;
|
progs->numfunctions = qfo->num_funcs + 1;
|
||||||
progs->numstrings = qfo->spaces[qfo_strings_space].data_size;
|
progs->numstrings = qfo->spaces[qfo_strings_space].data_size;
|
||||||
progs->numglobals = qfo->spaces[qfo_near_data_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 = align_globals_size (progs->numglobals);
|
||||||
progs->numglobals += qfo->spaces[qfo_type_space].data_size;
|
locals_start = progs->numglobals;
|
||||||
locals_start = qfo->spaces[qfo_near_data_space].data_size;
|
|
||||||
for (i = qfo_num_spaces; i < qfo->num_spaces; i++) {
|
for (i = qfo_num_spaces; i < qfo->num_spaces; i++) {
|
||||||
if (options.code.local_merging) {
|
if (options.code.local_merging) {
|
||||||
if (locals_size < qfo->spaces[i].data_size) {
|
if (locals_size < qfo->spaces[i].data_size) {
|
||||||
|
@ -837,11 +902,14 @@ qfo_to_progs (qfo_t *qfo, int *size)
|
||||||
big_locals = i;
|
big_locals = i;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
locals_size += qfo->spaces[i].data_size;
|
locals_size += align_globals_size (qfo->spaces[i].data_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
progs->numglobals += locals_size;
|
progs->numglobals += locals_size;
|
||||||
|
near_data_size = progs->numglobals;
|
||||||
progs->numglobals = RUP (progs->numglobals, 16 / sizeof (pr_type_t));
|
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;
|
progs->entityfields = qfo->spaces[qfo_entity_space].data_size;
|
||||||
*size += progs->numstatements * sizeof (dstatement_t);
|
*size += progs->numstatements * sizeof (dstatement_t);
|
||||||
*size += progs->numglobaldefs * sizeof (ddef_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;
|
progs->ofs_globals = data - (byte *) progs;
|
||||||
globals = (pr_type_t*) data;
|
globals = (pr_type_t*) data;
|
||||||
locals = globals + qfo->spaces[qfo_near_data_space].data_size;
|
locals = globals + locals_start;
|
||||||
far_data = locals + locals_size;
|
far_data = globals + near_data_size;
|
||||||
type_data = far_data + qfo->spaces[qfo_far_data_space].data_size;
|
type_data = far_data + qfo->spaces[qfo_far_data_space].data_size;
|
||||||
|
|
||||||
memcpy (strings, qfo->spaces[qfo_strings_space].d.strings,
|
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++)
|
for (j = 0; j < space->num_defs; j++)
|
||||||
space->defs[j].offset += locals_start;
|
space->defs[j].offset += locals_start;
|
||||||
if (!options.code.local_merging)
|
if (!options.code.local_merging)
|
||||||
locals_start += df->locals;
|
locals_start += align_globals_size (df->locals);
|
||||||
df->profile = 0;
|
df->profile = 0;
|
||||||
df->s_name = qf->name;
|
df->s_name = qf->name;
|
||||||
df->s_file = qf->file;
|
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,
|
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].data_size * sizeof (pr_type_t));
|
||||||
qfo->spaces[qfo_near_data_space].d.data = globals;
|
qfo->spaces[qfo_near_data_space].d.data = globals;
|
||||||
// lcear locals data
|
// clear locals data
|
||||||
memset (locals, 0, locals_size * sizeof (pr_type_t));
|
memset (locals, 0, locals_size * sizeof (pr_type_t));
|
||||||
// copy far data
|
// copy far data
|
||||||
memcpy (far_data, qfo->spaces[qfo_far_data_space].d.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 global defs\n", progs->numglobaldefs);
|
||||||
printf ("%6i fielddefs\n", progs->numfielddefs);
|
printf ("%6i fielddefs\n", progs->numfielddefs);
|
||||||
printf ("%6i globals\n", progs->numglobals);
|
printf ("%6i globals\n", progs->numglobals);
|
||||||
printf (" %6i near globals\n",
|
printf (" %6i near globals\n", near_data_size);
|
||||||
qfo->spaces[qfo_near_data_space].data_size + locals_size);
|
|
||||||
printf (" %6i locals size%s\n", locals_size, big_function);
|
printf (" %6i locals size%s\n", locals_size, big_function);
|
||||||
printf (" %6i far globals\n",
|
printf (" %6i far globals\n",
|
||||||
qfo->spaces[qfo_far_data_space].data_size);
|
qfo->spaces[qfo_far_data_space].data_size);
|
||||||
|
|
|
@ -69,11 +69,13 @@ enum {
|
||||||
OPT_PROGDEFS,
|
OPT_PROGDEFS,
|
||||||
OPT_QCCX_ESCAPES,
|
OPT_QCCX_ESCAPES,
|
||||||
OPT_TRADITIONAL,
|
OPT_TRADITIONAL,
|
||||||
|
OPT_BUG,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct option const long_options[] = {
|
static struct option const long_options[] = {
|
||||||
{"advanced", no_argument, 0, OPT_ADVANCED},
|
{"advanced", no_argument, 0, OPT_ADVANCED},
|
||||||
{"block-dot", optional_argument, 0, OPT_BLOCK_DOT},
|
{"block-dot", optional_argument, 0, OPT_BLOCK_DOT},
|
||||||
|
{"bug", required_argument, 0, OPT_BUG},
|
||||||
{"code", required_argument, 0, 'C'},
|
{"code", required_argument, 0, 'C'},
|
||||||
{"cpp", required_argument, 0, OPT_CPP},
|
{"cpp", required_argument, 0, OPT_CPP},
|
||||||
{"define", required_argument, 0, 'D'},
|
{"define", required_argument, 0, 'D'},
|
||||||
|
@ -139,6 +141,7 @@ usage (int status)
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
" --advanced Advanced Ruamoko mode\n"
|
" --advanced Advanced Ruamoko mode\n"
|
||||||
" default for separate compilation mode\n"
|
" default for separate compilation mode\n"
|
||||||
|
" --bug OPTION,... Set bug options\n"
|
||||||
" -C, --code OPTION,... Set code generation options\n"
|
" -C, --code OPTION,... Set code generation options\n"
|
||||||
" -c Only compile, don't link\n"
|
" -c Only compile, don't link\n"
|
||||||
" --cpp CPPSPEC cpp execution command line\n"
|
" --cpp CPPSPEC cpp execution command line\n"
|
||||||
|
@ -264,6 +267,21 @@ notice_usage (void)
|
||||||
exit (0);
|
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
|
static void
|
||||||
add_file (const char *file)
|
add_file (const char *file)
|
||||||
{
|
{
|
||||||
|
@ -590,6 +608,23 @@ DecodeArgs (int argc, char **argv)
|
||||||
free (opts);
|
free (opts);
|
||||||
}
|
}
|
||||||
break;
|
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=
|
case OPT_CPP: // --cpp=
|
||||||
cpp_name = save_string (optarg);
|
cpp_name = save_string (optarg);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -39,14 +39,25 @@
|
||||||
#endif
|
#endif
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "QF/alloc.h"
|
||||||
#include "QF/pr_comp.h"
|
#include "QF/pr_comp.h"
|
||||||
|
|
||||||
#include "diagnostic.h"
|
#include "diagnostic.h"
|
||||||
#include "opcodes.h"
|
#include "opcodes.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "pragma.h"
|
#include "pragma.h"
|
||||||
|
#include "strpool.h"
|
||||||
#include "type.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
|
static void
|
||||||
set_traditional (int traditional)
|
set_traditional (int traditional)
|
||||||
{
|
{
|
||||||
|
@ -73,20 +84,58 @@ set_traditional (int traditional)
|
||||||
opcode_init (); // reset the opcode table
|
opcode_init (); // reset the opcode table
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
pragma (const char *id)
|
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")) {
|
if (!strcmp (id, "traditional")) {
|
||||||
set_traditional (2);
|
set_traditional (2);
|
||||||
return;
|
} else if (!strcmp (id, "extended")) {
|
||||||
}
|
|
||||||
if (!strcmp (id, "extended")) {
|
|
||||||
set_traditional (1);
|
set_traditional (1);
|
||||||
return;
|
} else if (!strcmp (id, "advanced")) {
|
||||||
}
|
|
||||||
if (!strcmp (id, "advanced")) {
|
|
||||||
set_traditional (0);
|
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]
|
X [0-9a-fA-F]
|
||||||
ID [a-zA-Z_][a-zA-Z_0-9]*
|
ID [a-zA-Z_][a-zA-Z_0-9]*
|
||||||
FLOAT ({D}+|{D}*\.{D}+|{D}+\.{D}*)([eE]{m}?{D}+)?
|
FLOAT ({D}+|{D}*\.{D}+|{D}+\.{D}*)([eE]{m}?{D}+)?
|
||||||
|
FLOATf {FLOAT}[fF]
|
||||||
|
FLOATd {FLOAT}[dD]
|
||||||
INT ({D}+|0[xX]{X}+|0[bB]{B})
|
INT ({D}+|0[xX]{X}+|0[bB]{B})
|
||||||
RANGE \.\.
|
RANGE \.\.
|
||||||
ELLIPSIS \.\.\.
|
ELLIPSIS \.\.\.
|
||||||
|
@ -136,10 +138,35 @@ STRING \"(\\.|[^"\\])*\"
|
||||||
}
|
}
|
||||||
|
|
||||||
{FLOAT} {
|
{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);
|
float f = strtof (yytext, 0);
|
||||||
qc_yylval.expr = new_float_expr (f);
|
qc_yylval.expr = new_float_expr (f);
|
||||||
return VALUE;
|
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} {
|
{ID} {
|
||||||
int tok = keyword_or_id(yytext);
|
int tok = keyword_or_id(yytext);
|
||||||
|
@ -189,6 +216,11 @@ STRING \"(\\.|[^"\\])*\"
|
||||||
return ASX;
|
return ASX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"%%=" {
|
||||||
|
qc_yylval.op = MOD;
|
||||||
|
return ASX;
|
||||||
|
}
|
||||||
|
|
||||||
"<<=" {
|
"<<=" {
|
||||||
qc_yylval.op = SHL;
|
qc_yylval.op = SHL;
|
||||||
return ASX;
|
return ASX;
|
||||||
|
@ -204,6 +236,11 @@ STRING \"(\\.|[^"\\])*\"
|
||||||
return yytext[0];
|
return yytext[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"%%" {
|
||||||
|
qc_yylval.pointer = 0; // ensure pointer vals are null
|
||||||
|
return MOD;
|
||||||
|
}
|
||||||
|
|
||||||
{ELLIPSIS} return ELLIPSIS;
|
{ELLIPSIS} return ELLIPSIS;
|
||||||
|
|
||||||
"<<" return SHL;
|
"<<" return SHL;
|
||||||
|
@ -245,9 +282,12 @@ STRING \"(\\.|[^"\\])*\"
|
||||||
write_frame_macros (s);
|
write_frame_macros (s);
|
||||||
BEGIN (GRAB_OTHER); // ignore rest of line
|
BEGIN (GRAB_OTHER); // ignore rest of line
|
||||||
}
|
}
|
||||||
<PRAGMA>{ID} { pragma (yytext); }
|
<PRAGMA>{ID} { pragma_add_arg (yytext); }
|
||||||
|
|
||||||
<*>\r*\n {
|
<*>\r*\n {
|
||||||
|
if (YY_START == PRAGMA) {
|
||||||
|
pragma_process ();
|
||||||
|
}
|
||||||
pr.source_line++;
|
pr.source_line++;
|
||||||
BEGIN (INITIAL);
|
BEGIN (INITIAL);
|
||||||
}
|
}
|
||||||
|
@ -333,6 +373,7 @@ static keyword_t at_keywords[] = {
|
||||||
// be supported (sanely) by v6 progs.
|
// be supported (sanely) by v6 progs.
|
||||||
static keyword_t qf_keywords[] = {
|
static keyword_t qf_keywords[] = {
|
||||||
{"quaternion", TYPE, &type_quaternion},
|
{"quaternion", TYPE, &type_quaternion},
|
||||||
|
{"double", TYPE, &type_double},
|
||||||
{"int", TYPE, &type_integer },
|
{"int", TYPE, &type_integer },
|
||||||
{"unsigned", TYPE, &type_integer },//FIXME
|
{"unsigned", TYPE, &type_integer },//FIXME
|
||||||
{"function", TYPE, &type_function },
|
{"function", TYPE, &type_function },
|
||||||
|
|
|
@ -135,7 +135,7 @@ int yylex (void);
|
||||||
|
|
||||||
%left SHL SHR
|
%left SHL SHR
|
||||||
%left '+' '-'
|
%left '+' '-'
|
||||||
%left '*' '/' '%'
|
%left '*' '/' '%' MOD
|
||||||
%right <op> SIZEOF UNARY INCOP
|
%right <op> SIZEOF UNARY INCOP
|
||||||
%left HYPERUNARY
|
%left HYPERUNARY
|
||||||
%left '.' '(' '['
|
%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 '^' 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
|
texpr
|
||||||
|
|
|
@ -418,8 +418,11 @@ finish_link (void)
|
||||||
flags = (QFOD_GLOBAL | QFOD_CONSTANT | QFOD_INITIALIZED | QFOD_NOSAVE);
|
flags = (QFOD_GLOBAL | QFOD_CONSTANT | QFOD_INITIALIZED | QFOD_NOSAVE);
|
||||||
if (options.code.progsversion != PROG_ID_VERSION) {
|
if (options.code.progsversion != PROG_ID_VERSION) {
|
||||||
pr_int_t param_size = type_size (&type_param);
|
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,
|
linker_add_def (".param_size", &type_integer, flags,
|
||||||
¶m_size);
|
¶m_size);
|
||||||
|
linker_add_def (".param_alignment", &type_integer, flags,
|
||||||
|
¶m_alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.code.debug) {
|
if (options.code.debug) {
|
||||||
|
|
|
@ -87,6 +87,8 @@ operand_string (operand_t *op)
|
||||||
case ev_string:
|
case ev_string:
|
||||||
return va ("\"%s\"",
|
return va ("\"%s\"",
|
||||||
quote_string (op->o.value->v.string_val));
|
quote_string (op->o.value->v.string_val));
|
||||||
|
case ev_double:
|
||||||
|
return va ("%g", op->o.value->v.double_val);
|
||||||
case ev_float:
|
case ev_float:
|
||||||
return va ("%g", op->o.value->v.float_val);
|
return va ("%g", op->o.value->v.float_val);
|
||||||
case ev_vector:
|
case ev_vector:
|
||||||
|
@ -159,6 +161,9 @@ print_operand (operand_t *op)
|
||||||
case ev_string:
|
case ev_string:
|
||||||
printf ("\"%s\"", op->o.value->v.string_val);
|
printf ("\"%s\"", op->o.value->v.string_val);
|
||||||
break;
|
break;
|
||||||
|
case ev_double:
|
||||||
|
printf ("%g", op->o.value->v.double_val);
|
||||||
|
break;
|
||||||
case ev_float:
|
case ev_float:
|
||||||
printf ("%g", op->o.value->v.float_val);
|
printf ("%g", op->o.value->v.float_val);
|
||||||
break;
|
break;
|
||||||
|
@ -313,6 +318,15 @@ def_operand (def_t *def, type_t *type)
|
||||||
return op;
|
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 *
|
operand_t *
|
||||||
value_operand (ex_value_t *value)
|
value_operand (ex_value_t *value)
|
||||||
{
|
{
|
||||||
|
@ -389,7 +403,7 @@ alias_operand (type_t *type, operand_t *op)
|
||||||
operand_t *aop;
|
operand_t *aop;
|
||||||
|
|
||||||
if (type_size (type) != type_size (op->type)) {
|
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));
|
" (%d, %d)", type_size (type), type_size (op->type));
|
||||||
}
|
}
|
||||||
aop = new_operand (op_alias);
|
aop = new_operand (op_alias);
|
||||||
|
@ -425,6 +439,7 @@ convert_op (int op)
|
||||||
case '*': return "*";
|
case '*': return "*";
|
||||||
case '/': return "/";
|
case '/': return "/";
|
||||||
case '%': return "%";
|
case '%': return "%";
|
||||||
|
case MOD: return "%%";
|
||||||
case '&': return "&";
|
case '&': return "&";
|
||||||
case '|': 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)
|
while (def->alias)
|
||||||
def = def->alias;
|
def = def->alias;
|
||||||
*op = def_operand (alias_def (def, type, offset), 0);
|
*op = def_operand (alias_def (def, type, offset), 0);
|
||||||
|
} else if (aop->op_type == op_value) {
|
||||||
|
*op = value_operand (aop->o.value);
|
||||||
} else {
|
} else {
|
||||||
internal_error (e, "invalid alias target: %s: %s",
|
internal_error (e, "invalid alias target: %s: %s",
|
||||||
optype_str (aop->op_type), operand_string (aop));
|
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;
|
statement_t *s;
|
||||||
|
|
||||||
src_type = get_type (e->e.expr.e1);
|
src_type = get_type (e->e.expr.e1);
|
||||||
if ((src_type->type == ev_integer && type->type == ev_float)
|
if (is_scalar (src_type) && is_scalar (type)) {
|
||||||
|| (src_type->type == ev_float && type->type == ev_integer)) {
|
|
||||||
operand_t *src = 0;
|
operand_t *src = 0;
|
||||||
sblock = statement_subexpr (sblock, e->e.expr.e1, &src);
|
sblock = statement_subexpr (sblock, e->e.expr.e1, &src);
|
||||||
*op = temp_operand (e->e.expr.type);
|
*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);
|
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 = statement_subexpr (sblock, e->e.expr.e1, &s->opa);
|
||||||
|
}
|
||||||
sblock_add_statement (sblock, s);
|
sblock_add_statement (sblock, s);
|
||||||
sblock->next = new_sblock ();
|
sblock->next = new_sblock ();
|
||||||
sblock = sblock->next;
|
sblock = sblock->next;
|
||||||
|
@ -1661,10 +1679,6 @@ static void
|
||||||
check_final_block (sblock_t *sblock)
|
check_final_block (sblock_t *sblock)
|
||||||
{
|
{
|
||||||
statement_t *s = 0;
|
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)
|
if (!sblock)
|
||||||
return;
|
return;
|
||||||
|
@ -1685,16 +1699,11 @@ check_final_block (sblock_t *sblock)
|
||||||
sblock->next = new_sblock ();
|
sblock->next = new_sblock ();
|
||||||
sblock = sblock->next;
|
sblock = sblock->next;
|
||||||
}
|
}
|
||||||
|
s = new_statement (st_func, "<RETURN_V>", 0);
|
||||||
if (options.traditional || options.code.progsversion == PROG_ID_VERSION) {
|
if (options.traditional || options.code.progsversion == PROG_ID_VERSION) {
|
||||||
return_symbol = make_symbol (".return", &type_param, pr.symtab->space,
|
s->opcode = save_string ("<RETURN>");
|
||||||
sc_extern);
|
s->opa = return_operand (&type_void);
|
||||||
return_def = return_symbol->s.def;
|
|
||||||
return_opcode = "<RETURN>";
|
|
||||||
}
|
}
|
||||||
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);
|
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 *sym = find_struct (su, tag, type);
|
||||||
symbol_t *s;
|
symbol_t *s;
|
||||||
|
int alignment = 1;
|
||||||
|
|
||||||
symtab->parent = 0; // disconnect struct's symtab from parent scope
|
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)
|
if (size > symtab->size)
|
||||||
symtab->size = size;
|
symtab->size = size;
|
||||||
}
|
}
|
||||||
|
if (s->type->alignment > alignment) {
|
||||||
|
alignment = s->type->alignment;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!type)
|
if (!type)
|
||||||
sym->type = find_type (sym->type); // checks the tag, not the symtab
|
sym->type = find_type (sym->type); // checks the tag, not the symtab
|
||||||
sym->type->t.symtab = symtab;
|
sym->type->t.symtab = symtab;
|
||||||
|
sym->type->alignment = alignment;
|
||||||
if (!type && sym->type->type_def->external) //FIXME should not be necessary
|
if (!type && sym->type->type_def->external) //FIXME should not be necessary
|
||||||
sym->type->type_def = qfo_encode_type (sym->type);
|
sym->type->type_def = qfo_encode_type (sym->type);
|
||||||
return sym;
|
return sym;
|
||||||
|
@ -166,6 +171,7 @@ finish_enum (symbol_t *sym)
|
||||||
|
|
||||||
enum_type = sym->type = find_type (sym->type);
|
enum_type = sym->type = find_type (sym->type);
|
||||||
enum_tab = enum_type->t.symtab;
|
enum_tab = enum_type->t.symtab;
|
||||||
|
enum_type->alignment = 1;
|
||||||
|
|
||||||
for (name = enum_tab->symbols; name; name = name->next) {
|
for (name = enum_tab->symbols; name; name = name->next) {
|
||||||
name->type = sym->type;
|
name->type = sym->type;
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "class.h"
|
#include "class.h"
|
||||||
#include "codespace.h"
|
#include "codespace.h"
|
||||||
#include "diagnostic.h"
|
#include "diagnostic.h"
|
||||||
|
@ -12,9 +14,12 @@
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
#include "function.h"
|
#include "function.h"
|
||||||
#include "obj_file.h"
|
#include "obj_file.h"
|
||||||
|
#include "obj_type.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "qfcc.h"
|
#include "qfcc.h"
|
||||||
#include "strpool.h"
|
#include "strpool.h"
|
||||||
|
#include "struct.h"
|
||||||
|
#include "symtab.h"
|
||||||
#include "type.h"
|
#include "type.h"
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
|
|
||||||
|
@ -23,11 +28,22 @@ options_t options;
|
||||||
int num_linenos;
|
int num_linenos;
|
||||||
pr_lineno_t *linenos;
|
pr_lineno_t *linenos;
|
||||||
pr_info_t pr;
|
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;}
|
__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;}
|
__attribute__((const)) codespace_t *codespace_new (void) {return 0;}
|
||||||
void codespace_addcode (codespace_t *codespace, struct dstatement_s *code, int size) {}
|
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;}
|
__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) {}
|
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 *_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)) 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
|
// simple types. function types are dynamically allocated
|
||||||
type_t type_invalid = { ev_invalid, "invalid" };
|
type_t type_invalid = { ev_invalid, "invalid" };
|
||||||
type_t type_void = { ev_void, "void" };
|
type_t type_void = { ev_void, "void" };
|
||||||
type_t type_string = { ev_string, "string" };
|
type_t type_string = { ev_string, "string", 1 };
|
||||||
type_t type_float = { ev_float, "float" };
|
type_t type_float = { ev_float, "float", 1 };
|
||||||
type_t type_vector = { ev_vector, "vector" };
|
type_t type_vector = { ev_vector, "vector", 1 };
|
||||||
type_t type_entity = { ev_entity, "entity" };
|
type_t type_entity = { ev_entity, "entity", 1 };
|
||||||
type_t type_field = {ev_field, "field", ty_none, {{&type_void}} };
|
type_t type_field = {ev_field, "field", 1, ty_none, {{&type_void}} };
|
||||||
|
|
||||||
// type_function is a void() function used for state defs
|
// type_function is a void() function used for state defs
|
||||||
type_t type_function = { ev_func, "function", ty_none, {{&type_void}} };
|
type_t type_function = { ev_func, "function", 1, ty_none, {{&type_void}} };
|
||||||
type_t type_pointer = { ev_pointer, "pointer", ty_none, {{&type_void}} };
|
type_t type_pointer = { ev_pointer, "pointer", 1, ty_none, {{&type_void}} };
|
||||||
type_t type_quaternion = { ev_quat, "quaternion" };
|
type_t type_quaternion = { ev_quat, "quaternion", 1 };
|
||||||
type_t type_integer = { ev_integer, "int" };
|
type_t type_integer = { ev_integer, "int", 1 };
|
||||||
type_t type_uinteger = { ev_uinteger, "uint" };
|
type_t type_uinteger = { ev_uinteger, "uint", 1 };
|
||||||
type_t type_short = { ev_short, "short" };
|
type_t type_short = { ev_short, "short", 1 };
|
||||||
|
type_t type_double = { ev_double, "double", 2 };
|
||||||
|
|
||||||
type_t *type_nil;
|
type_t *type_nil;
|
||||||
type_t *type_default;
|
type_t *type_default;
|
||||||
|
|
||||||
// these will be built up further
|
// these will be built up further
|
||||||
type_t type_va_list = { ev_invalid, 0, ty_struct };
|
type_t type_va_list = { ev_invalid, 0, 0, ty_struct };
|
||||||
type_t type_param = { ev_invalid, 0, ty_struct };
|
type_t type_param = { ev_invalid, 0, 0, ty_struct };
|
||||||
type_t type_zero = { ev_invalid, 0, ty_struct };
|
type_t type_zero = { ev_invalid, 0, 0, ty_struct };
|
||||||
type_t type_type_encodings = { ev_invalid, "@type_encodings", 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_t *ev_types[ev_type_count] = {
|
||||||
&type_void,
|
&type_void,
|
||||||
|
@ -101,6 +104,7 @@ type_t *ev_types[ev_type_count] = {
|
||||||
&type_integer,
|
&type_integer,
|
||||||
&type_uinteger,
|
&type_uinteger,
|
||||||
&type_short,
|
&type_short,
|
||||||
|
&type_double,
|
||||||
&type_invalid,
|
&type_invalid,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -180,6 +184,7 @@ free_type (type_t *type)
|
||||||
case ev_integer:
|
case ev_integer:
|
||||||
case ev_uinteger:
|
case ev_uinteger:
|
||||||
case ev_short:
|
case ev_short:
|
||||||
|
case ev_double:
|
||||||
break;
|
break;
|
||||||
case ev_field:
|
case ev_field:
|
||||||
case ev_pointer:
|
case ev_pointer:
|
||||||
|
@ -214,19 +219,24 @@ append_type (type_t *type, type_t *new)
|
||||||
case ev_integer:
|
case ev_integer:
|
||||||
case ev_uinteger:
|
case ev_uinteger:
|
||||||
case ev_short:
|
case ev_short:
|
||||||
|
case ev_double:
|
||||||
internal_error (0, "append to basic type");
|
internal_error (0, "append to basic type");
|
||||||
case ev_field:
|
case ev_field:
|
||||||
case ev_pointer:
|
case ev_pointer:
|
||||||
t = &(*t)->t.fldptr.type;
|
t = &(*t)->t.fldptr.type;
|
||||||
|
type->alignment = 1;
|
||||||
break;
|
break;
|
||||||
case ev_func:
|
case ev_func:
|
||||||
t = &(*t)->t.func.type;
|
t = &(*t)->t.func.type;
|
||||||
|
type->alignment = 1;
|
||||||
break;
|
break;
|
||||||
case ev_invalid:
|
case ev_invalid:
|
||||||
if ((*t)->meta == ty_array)
|
if ((*t)->meta == ty_array) {
|
||||||
t = &(*t)->t.array.type;
|
t = &(*t)->t.array.type;
|
||||||
else
|
type->alignment = new->alignment;
|
||||||
|
} else {
|
||||||
internal_error (0, "append to object type");
|
internal_error (0, "append to object type");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -360,6 +370,7 @@ field_type (type_t *aux)
|
||||||
else
|
else
|
||||||
new = new_type ();
|
new = new_type ();
|
||||||
new->type = ev_field;
|
new->type = ev_field;
|
||||||
|
new->alignment = 1;
|
||||||
new->t.fldptr.type = aux;
|
new->t.fldptr.type = aux;
|
||||||
if (aux)
|
if (aux)
|
||||||
new = find_type (new);
|
new = find_type (new);
|
||||||
|
@ -377,6 +388,7 @@ pointer_type (type_t *aux)
|
||||||
else
|
else
|
||||||
new = new_type ();
|
new = new_type ();
|
||||||
new->type = ev_pointer;
|
new->type = ev_pointer;
|
||||||
|
new->alignment = 1;
|
||||||
new->t.fldptr.type = aux;
|
new->t.fldptr.type = aux;
|
||||||
if (aux)
|
if (aux)
|
||||||
new = find_type (new);
|
new = find_type (new);
|
||||||
|
@ -394,6 +406,9 @@ array_type (type_t *aux, int size)
|
||||||
else
|
else
|
||||||
new = new_type ();
|
new = new_type ();
|
||||||
new->type = ev_invalid;
|
new->type = ev_invalid;
|
||||||
|
if (aux) {
|
||||||
|
new->alignment = aux->alignment;
|
||||||
|
}
|
||||||
new->meta = ty_array;
|
new->meta = ty_array;
|
||||||
new->t.array.type = aux;
|
new->t.array.type = aux;
|
||||||
new->t.array.size = size;
|
new->t.array.size = size;
|
||||||
|
@ -413,6 +428,9 @@ based_array_type (type_t *aux, int base, int top)
|
||||||
else
|
else
|
||||||
new = new_type ();
|
new = new_type ();
|
||||||
new->type = ev_invalid;
|
new->type = ev_invalid;
|
||||||
|
if (aux) {
|
||||||
|
new->alignment = aux->alignment;
|
||||||
|
}
|
||||||
new->meta = ty_array;
|
new->meta = ty_array;
|
||||||
new->t.array.type = aux;
|
new->t.array.type = aux;
|
||||||
new->t.array.base = base;
|
new->t.array.base = base;
|
||||||
|
@ -582,6 +600,9 @@ encode_type (dstring_t *encoding, const type_t *type)
|
||||||
case ev_string:
|
case ev_string:
|
||||||
dasprintf (encoding, "*");
|
dasprintf (encoding, "*");
|
||||||
break;
|
break;
|
||||||
|
case ev_double:
|
||||||
|
dasprintf (encoding, "d");
|
||||||
|
break;
|
||||||
case ev_float:
|
case ev_float:
|
||||||
dasprintf (encoding, "f");
|
dasprintf (encoding, "f");
|
||||||
break;
|
break;
|
||||||
|
@ -685,6 +706,12 @@ is_integral (const type_t *type)
|
||||||
return is_enum (type);
|
return is_enum (type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
is_double (const type_t *type)
|
||||||
|
{
|
||||||
|
return type->type == ev_double;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
is_float (const type_t *type)
|
is_float (const type_t *type)
|
||||||
{
|
{
|
||||||
|
@ -694,7 +721,7 @@ is_float (const type_t *type)
|
||||||
int
|
int
|
||||||
is_scalar (const type_t *type)
|
is_scalar (const type_t *type)
|
||||||
{
|
{
|
||||||
return is_float (type) || is_integral (type);
|
return is_float (type) || is_integral (type) || is_double (type);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -830,6 +857,7 @@ type_size (const type_t *type)
|
||||||
case ev_integer:
|
case ev_integer:
|
||||||
case ev_uinteger:
|
case ev_uinteger:
|
||||||
case ev_short:
|
case ev_short:
|
||||||
|
case ev_double:
|
||||||
case ev_type_count:
|
case ev_type_count:
|
||||||
return pr_type_size[type->type];
|
return pr_type_size[type->type];
|
||||||
case ev_invalid:
|
case ev_invalid:
|
||||||
|
@ -869,6 +897,7 @@ init_types (void)
|
||||||
{
|
{
|
||||||
static struct_def_t zero_struct[] = {
|
static struct_def_t zero_struct[] = {
|
||||||
{"string_val", &type_string},
|
{"string_val", &type_string},
|
||||||
|
{"double_val", &type_double},
|
||||||
{"float_val", &type_float},
|
{"float_val", &type_float},
|
||||||
{"entity_val", &type_entity},
|
{"entity_val", &type_entity},
|
||||||
{"field_val", &type_field},
|
{"field_val", &type_field},
|
||||||
|
@ -895,6 +924,7 @@ init_types (void)
|
||||||
{"integer_val", &type_integer},
|
{"integer_val", &type_integer},
|
||||||
{"uinteger_val", &type_uinteger},
|
{"uinteger_val", &type_uinteger},
|
||||||
{"quaternion_val", &type_quaternion},
|
{"quaternion_val", &type_quaternion},
|
||||||
|
{"double_val", &type_double},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
static struct_def_t vector_struct[] = {
|
static struct_def_t vector_struct[] = {
|
||||||
|
@ -982,6 +1012,7 @@ chain_initial_types (void)
|
||||||
chain_type (&type_integer);
|
chain_type (&type_integer);
|
||||||
chain_type (&type_uinteger);
|
chain_type (&type_uinteger);
|
||||||
chain_type (&type_short);
|
chain_type (&type_short);
|
||||||
|
chain_type (&type_double);
|
||||||
}
|
}
|
||||||
|
|
||||||
chain_type (&type_param);
|
chain_type (&type_param);
|
||||||
|
|
|
@ -69,6 +69,7 @@ typedef struct {
|
||||||
ex_pointer_t pointer;
|
ex_pointer_t pointer;
|
||||||
float quaternion_val[4];
|
float quaternion_val[4];
|
||||||
int integer_val;
|
int integer_val;
|
||||||
|
double double_val;
|
||||||
} i;
|
} i;
|
||||||
} immediate_t;
|
} immediate_t;
|
||||||
|
|
||||||
|
@ -132,6 +133,16 @@ new_string_val (const char *string_val)
|
||||||
return find_value (&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 *
|
ex_value_t *
|
||||||
new_float_val (float float_val)
|
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 *pointer_imm_defs;
|
||||||
static hashtab_t *quaternion_imm_defs;
|
static hashtab_t *quaternion_imm_defs;
|
||||||
static hashtab_t *integer_imm_defs;
|
static hashtab_t *integer_imm_defs;
|
||||||
|
static hashtab_t *double_imm_defs;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
imm_free (void *_imm, void *unused)
|
imm_free (void *_imm, void *unused)
|
||||||
|
@ -296,6 +308,8 @@ imm_get_hash (const void *_imm, void *_tab)
|
||||||
} else if (tab == &quaternion_imm_defs) {
|
} else if (tab == &quaternion_imm_defs) {
|
||||||
return Hash_Buffer (&imm->i.quaternion_val,
|
return Hash_Buffer (&imm->i.quaternion_val,
|
||||||
sizeof (&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) {
|
} else if (tab == &integer_imm_defs) {
|
||||||
return imm->i.integer_val;
|
return imm->i.integer_val;
|
||||||
} else {
|
} else {
|
||||||
|
@ -330,6 +344,8 @@ imm_compare (const void *_imm1, const void *_imm2, void *_tab)
|
||||||
sizeof (imm1->i.pointer));
|
sizeof (imm1->i.pointer));
|
||||||
} else if (tab == &quaternion_imm_defs) {
|
} else if (tab == &quaternion_imm_defs) {
|
||||||
return QuatCompare (imm1->i.quaternion_val, imm2->i.quaternion_val);
|
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) {
|
} else if (tab == &integer_imm_defs) {
|
||||||
return imm1->i.integer_val == imm2->i.integer_val;
|
return imm1->i.integer_val == imm2->i.integer_val;
|
||||||
} else {
|
} else {
|
||||||
|
@ -352,6 +368,24 @@ value_as_float (ex_value_t *value)
|
||||||
return value->v.integer_val;
|
return value->v.integer_val;
|
||||||
if (value->lltype == ev_short)
|
if (value->lltype == ev_short)
|
||||||
return value->v.short_val;
|
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)
|
if (value->lltype == ev_float)
|
||||||
return value->v.float_val;
|
return value->v.float_val;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -366,6 +400,8 @@ value_as_int (ex_value_t *value)
|
||||||
return value->v.integer_val;
|
return value->v.integer_val;
|
||||||
if (value->lltype == ev_short)
|
if (value->lltype == ev_short)
|
||||||
return value->v.short_val;
|
return value->v.short_val;
|
||||||
|
if (value->lltype == ev_double)
|
||||||
|
return value->v.double_val;
|
||||||
if (value->lltype == ev_float)
|
if (value->lltype == ev_float)
|
||||||
return value->v.float_val;
|
return value->v.float_val;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -380,6 +416,8 @@ value_as_uint (ex_value_t *value)
|
||||||
return value->v.integer_val;
|
return value->v.integer_val;
|
||||||
if (value->lltype == ev_short)
|
if (value->lltype == ev_short)
|
||||||
return value->v.short_val;
|
return value->v.short_val;
|
||||||
|
if (value->lltype == ev_double)
|
||||||
|
return value->v.double_val;
|
||||||
if (value->lltype == ev_float)
|
if (value->lltype == ev_float)
|
||||||
return value->v.float_val;
|
return value->v.float_val;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -395,6 +433,9 @@ convert_value (ex_value_t *value, type_t *type)
|
||||||
if (is_float (type)) {
|
if (is_float (type)) {
|
||||||
float val = value_as_float (value);
|
float val = value_as_float (value);
|
||||||
return new_float_val (val);
|
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) {
|
} else if (type->type == ev_short) {
|
||||||
int val = value_as_int (value);
|
int val = value_as_int (value);
|
||||||
return new_short_val (val);
|
return new_short_val (val);
|
||||||
|
@ -494,6 +535,10 @@ emit_value (ex_value_t *value, def_t *def)
|
||||||
tab = quaternion_imm_defs;
|
tab = quaternion_imm_defs;
|
||||||
type = &type_quaternion;
|
type = &type_quaternion;
|
||||||
break;
|
break;
|
||||||
|
case ev_double:
|
||||||
|
tab = double_imm_defs;
|
||||||
|
type = &type_double;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
internal_error (0, 0);
|
internal_error (0, 0);
|
||||||
}
|
}
|
||||||
|
@ -591,6 +636,7 @@ clear_immediates (void)
|
||||||
Hash_FlushTable (pointer_imm_defs);
|
Hash_FlushTable (pointer_imm_defs);
|
||||||
Hash_FlushTable (quaternion_imm_defs);
|
Hash_FlushTable (quaternion_imm_defs);
|
||||||
Hash_FlushTable (integer_imm_defs);
|
Hash_FlushTable (integer_imm_defs);
|
||||||
|
Hash_FlushTable (double_imm_defs);
|
||||||
} else {
|
} else {
|
||||||
value_table = Hash_NewTable (16381, 0, 0, 0);
|
value_table = Hash_NewTable (16381, 0, 0, 0);
|
||||||
Hash_SetHashCompare (value_table, value_get_hash, value_compare);
|
Hash_SetHashCompare (value_table, value_get_hash, value_compare);
|
||||||
|
@ -624,6 +670,10 @@ clear_immediates (void)
|
||||||
integer_imm_defs =
|
integer_imm_defs =
|
||||||
Hash_NewTable (16381, 0, imm_free, &integer_imm_defs);
|
Hash_NewTable (16381, 0, imm_free, &integer_imm_defs);
|
||||||
Hash_SetHashCompare (integer_imm_defs, imm_get_hash, imm_compare);
|
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;
|
def = make_symbol (".zero", &type_zero, 0, sc_extern)->s.def;
|
||||||
|
|
|
@ -29,15 +29,19 @@ test_bins=\
|
||||||
fail_bins=
|
fail_bins=
|
||||||
|
|
||||||
test_progs_dat=\
|
test_progs_dat=\
|
||||||
|
address-cast.dat \
|
||||||
|
alignment.dat \
|
||||||
chewed-alias.dat \
|
chewed-alias.dat \
|
||||||
chewed-return.dat \
|
chewed-return.dat \
|
||||||
comma-expr.dat \
|
comma-expr.dat \
|
||||||
deadbool.dat \
|
deadbool.dat \
|
||||||
|
double.dat \
|
||||||
enum.dat \
|
enum.dat \
|
||||||
fordecl.dat \
|
fordecl.dat \
|
||||||
func-expr.dat \
|
func-expr.dat \
|
||||||
func-static.dat \
|
func-static.dat \
|
||||||
infloop.dat \
|
infloop.dat \
|
||||||
|
ivar-struct-return.dat \
|
||||||
modulo.dat \
|
modulo.dat \
|
||||||
paramret.dat \
|
paramret.dat \
|
||||||
quaternion.dat \
|
quaternion.dat \
|
||||||
|
@ -57,11 +61,31 @@ test_progs_dat=\
|
||||||
|
|
||||||
fail_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=\
|
test_defspace_src=\
|
||||||
tw-defspace.c tw-diagnostic.c tw-strpool.c
|
tw-defspace.c tw-diagnostic.c tw-strpool.c
|
||||||
|
|
||||||
TESTS=$(test_bins) $(test_progs_dat:.dat=.run)
|
TESTS=\
|
||||||
XFAIL_TESTS=$(fail_bins) $(fail_progs_dat:.dat=.run)
|
$(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)
|
check_PROGRAMS=test-harness $(test_progs_dat) $(test_bins)
|
||||||
|
|
||||||
|
@ -75,6 +99,24 @@ test_harness_DEPENDENCIES= $(QFCC_TEST_DEPS)
|
||||||
|
|
||||||
r_depfiles_remade=
|
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_dat_SOURCES=chewed-alias.r
|
||||||
chewed_alias_obj=$(chewed_alias_dat_SOURCES:.r=.qfo)
|
chewed_alias_obj=$(chewed_alias_dat_SOURCES:.r=.qfo)
|
||||||
chewed-alias.dat$(EXEEXT): $(chewed_alias_obj) $(QFCC_DEP)
|
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
|
include ./$(DEPDIR)/deadbool.Qo # am--include-marker
|
||||||
r_depfiles_remade += ./$(DEPDIR)/deadbool.Qo
|
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_dat_SOURCES=enum.r
|
||||||
enum_obj=$(enum_dat_SOURCES:.r=.qfo)
|
enum_obj=$(enum_dat_SOURCES:.r=.qfo)
|
||||||
enum.dat$(EXEEXT): $(enum_obj) $(QFCC_DEP)
|
enum.dat$(EXEEXT): $(enum_obj) $(QFCC_DEP)
|
||||||
|
@ -156,6 +237,15 @@ infloop.run: Makefile build-run
|
||||||
include ./$(DEPDIR)/infloop.Qo # am--include-marker
|
include ./$(DEPDIR)/infloop.Qo # am--include-marker
|
||||||
r_depfiles_remade += ./$(DEPDIR)/infloop.Qo
|
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_dat_SOURCES=modulo.r
|
||||||
modulo_obj=$(modulo_dat_SOURCES:.r=.qfo)
|
modulo_obj=$(modulo_dat_SOURCES:.r=.qfo)
|
||||||
modulo.dat$(EXEEXT): $(modulo_obj) $(QFCC_DEP)
|
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;
|
return;
|
||||||
if (!time) {
|
if (!time) {
|
||||||
ent = spawn ();
|
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 foo (float a, float b)
|
||||||
{
|
{
|
||||||
float c = a % b;
|
float c = a % b;
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
#pragma advanced
|
||||||
|
|
||||||
float bar (float a, float b)
|
float bar (float a, float b)
|
||||||
{
|
{
|
||||||
float c;
|
float c;
|
||||||
|
@ -15,14 +38,35 @@ float bar (float a, float b)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma traditional
|
||||||
float baz (float a, float b)
|
float baz (float a, float b)
|
||||||
{
|
{
|
||||||
float c = (a + b) % (a - b);
|
float c = (a + b) % (a - b);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
#pragma advanced
|
||||||
|
|
||||||
float test (string name, float (func)(float a, float b),
|
@overload int
|
||||||
float a, float b, float c)
|
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;
|
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",
|
printf ("%s: (%g + %g) %% (%g - %g): %g != %g\n",
|
||||||
name, a, b, a, b, ret, c);
|
name, a, b, a, b, ret, c);
|
||||||
else
|
else
|
||||||
printf ("%s: %g %% %g: %g != %g\n",
|
printf ("%s: %g %s %g: %g != %g\n",
|
||||||
name, a, b, ret, c);
|
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 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -42,20 +105,56 @@ float test (string name, float (func)(float a, float b),
|
||||||
float main (void)
|
float main (void)
|
||||||
{
|
{
|
||||||
float res = 0;
|
float res = 0;
|
||||||
res |= test ("foo", foo, 5, 3, 2);
|
res |= test ("foo", "%", foo, 5, 3, 2);
|
||||||
res |= test ("bar", bar, 5, 3, 2);
|
res |= test ("bar", "%", bar, 5, 3, 2);
|
||||||
res |= test ("baz", baz, 5, 3, 0);
|
res |= test ("baz", "%", baz, 5, 3, 0);
|
||||||
|
res |= test ("snafu", "%", snafu, 5, 3, 2);
|
||||||
|
|
||||||
res |= test ("foo", foo, -5, 3, -2);
|
res |= test ("foo", "%", foo, -5, 3, -2);
|
||||||
res |= test ("bar", bar, -5, 3, -2);
|
res |= test ("bar", "%", bar, -5, 3, -2);
|
||||||
res |= test ("baz", baz, -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 ("foo", "%", foo, 5, -3, 2);
|
||||||
res |= test ("bar", bar, 5, -3, 2);
|
res |= test ("bar", "%", bar, 5, -3, 2);
|
||||||
res |= test ("baz", baz, 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 ("foo", "%", foo, -5, -3, -2);
|
||||||
res |= test ("bar", bar, -5, -3, -2);
|
res |= test ("bar", "%", bar, -5, -3, -2);
|
||||||
res |= test ("baz", baz, -5, -3, 0);
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ state0 (void)
|
||||||
[$frame1, state1]
|
[$frame1, state1]
|
||||||
{
|
{
|
||||||
if (self.frame != $frame1 || self.think != 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);
|
printf ("state0: %g %x %g\n", self.frame, self.think, self.nextthink);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
@ -21,10 +21,10 @@ state0 (void)
|
||||||
|
|
||||||
void
|
void
|
||||||
state1 (void)
|
state1 (void)
|
||||||
[$frame2, state2, 0.2]
|
[$frame2, state2, 0.2f]
|
||||||
{
|
{
|
||||||
if (self.frame != $frame2 || self.think != state2
|
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);
|
printf ("state0: %g %x %g\n", self.frame, self.think, self.nextthink);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
@ -32,10 +32,10 @@ state1 (void)
|
||||||
|
|
||||||
void
|
void
|
||||||
state2 (void)
|
state2 (void)
|
||||||
[$frame0, state0, 0.5]
|
[$frame0, state0, 0.5f]
|
||||||
{
|
{
|
||||||
if (self.frame != $frame0 || self.think != state0
|
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);
|
printf ("state0: %g %x %g\n", self.frame, self.think, self.nextthink);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,9 +135,13 @@ init_qf (void)
|
||||||
|
|
||||||
Memory_Init (malloc (1024 * 1024), 1024 * 1024);
|
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);
|
Cvar_Get ("pr_boundscheck", "2", 0, 0, 0);
|
||||||
|
|
||||||
|
if (options.trace > 1) {
|
||||||
|
Cvar_SetValue (debug, 4);
|
||||||
|
}
|
||||||
|
|
||||||
pr.edicts = &edicts;
|
pr.edicts = &edicts;
|
||||||
pr.num_edicts = &num_edicts;
|
pr.num_edicts = &num_edicts;
|
||||||
pr.reserved_edicts = &reserved_edicts;
|
pr.reserved_edicts = &reserved_edicts;
|
||||||
|
@ -207,7 +211,7 @@ parse_options (int argc, char **argv)
|
||||||
options.flote = 1;
|
options.flote = 1;
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
options.trace = 1;
|
options.trace++;
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
usage (0);
|
usage (0);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
void printf (string fmt, ...) = #0;
|
void printf (string fmt, ...) = #0;
|
||||||
float (string s) stof = #0;
|
float (string s) stof = #0;
|
||||||
float (float x) sqrt = #0;
|
@overload float (float x) sqrt = #0;
|
||||||
|
|
||||||
float
|
float
|
||||||
heron (float a, float b, float c)
|
heron (float a, float b, float c)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue