diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/tools/yasm/libyasm/bytecode.h | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/tools/yasm/libyasm/bytecode.h')
-rw-r--r-- | contrib/tools/yasm/libyasm/bytecode.h | 638 |
1 files changed, 638 insertions, 0 deletions
diff --git a/contrib/tools/yasm/libyasm/bytecode.h b/contrib/tools/yasm/libyasm/bytecode.h new file mode 100644 index 00000000000..47cd26244b0 --- /dev/null +++ b/contrib/tools/yasm/libyasm/bytecode.h @@ -0,0 +1,638 @@ +/** + * \file libyasm/bytecode.h + * \brief YASM bytecode interface. + * + * \license + * Copyright (C) 2001-2007 Peter Johnson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * \endlicense + */ +#ifndef YASM_BYTECODE_H +#define YASM_BYTECODE_H + +#ifndef YASM_LIB_DECL +#define YASM_LIB_DECL +#endif + +/** A data value (opaque type). */ +typedef struct yasm_dataval yasm_dataval; +/** A list of data values. */ +typedef struct yasm_datavalhead yasm_datavalhead; + +/** Linked list of data values. */ +/*@reldef@*/ STAILQ_HEAD(yasm_datavalhead, yasm_dataval); + +/** Add a dependent span for a bytecode. + * \param add_span_data add_span_data passed into bc_calc_len() + * \param bc bytecode containing span + * \param id non-zero identifier for span; may be any non-zero value + * if <0, expand is called for any change; + * if >0, expand is only called when exceeds threshold + * \param value dependent value for bytecode expansion + * \param neg_thres negative threshold for long/short decision + * \param pos_thres positive threshold for long/short decision + */ +typedef void (*yasm_bc_add_span_func) + (void *add_span_data, yasm_bytecode *bc, int id, const yasm_value *value, + long neg_thres, long pos_thres); + +/** Bytecode callback structure. Any implementation of a specific bytecode + * must implement these functions and this callback structure. The bytecode + * implementation-specific data is stored in #yasm_bytecode.contents. + */ +typedef struct yasm_bytecode_callback { + /** Destroys the implementation-specific data. + * Called from yasm_bc_destroy(). + * \param contents #yasm_bytecode.contents + */ + void (*destroy) (/*@only@*/ void *contents); + + /** Prints the implementation-specific data (for debugging purposes). + * Called from yasm_bc_print(). + * \param contents #yasm_bytecode.contents + * \param f file + * \param indent_level indentation level + */ + void (*print) (const void *contents, FILE *f, int indent_level); + + /** Finalizes the bytecode after parsing. Called from yasm_bc_finalize(). + * A generic fill-in for this is yasm_bc_finalize_common(). + * \param bc bytecode + * \param prev_bc bytecode directly preceding bc + */ + void (*finalize) (yasm_bytecode *bc, yasm_bytecode *prev_bc); + + /** Return elements size of a data bytecode. + * This function should return the size of each elements of a data + * bytecode, for proper dereference of symbols attached to it. + * \param bc bytecode + * \return 0 if element size is unknown. + */ + int (*elem_size) (yasm_bytecode *bc); + + /** Calculates the minimum size of a bytecode. + * Called from yasm_bc_calc_len(). + * A generic fill-in for this is yasm_bc_calc_len_common(), but as this + * function internal errors when called, be very careful when using it! + * This function should simply add to bc->len and not set it directly + * (it's initialized by yasm_bc_calc_len() prior to passing control to + * this function). + * + * \param bc bytecode + * \param add_span function to call to add a span + * \param add_span_data extra data to be passed to add_span function + * \return 0 if no error occurred, nonzero if there was an error + * recognized (and output) during execution. + * \note May store to bytecode updated expressions. + */ + int (*calc_len) (yasm_bytecode *bc, yasm_bc_add_span_func add_span, + void *add_span_data); + + /** Recalculates the bytecode's length based on an expanded span length. + * Called from yasm_bc_expand(). + * A generic fill-in for this is yasm_bc_expand_common(), but as this + * function internal errors when called, if used, ensure that calc_len() + * never adds a span. + * This function should simply add to bc->len to increase the length by + * a delta amount. + * \param bc bytecode + * \param span span ID (as given to add_span in calc_len) + * \param old_val previous span value + * \param new_val new span value + * \param neg_thres negative threshold for long/short decision + * (returned) + * \param pos_thres positive threshold for long/short decision + * (returned) + * \return 0 if bc no longer dependent on this span's length, negative if + * there was an error recognized (and output) during execution, + * and positive if bc size may increase for this span further + * based on the new negative and positive thresholds returned. + * \note May store to bytecode updated expressions. + */ + int (*expand) (yasm_bytecode *bc, int span, long old_val, long new_val, + /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres); + + /** Convert a bytecode into its byte representation. + * Called from yasm_bc_tobytes(). + * A generic fill-in for this is yasm_bc_tobytes_common(), but as this + * function internal errors when called, be very careful when using it! + * \param bc bytecode + * \param bufp byte representation destination buffer; + * should be incremented as it's written to, + * so that on return its delta from the + * passed-in buf matches the bytecode length + * (it's okay not to do this if an error + * indication is returned) + * \param bufstart For calculating the correct offset parameter for + * the \a output_value calls: *bufp - bufstart. + * \param d data to pass to each call to + * output_value/output_reloc + * \param output_value function to call to convert values into their byte + * representation + * \param output_reloc function to call to output relocation entries + * for a single sym + * \return Nonzero on error, 0 on success. + * \note May result in non-reversible changes to the bytecode, but it's + * preferable if calling this function twice would result in the + * same output. + */ + int (*tobytes) (yasm_bytecode *bc, unsigned char **bufp, + unsigned char *bufstart, void *d, + yasm_output_value_func output_value, + /*@null@*/ yasm_output_reloc_func output_reloc); + + /** Special bytecode classifications. Most bytecode types should use + * #YASM_BC_SPECIAL_NONE. Others cause special handling to kick in + * in various parts of yasm. + */ + enum yasm_bytecode_special_type { + YASM_BC_SPECIAL_NONE = 0, + + /** Bytecode reserves space instead of outputting data. */ + YASM_BC_SPECIAL_RESERVE, + + /** Adjusts offset instead of calculating len. */ + YASM_BC_SPECIAL_OFFSET, + + /** Instruction bytecode. */ + YASM_BC_SPECIAL_INSN + } special; +} yasm_bytecode_callback; + +/** A bytecode. */ +struct yasm_bytecode { + /** Bytecodes are stored as a singly linked list, with tail insertion. + * \see section.h (#yasm_section). + */ + /*@reldef@*/ STAILQ_ENTRY(yasm_bytecode) link; + + /** The bytecode callback structure for this bytecode. May be NULL + * during partial initialization. + */ + /*@null@*/ const yasm_bytecode_callback *callback; + + /** Pointer to section containing bytecode; NULL if not part of a + * section. + */ + /*@dependent@*/ /*@null@*/ yasm_section *section; + + /** Number of times bytecode is repeated. + * NULL=1 (to save space in the common case). + */ + /*@only@*/ /*@null@*/ yasm_expr *multiple; + + /** Total length of entire bytecode (not including multiple copies). */ + unsigned long len; + + /** Number of copies, integer version. */ + long mult_int; + + /** Line number where bytecode was defined. */ + unsigned long line; + + /** Offset of bytecode from beginning of its section. + * 0-based, ~0UL (e.g. all 1 bits) if unknown. + */ + unsigned long offset; + + /** Unique integer index of bytecode. Used during optimization. */ + unsigned long bc_index; + + /** NULL-terminated array of labels that point to this bytecode (as the + * bytecode previous to the label). NULL if no labels point here. + */ + /*@null@*/ yasm_symrec **symrecs; + + /** Implementation-specific data (type identified by callback). */ + void *contents; +}; + +/** Create a bytecode of any specified type. + * \param callback bytecode callback functions, if NULL, creates empty + * bytecode (may not be resolved or output) + * \param contents type-specific data + * \param line virtual line (from yasm_linemap) + * \return Newly allocated bytecode of the specified type. + */ +YASM_LIB_DECL +/*@only@*/ yasm_bytecode *yasm_bc_create_common + (/*@null@*/ const yasm_bytecode_callback *callback, + /*@only@*/ /*@null@*/ void *contents, unsigned long line); + +/** Transform a bytecode of any type into a different type. + * \param bc bytecode to transform + * \param callback new bytecode callback function + * \param contents new type-specific data + */ +YASM_LIB_DECL +void yasm_bc_transform(yasm_bytecode *bc, + const yasm_bytecode_callback *callback, + void *contents); + +/** Common bytecode callback finalize function, for where no finalization + * is ever required for this type of bytecode. + */ +YASM_LIB_DECL +void yasm_bc_finalize_common(yasm_bytecode *bc, yasm_bytecode *prev_bc); + +/** Common bytecode callback calc_len function, for where the bytecode has + * no calculatable length. Causes an internal error if called. + */ +YASM_LIB_DECL +int yasm_bc_calc_len_common(yasm_bytecode *bc, yasm_bc_add_span_func add_span, + void *add_span_data); + +/** Common bytecode callback expand function, for where the bytecode is + * always short (calc_len never calls add_span). Causes an internal + * error if called. + */ +YASM_LIB_DECL +int yasm_bc_expand_common + (yasm_bytecode *bc, int span, long old_val, long new_val, + /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres); + +/** Common bytecode callback tobytes function, for where the bytecode + * cannot be converted to bytes. Causes an internal error if called. + */ +YASM_LIB_DECL +int yasm_bc_tobytes_common + (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d, + yasm_output_value_func output_value, + /*@null@*/ yasm_output_reloc_func output_reloc); + +/** Get the next bytecode in a linked list of bytecodes. + * \param bc bytecode + * \return Next bytecode. + */ +#define yasm_bc__next(bc) STAILQ_NEXT(bc, link) + +/** Set multiple field of a bytecode. + * A bytecode can be repeated a number of times when output. This function + * sets that multiple. + * \param bc bytecode + * \param e multiple (kept, do not free) + */ +YASM_LIB_DECL +void yasm_bc_set_multiple(yasm_bytecode *bc, /*@keep@*/ yasm_expr *e); + +/** Create a bytecode containing data value(s). + * \param datahead list of data values (kept, do not free) + * \param size storage size (in bytes) for each data value + * \param append_zero append a single zero byte after each data value + * (if non-zero) + * \param arch architecture (optional); if provided, data items + * are directly simplified to bytes if possible + * \param line virtual line (from yasm_linemap) + * \return Newly allocated bytecode. + */ +YASM_LIB_DECL +/*@only@*/ yasm_bytecode *yasm_bc_create_data + (yasm_datavalhead *datahead, unsigned int size, int append_zero, + /*@null@*/ yasm_arch *arch, unsigned long line); + +/** Create a bytecode containing LEB128-encoded data value(s). + * \param datahead list of data values (kept, do not free) + * \param sign signedness (1=signed, 0=unsigned) of each data value + * \param line virtual line (from yasm_linemap) + * \return Newly allocated bytecode. + */ +YASM_LIB_DECL +/*@only@*/ yasm_bytecode *yasm_bc_create_leb128 + (yasm_datavalhead *datahead, int sign, unsigned long line); + +/** Create a bytecode reserving space. + * \param numitems number of reserve "items" (kept, do not free) + * \param itemsize reserved size (in bytes) for each item + * \param line virtual line (from yasm_linemap) + * \return Newly allocated bytecode. + */ +YASM_LIB_DECL +/*@only@*/ yasm_bytecode *yasm_bc_create_reserve + (/*@only@*/ yasm_expr *numitems, unsigned int itemsize, + unsigned long line); + +/** Get the number of items and itemsize for a reserve bytecode. If bc + * is not a reserve bytecode, returns NULL. + * \param bc bytecode + * \param itemsize reserved size (in bytes) for each item (returned) + * \return NULL if bc is not a reserve bytecode, otherwise an expression + * for the number of items to reserve. + */ +YASM_LIB_DECL +/*@null@*/ const yasm_expr *yasm_bc_reserve_numitems + (yasm_bytecode *bc, /*@out@*/ unsigned int *itemsize); + +/** Create a bytecode that includes a binary file verbatim. + * \param filename path to binary file (kept, do not free) + * \param start starting location in file (in bytes) to read data from + * (kept, do not free); may be NULL to indicate 0 + * \param maxlen maximum number of bytes to read from the file (kept, do + * do not free); may be NULL to indicate no maximum + * \param linemap line mapping repository + * \param line virtual line (from yasm_linemap) for the bytecode + * \return Newly allocated bytecode. + */ +YASM_LIB_DECL +/*@only@*/ yasm_bytecode *yasm_bc_create_incbin + (/*@only@*/ char *filename, /*@only@*/ /*@null@*/ yasm_expr *start, + /*@only@*/ /*@null@*/ yasm_expr *maxlen, yasm_linemap *linemap, + unsigned long line); + +/** Create a bytecode that aligns the following bytecode to a boundary. + * \param boundary byte alignment (must be a power of two) + * \param fill fill data (if NULL, code_fill or 0 is used) + * \param maxskip maximum number of bytes to skip + * \param code_fill code fill data (if NULL, 0 is used) + * \param line virtual line (from yasm_linemap) + * \return Newly allocated bytecode. + * \note The precedence on generated fill is as follows: + * - from fill parameter (if not NULL) + * - from code_fill parameter (if not NULL) + * - 0 + */ +YASM_LIB_DECL +/*@only@*/ yasm_bytecode *yasm_bc_create_align + (/*@keep@*/ yasm_expr *boundary, /*@keep@*/ /*@null@*/ yasm_expr *fill, + /*@keep@*/ /*@null@*/ yasm_expr *maxskip, + /*@null@*/ const unsigned char **code_fill, unsigned long line); + +/** Create a bytecode that puts the following bytecode at a fixed section + * offset. + * \param start section offset of following bytecode + * \param fill fill value + * \param line virtual line (from yasm_linemap) + * \return Newly allocated bytecode. + */ +YASM_LIB_DECL +/*@only@*/ yasm_bytecode *yasm_bc_create_org + (unsigned long start, unsigned long fill, unsigned long line); + +/** Get the section that contains a particular bytecode. + * \param bc bytecode + * \return Section containing bc (can be NULL if bytecode is not part of a + * section). + */ +YASM_LIB_DECL +/*@dependent@*/ /*@null@*/ yasm_section *yasm_bc_get_section + (yasm_bytecode *bc); + +/** Add to the list of symrecs that reference a bytecode. For symrec use + * only. + * \param bc bytecode + * \param sym symbol + */ +YASM_LIB_DECL +void yasm_bc__add_symrec(yasm_bytecode *bc, /*@dependent@*/ yasm_symrec *sym); + +/** Delete (free allocated memory for) a bytecode. + * \param bc bytecode (only pointer to it); may be NULL + */ +YASM_LIB_DECL +void yasm_bc_destroy(/*@only@*/ /*@null@*/ yasm_bytecode *bc); + +/** Print a bytecode. For debugging purposes. + * \param f file + * \param indent_level indentation level + * \param bc bytecode + */ +YASM_LIB_DECL +void yasm_bc_print(const yasm_bytecode *bc, FILE *f, int indent_level); + +/** Finalize a bytecode after parsing. + * \param bc bytecode + * \param prev_bc bytecode directly preceding bc in a list of bytecodes + */ +YASM_LIB_DECL +void yasm_bc_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc); + +/** Determine the distance between the starting offsets of two bytecodes. + * \param precbc1 preceding bytecode to the first bytecode + * \param precbc2 preceding bytecode to the second bytecode + * \return Distance in bytes between the two bytecodes (bc2-bc1), or NULL if + * the distance was indeterminate. + * \warning Only valid /after/ optimization. + */ +YASM_LIB_DECL +/*@null@*/ /*@only@*/ yasm_intnum *yasm_calc_bc_dist + (yasm_bytecode *precbc1, yasm_bytecode *precbc2); + +/** Get the offset of the next bytecode (the next bytecode doesn't have to + * actually exist). + * \param precbc preceding bytecode + * \return Offset of the next bytecode in bytes. + * \warning Only valid /after/ optimization. + */ +YASM_LIB_DECL +unsigned long yasm_bc_next_offset(yasm_bytecode *precbc); + +/** Return elemens size of a data bytecode. + * Returns the size of each elements of a data bytecode, for proper dereference + * of symbols attached to it. + * \param bc bytecode + * \return 0 if element size is unknown + */ +YASM_LIB_DECL +int yasm_bc_elem_size(yasm_bytecode *bc); + +/** Resolve EQUs in a bytecode and calculate its minimum size. + * Generates dependent bytecode spans for cases where, if the length spanned + * increases, it could cause the bytecode size to increase. + * Any bytecode multiple is NOT included in the length or spans generation; + * this must be handled at a higher level. + * \param bc bytecode + * \param add_span function to call to add a span + * \param add_span_data extra data to be passed to add_span function + * \return 0 if no error occurred, nonzero if there was an error recognized + * (and output) during execution. + * \note May store to bytecode updated expressions and the short length. + */ +YASM_LIB_DECL +int yasm_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, + void *add_span_data); + +/** Recalculate a bytecode's length based on an expanded span length. + * \param bc bytecode + * \param span span ID (as given to yasm_bc_add_span_func in + * yasm_bc_calc_len) + * \param old_val previous span value + * \param new_val new span value + * \param neg_thres negative threshold for long/short decision (returned) + * \param pos_thres positive threshold for long/short decision (returned) + * \return 0 if bc no longer dependent on this span's length, negative if + * there was an error recognized (and output) during execution, and + * positive if bc size may increase for this span further based on the + * new negative and positive thresholds returned. + * \note May store to bytecode updated expressions and the updated length. + */ +YASM_LIB_DECL +int yasm_bc_expand(yasm_bytecode *bc, int span, long old_val, long new_val, + /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres); + +/** Convert a bytecode into its byte representation. + * \param bc bytecode + * \param buf byte representation destination buffer + * \param bufsize size of buf (in bytes) prior to call; size of the + * generated data after call + * \param gap if nonzero, indicates the data does not really need to + * exist in the object file; if nonzero, contents of buf + * are undefined [output] + * \param d data to pass to each call to output_value/output_reloc + * \param output_value function to call to convert values into their byte + * representation + * \param output_reloc function to call to output relocation entries + * for a single sym + * \return Newly allocated buffer that should be used instead of buf for + * reading the byte representation, or NULL if buf was big enough to + * hold the entire byte representation. + * \note Calling twice on the same bytecode may \em not produce the same + * results on the second call, as calling this function may result in + * non-reversible changes to the bytecode. + */ +YASM_LIB_DECL +/*@null@*/ /*@only@*/ unsigned char *yasm_bc_tobytes + (yasm_bytecode *bc, unsigned char *buf, unsigned long *bufsize, + /*@out@*/ int *gap, void *d, yasm_output_value_func output_value, + /*@null@*/ yasm_output_reloc_func output_reloc) + /*@sets *buf@*/; + +/** Get the bytecode multiple value as an integer. + * \param bc bytecode + * \param multiple multiple value (output) + * \param calc_bc_dist nonzero if distances between bytecodes should be + * calculated, 0 if error should be returned in this case + * \return 1 on error (set with yasm_error_set), 0 on success. + */ +YASM_LIB_DECL +int yasm_bc_get_multiple(yasm_bytecode *bc, /*@out@*/ long *multiple, + int calc_bc_dist); + +/** Get the bytecode multiple value as an expression. + * \param bc bytecode + * \return Bytecode multiple, NULL if =1. + */ +YASM_LIB_DECL +const yasm_expr *yasm_bc_get_multiple_expr(const yasm_bytecode *bc); + +/** Get a #yasm_insn structure from an instruction bytecode (if possible). + * \param bc bytecode + * \return Instruction details if bytecode is an instruction bytecode, + * otherwise NULL. + */ +YASM_LIB_DECL +/*@dependent@*/ /*@null@*/ yasm_insn *yasm_bc_get_insn(yasm_bytecode *bc); + +/** Create a new data value from an expression. + * \param expn expression + * \return Newly allocated data value. + */ +YASM_LIB_DECL +yasm_dataval *yasm_dv_create_expr(/*@keep@*/ yasm_expr *expn); + +/** Create a new data value from a string. + * \param contents string (may contain NULs) + * \param len length of string + * \return Newly allocated data value. + */ +YASM_LIB_DECL +yasm_dataval *yasm_dv_create_string(/*@keep@*/ char *contents, size_t len); + +/** Create a new data value from raw bytes data. + * \param contents raw data (may contain NULs) + * \param len length + * \return Newly allocated data value. + */ +YASM_LIB_DECL +yasm_dataval *yasm_dv_create_raw(/*@keep@*/ unsigned char *contents, + unsigned long len); + +/** Create a new uninitialized data value. + * \return Newly allocated data value. + */ +YASM_LIB_DECL +yasm_dataval *yasm_dv_create_reserve(void); + +#ifndef YASM_DOXYGEN +#define yasm_dv_create_string(s, l) yasm_dv_create_raw((unsigned char *)(s), \ + (unsigned long)(l)) +#endif + +/** Get the underlying value of a data value. + * \param dv data value + * \return Value, or null if non-value (e.g. string or raw). + */ +YASM_LIB_DECL +yasm_value *yasm_dv_get_value(yasm_dataval *dv); + +/** Set multiple field of a data value. + * A data value can be repeated a number of times when output. This function + * sets that multiple. + * \param dv data value + * \param e multiple (kept, do not free) + */ +YASM_LIB_DECL +void yasm_dv_set_multiple(yasm_dataval *dv, /*@keep@*/ yasm_expr *e); + +/** Get the data value multiple value as an unsigned long integer. + * \param dv data value + * \param multiple multiple value (output) + * \return 1 on error (set with yasm_error_set), 0 on success. + */ +YASM_LIB_DECL +int yasm_dv_get_multiple(yasm_dataval *dv, /*@out@*/ unsigned long *multiple); + +/** Initialize a list of data values. + * \param headp list of data values + */ +void yasm_dvs_initialize(yasm_datavalhead *headp); +#ifndef YASM_DOXYGEN +#define yasm_dvs_initialize(headp) STAILQ_INIT(headp) +#endif + +/** Delete (free allocated memory for) a list of data values. + * \param headp list of data values + */ +YASM_LIB_DECL +void yasm_dvs_delete(yasm_datavalhead *headp); + +/** Add data value to the end of a list of data values. + * \note Does not make a copy of the data value; so don't pass this function + * static or local variables, and discard the dv pointer after calling + * this function. + * \param headp data value list + * \param dv data value (may be NULL) + * \return If data value was actually appended (it wasn't NULL), the data + * value; otherwise NULL. + */ +YASM_LIB_DECL +/*@null@*/ yasm_dataval *yasm_dvs_append + (yasm_datavalhead *headp, /*@returned@*/ /*@null@*/ yasm_dataval *dv); + +/** Print a data value list. For debugging purposes. + * \param f file + * \param indent_level indentation level + * \param headp data value list + */ +YASM_LIB_DECL +void yasm_dvs_print(const yasm_datavalhead *headp, FILE *f, int indent_level); + +#endif |