From 6c631c6d5d0ed553522ec85cb2f614385ec69cf7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 19 Dec 2010 11:35:18 +0900 Subject: [PATCH] Start documenting qfcc. --- tools/qfcc/include/expr.h | 425 ++++++++++++++++++++++++++++++++------ tools/qfcc/include/qfcc.h | 37 +++- 2 files changed, 392 insertions(+), 70 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 6b06a45d9..7552c071b 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -34,55 +34,80 @@ #include "QF/pr_comp.h" -typedef enum { - ex_error, - ex_state, - ex_bool, - ex_label, - ex_block, - ex_expr, // binary expression - ex_uexpr, // unary expression - ex_def, - ex_temp, // temporary variable - ex_name, +/** \defgroup qfcc_expr Expressions + \ingroup qfcc +*/ +//@{ - ex_nil, // umm, nil, null. nuff said - ex_string, - ex_float, - ex_vector, - ex_entity, - ex_field, - ex_func, - ex_pointer, - ex_quaternion, - ex_integer, - ex_uinteger, - ex_short, +/** Type of the exression node in an expression tree. +*/ +typedef enum { + ex_error, ///< error expression. used to signal an error + ex_state, ///< state expression (::ex_state_t) + ex_bool, ///< short circuit boolean logic expression (::ex_bool_t) + ex_label, ///< goto/branch label (::ex_label_t) + ex_block, ///< statement block expression (::ex_block_t) + ex_expr, ///< binary expression (::ex_expr_t) + ex_uexpr, ///< unary expression (::ex_expr_t) + ex_def, ///< non-temporary variable (::def_t) + ex_temp, ///< temporary variable (::ex_temp_t) + ex_name, ///< unresolved name (expr_t::e::string_val) + + ex_nil, ///< umm, nil, null. nuff said (0 of any type) + ex_string, ///< string constant (expr_t::e::string_val) + ex_float, ///< float constant (expr_t::e::float_val) + ex_vector, ///< vector constant (expr_t::e::vector_val) + ex_entity, ///< entity constant (expr_t::e::entity_val) + ex_field, ///< field constant + ex_func, ///< function constant (expr_t::e::func_val) + ex_pointer, ///< pointer constant (expr_t::e::pointer) + ex_quaternion, ///< quaternion constant (expr_t::e::quaternion_val) + ex_integer, ///< integer constant (expr_t::e::integer_val) + ex_uinteger, ///< unsigned integer constant (expr_t::e::uinteger_val) + ex_short, ///< short constant (expr_t::e::short_val) } expr_type; +/** Binary and unary expressions. + + This is used for both binary and unary expressions. Unary expressions do + not use e2. The opcode is generally the parser token for the expression, + though special codes are used for non-math expressions. +*/ +typedef struct ex_expr_s { + int op; ///< op-code of this expression + struct type_s *type; ///< the type of the result of this expression + struct expr_s *e1; ///< left side of binary, sole of unary + struct expr_s *e2; ///< right side of binary, null for unary +} ex_expr_t; + typedef struct ex_label_s { - struct ex_label_s *next; - struct reloc_s *refs; - int ofs; - const char *name; + struct ex_label_s *next; ///< next lable in global list of labels + struct reloc_s *refs; ///< relocations associated with this label + int ofs; ///< the location of this label if known + const char *name; ///< the name of this label } ex_label_t; typedef struct { - struct expr_s *head; - struct expr_s **tail; - struct expr_s *result; - int is_call; + struct expr_s *head; ///< the first expression in the block + struct expr_s **tail; ///< last expression in the block, for appending + struct expr_s *result; ///< the result of this block if non-void + int is_call; ///< this block exprssion forms a function call } ex_block_t; typedef struct { struct expr_s *expr; - struct def_s *def; - struct type_s *type; - int users; + struct def_s *def; ///< The def for the temporary variable, if + ///< allocated + struct type_s *type; ///< The type of the temporary variable. + int users; ///< Reference count. Source of much hair loss. } ex_temp_t; +/** Pointer constant expression. + + Represent a pointer to an absolute address in data space. +*/ typedef struct { - int val; + int val; struct type_s *type; struct def_s *def; } ex_pointer_t; @@ -98,45 +123,74 @@ typedef struct { struct expr_s *e; } ex_bool_t; +/** State expression used for think function state-machines. + + State expressions are of the form [framenum, nextthink] + (standard) or [framenum, nextthink, timestep] (QF extension) + and come before the opening brace of the function. If the state + expression is of the former form, then \c step will be null. Normally, + \c framenum and \c nextthink must be constant (though \c nextthink may + be a forward reference), but qfcc allows both \c framenum and + \c nextthink, and also \c timestep, to be variable. + + \par From qcc: + States are special functions made for convenience. They + automatically set frame, nextthink (implicitly), and think (allowing + forward definitions). + + \verbatim + void() name = [framenum, nextthink] {code}; + \endverbatim + expands to: + \verbatim + void name () + { + self.frame=framenum; + self.nextthink = time + 0.1; + self.think = nextthink + [code] + }; + \endverbatim + + Although the above expansion shows three expressions, a state expression + using constant values is just one instruction: either + state framenum, nextthink (standard) or + state.f framenum, nextthink, timestep (QF, optional). +*/ typedef struct { - struct expr_s *frame; - struct expr_s *think; - struct expr_s *step; + struct expr_s *frame; ///< the frame to which to change in this state + struct expr_s *think; ///< think function for the next state + struct expr_s *step; ///< time step until the next state } ex_state_t; #define POINTER_VAL(p) (((p).def ? (p).def->ofs : 0) + (p).val) typedef struct expr_s { - struct expr_s *next; - expr_type type; - int line; - string_t file; - unsigned paren:1; - unsigned rvalue:1; + struct expr_s *next; ///< the next expression in a block expression + expr_type type; ///< the type of the result of this expression + int line; ///< source line that generated this expression + string_t file; ///< source file that generated this expression + unsigned paren:1; ///< the expression is enclosed in () + unsigned rvalue:1; ///< the expression is on the left side of = union { - ex_label_t label; - ex_state_t state; - ex_bool_t bool; - ex_block_t block; - struct { - int op; - struct type_s *type; - struct expr_s *e1; - struct expr_s *e2; - } expr; - struct def_s *def; - ex_temp_t temp; + ex_label_t label; ///< label expression + ex_state_t state; ///< state expression + ex_bool_t bool; ///< boolean logic expression + ex_block_t block; ///< statement block expression + ex_expr_t expr; ///< binary or unary expression + struct def_s *def; ///< def reference expression + ex_temp_t temp; ///< temporary variable expression - const char *string_val; - float float_val; - float vector_val[3]; - int entity_val; - int func_val; - ex_pointer_t pointer; - float quaternion_val[4]; - int integer_val; - unsigned int uinteger_val; - short short_val; + const char *string_val; ///< string constant + float float_val; ///< float constant + float vector_val[3]; ///< vector constant + int entity_val; ///< entity constant + int func_val; ///< function constant + ex_pointer_t pointer; ///< pointer constant + float quaternion_val[4]; ///< quaternion constant + int integer_val; ///< integer constant + unsigned uinteger_val; ///< unsigned integer constant + short short_val; ///< short constant } e; } expr_t; @@ -144,44 +198,279 @@ extern etype_t qc_types[]; extern struct type_s *ev_types[]; extern expr_type expr_types[]; +/** Report a type mismatch error. + + \a e1 is used for reporting the file and line number of the error. + + \param e1 Left side expression. Used for reporting the type. + \param e2 Right side expression. Used for reporting the type. + \param op The opcode of the expression. + \return \a e1 with its type set to ex_error. +*/ expr_t *type_mismatch (expr_t *e1, expr_t *e2, int op); extern expr_t *local_expr; +/** Get the type descriptor of the expression result. + + \param e The expression from which to get the result type. + \return Pointer to the type description, or null if the expression + type (expr_t::type) is inappropriate. +*/ struct type_s *get_type (expr_t *e); + +/** Get the basic type code of the expression result. + + \param e The expression from which to get the result type. + \return Pointer to the type description, or ev_type_count if + get_type() returns null. +*/ etype_t extract_type (expr_t *e); +/** Create a new expression node. + + Sets the source file and line number information. The expression node is + otherwise raw. This function is generally not used directly. + + \return The new expression node. +*/ expr_t *new_expr (void); +/** Create a new label name. + + The label name is guaranteed to to the compilation. It is made up of the + name of the current function plus an incrementing number. The number is + not reset between functions. + + \return The string representing the label name. +*/ const char *new_label_name (void); +/** Create a new label expression node. + + The label name is set using new_label_name(), and the label is linked + into the global list of labels for later resolution. + + \return The new label expression (::ex_label_t) node. +*/ expr_t *new_label_expr (void); + +/** Create a new state expression node. + + The label name is set using new_label_name(), and the label is linked + into the global list of labels for later resolution. + + \param frame The expression giving the frame number. + \param think The expression giving the think function. + \param step The expression giving the time step value, or null if + no time-step is specified (standard form). + \return The new state expression (::ex_state_t) node. +*/ expr_t *new_state_expr (expr_t *frame, expr_t *think, expr_t *step); + expr_t *new_bool_expr (ex_list_t *true_list, ex_list_t *false_list, expr_t *e); + +/** Create a new statement block expression node. + + The returned block expression is empty. Use append_expr() to add + expressions to the block expression. + + \return The new block expression (::ex_block_t) node. +*/ expr_t *new_block_expr (void); + +/** Create a new binary expression node node. + + If \a e1 or \a e2 represent temporary variables, their ex_temp_t::users + field will be incremented. + + If either \a e1 or \a e2 are error expressions, then that expression will + be returned instead of a new binary expression. + + \param op The op-ccode of the binary expression. + \param e1 The left side of the binary expression. + \param e2 The right side of the binary expression. + \return The new binary expression node (::ex_expr_t) if neither + \a e1 nor \a e2 are error expressions, otherwise the + expression that is an error expression. +*/ expr_t *new_binary_expr (int op, expr_t *e1, expr_t *e2); + +/** Create a new unary expression node node. + + If \a e1 represents a temporary variable, its ex_temp_t::users field + will be incremented. + + If \a e1 is an error expression, then it will be returned instead of a + new binary expression. + + \param op The op-code of the unary expression. + \param e1 The "right" side of the expression. + \return The new unary expression node (::ex_expr_t) if \a e1 + is not an error expression, otherwise \a e1. +*/ expr_t *new_unary_expr (int op, expr_t *e1); + +/** Create a new def reference (non-temporary variable) expression node. + + \return The new def reference expression node (::def_t). +*/ expr_t *new_def_expr (struct def_s *def); + +/** Create a new temporary variable expression node. + + Does not allocate a new temporary variable. + The ex_temp_t::users field will be 0. + + \param type The type of the temporary variable. + \return The new temporary variable expression node (ex_temp_t). +*/ expr_t *new_temp_def_expr (struct type_s *type); + +/** Create a new nil expression node. + + nil represents 0 of any type. + + \return The new nil expression node. +*/ expr_t *new_nil_expr (void); + +/** Create a new name expression node. + + Name expression nodes represent as yet unresolved names. + + \param name The name being represented. + \return The new name expression node (expr_t::e::string_val). +*/ expr_t *new_name_expr (const char *name); +/** Create a new string constant expression node. + + \param string_val The string constant being represented. + \return The new string constant expression node + (expr_t::e::string_val). +*/ expr_t *new_string_expr (const char *string_val); + +/** Create a new float constant expression node. + + \param float_val The float constant being represented. + \return The new float constant expression node + (expr_t::e::float_val). +*/ expr_t *new_float_expr (float float_val); + +/** Create a new vector constant expression node. + + \param vector_val The vector constant being represented. + \return The new vector constant expression node + (expr_t::e::vector_val). +*/ expr_t *new_vector_expr (float *vector_val); + +/** Create a new entity constant expression node. + + \param entity_val The entity constant being represented. + \return The new entity constant expression node + (expr_t::e::entity_val). +*/ expr_t *new_entity_expr (int entity_val); + +/** Create a new field constant expression node. + + \param field_val XXX + \param type The type of the field. + \param def + \return The new field constant expression node + (expr_t::e::field_val). +*/ expr_t *new_field_expr (int field_val, struct type_s *type, struct def_s *def); + +/** Create a new function constant expression node. + + \param func_val The function constant being represented. + \return The new function constant expression node + (expr_t::e::func_val). +*/ expr_t *new_func_expr (int func_val); + +/** Create a new pointer constant expression node. + + \param val The pointer constant (address) being represented. XXX + \param type The type of the referenced value. + \param def + \return The new pointer constant expression node + (expr_t::e::pointer_val). +*/ expr_t *new_pointer_expr (int val, struct type_s *type, struct def_s *def); + +/** Create a new quaternion constant expression node. + + \param quaternion_val The quaternion constant being represented. + \return The new quaternion constant expression node + (expr_t::e::quaternion_val). +*/ expr_t *new_quaternion_expr (float *quaternion_val); + +/** Create a new integer constant expression node. + + \param integer_val The integer constant being represented. + \return The new integer constant expression node + (expr_t::e::integer_val). +*/ expr_t *new_integer_expr (int integer_val); + +/** Create a new unsigned integer constant expression node. + + \param uinteger_val The unsigned integer constant being represented. + \return The new unsigned integer constant expression node + (expr_t::e::uinteger_val). +*/ expr_t *new_uinteger_expr (unsigned int uinteger_val); + +/** Create a new short constant expression node. + + \param short_val The short constant being represented. + \return The new short constant expression node + (expr_t::e::short_val). +*/ expr_t *new_short_expr (short short_val); +/** Check of the expression refers to a constant value. + + \param e The expression to check. + \return True if the expression is constant. +*/ int is_constant (expr_t *e); + +/** Check if the op-code is a comparison. + + \param op The op-code to check. + \return True if the op-code is a comparison operator. +*/ int is_compare (int op); + +/** Check if the op-code is a math operator. + + \param op The op-code to check. + \return True if the op-code is a math operator. +*/ int is_math (int op); + +/** Check if the op-code is a logic operator. + + \param op The op-code to check. + \return True if the op-code is a logic operator. +*/ int is_logic (int op); + +/** Convert a constant def to a constant expression. + + \param var The def to convert. + \return A new constant expression of the appropriate type with + the value of the constant def, or \a var if neither a def + nor a constant def. +*/ expr_t *constant_expr (expr_t *var); expr_t *new_bind_expr (expr_t *e1, expr_t *e2); @@ -232,7 +521,7 @@ void init_elements (struct def_s *def, expr_t *eles); expr_t *error (expr_t *e, const char *fmt, ...) __attribute__((format(printf, 2,3))); expr_t *warning (expr_t *e, const char *fmt, ...) __attribute__((format(printf, 2,3))); -expr_t * notice (expr_t *e, const char *fmt, ...) __attribute__((format(printf, 2,3))); +expr_t *notice (expr_t *e, const char *fmt, ...) __attribute__((format(printf, 2,3))); const char *get_op_string (int op); @@ -249,4 +538,6 @@ expr_t *sizeof_expr (expr_t *expr, struct type_s *type); expr_t *fold_constants (expr_t *e); +//@} + #endif//__expr_h diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index 518998491..0c0ae64b8 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -49,9 +49,8 @@ struct srcline_s { int source_line; }; -// -// output generated by prog parsing -// +/** Output generated by prog parsing. +*/ typedef struct pr_info_s { struct type_s *types; struct ex_label_s *labels; @@ -111,7 +110,16 @@ extern struct scope_s *current_scope; const char *strip_path (const char *filename); +/** Smart strdup. + + Create a unique copy of a string. If the same string has been seen + before, does not create a new copy but rather returns the previously + seen string. + \param str The string to copy. + \return The unique copy of the string. +*/ const char *save_string (const char *str); + void clear_frame_macros (void); extern FILE *yyin; int yyparse (void); @@ -124,6 +132,22 @@ char *fix_backslash (char *path); #define NORMALIZE(x) x #endif +/** High-tide structure allocator for use in linked lists. + + Using a free-list with the name of \c free_NAME, return a single element. + The type of the element must be a structure with a field named \c next. + When the free-list is empty, memory is claimed from the system in blocks. + elements may be returned to the pool by linking them into the free-list. + + \param s The number of structures in the block. + \param t The structure type. + \param n The \c NAME portion of the \c free_NAME free-list. + \param v The destination of the pointer to the allocated + element. The contents of the allocated element will be + memset to 0. + + \hideinitializer +*/ #define ALLOC(s, t, n, v) \ do { \ if (!free_##n) { \ @@ -138,6 +162,13 @@ char *fix_backslash (char *path); memset (v, 0, sizeof (*v)); \ } while (0) +/** Round \a x up to the next multiple of \a a. + \note \a a must be a power of two or this will break. + \note There are no side effects on \a x. + \param x The value to be rounded up. + \param a The rounding factor. + \return The rounded value. +*/ #define RUP(x,a) (((x) + ((a) - 1)) & ~((a) - 1)) //@}