/gtparser

generic text parsing functions

Primary LanguageCGNU Lesser General Public License v2.1LGPL-2.1

gtparser

Small library of generic text parsing functions enough to parse simple grammars, like in config files.

For such grammars, it may be easier to implement parsing rules by hand, over than using parser generator like Bison.

To use these functions, source text should be available as a read-only raw array of bytes in utf-8 or other ascii-based encoding (for example latin1 or cp1251).

Large text files may be mmap()'ed to a memory region before parsing.

Contents

Generic text functions

  1. digit_value
  2. is_digit
  3. _is_first_name
  4. _is_next_name
  5. _hex_char_value
  6. is_first_name (table lookup-based)
  7. is_next_name (table lookup-based)
  8. hex_char_value (table lookup-based)
  9. gt_scan_name
  10. gt_scan_uint
  11. gt_scan_uint64
  12. gt_scan_hex
  13. gt_scan_hex64
  14. is_space

Source text iterator API (gtparser/parser_base.h)

  1. src_iter_init
  2. src_iter_step
  3. src_iter_eof
  4. src_iter_next
  5. src_iter_process_tab
  6. src_iter_check_tab
  7. src_iter_inc_line
  8. src_iter_check
  9. src_iter_current_char
  10. src_iter_char_or_eof
  11. src_iter_get_column
  12. src_iter_get_pos
  13. src_iter_return_pos
  14. src_iter_save_pos
  15. src_iter_return_save_pos
  16. src_iter_restore_pos

Handy functions for use with source text iterator

  1. gt_skip_rest_of_line
  2. _skip_comment
  3. read_non_space_skip_comments
  4. read_non_space_stop_eol
  5. read_name
  6. read_uint
  7. read_uint64
  8. read_hex
  9. read_hex64
  10. gt_parse_cstring
  11. gt_copy_cstring

Helpers for composing error message

  1. parser_err_reserve
  2. parser_err_reserve_
  3. parser_err_prepend_at
  4. parser_err_prepend_at_
  5. parser_err_prepend_at_line
  6. parser_err_prepend_at_line_
  7. parser_err_prepend_at_char
  8. parser_err_prepend_at_char_
  9. parser_err_print_char
  10. parser_err_print_chars
  11. parser_err_print_string_constant
  12. parser_err_print_string
  13. parser_err_print
  14. parser_err_finish

Check if given char is a decimal digit and get its value

unsigned digit_value(char c);

Parameters:

  • c - char to check

Returns: value <= 9 if c is matched by regexp [0-9]

Declared in: gtparser/char_func.h

Check if given char is a decimal digit

int is_digit(char c);

Parameters:

  • c - char to check

Returns: non-zero if c is matched by regexp [0-9]

Declared in: gtparser/char_func.h

Check if given char may start an identifier name

int _is_first_name(char c);

Parameters:

  • c - char to check

Returns: non-zero if c is matched by regexp: [_a-zA-Z]

Declared in: gtparser/char_func.h

Note: table lookup-based is_first_name() may be slightly faster than this header-only inline _is_first_name()

Check if given char may continue an identifier name

int _is_next_name(char c);

Parameters:

  • c - char to check

Returns: non-zero if c is matched by regexp: [_a-zA-Z0-9]

Declared in: gtparser/char_func.h

Note: table lookup-based is_next_name() may be slightly faster than this header-only inline _is_next_name()

Check if given char is a hexadecimal digit and get its value

unsigned _hex_char_value(char c);

Parameters:

  • c - char to check

Returns: value <= 15 if c is matched by regexp: [0-9a-fA-F]

Declared in: gtparser/char_func.h

Note: table lookup-based hex_char_value() may be slightly faster than this header-only inline _hex_char_value()

Check if given char may start an identifier name (table lookup-based version)

int is_first_name(char c);

Parameters:

  • c - char to check

Returns: non-zero if c is matched by regexp: [_a-zA-Z]

Declared in: gtparser/name_scanner.h

Check if given char may continue an identifier name (table lookup-based version)

int is_next_name(char c);

Parameters:

  • c - char to check

Returns: non-zero if c is matched by regexp: [_a-zA-Z0-9]

Declared in: gtparser/name_scanner.h

Check if given char is a hexadecimal digit and get its value (table lookup-based version)

unsigned hex_char_value(char c);

Parameters:

  • c - char to check

Returns: value <= 15 if c is matched by regexp: [0-9a-fA-F]

Declared in: gtparser/name_scanner.h

Scan characters of a name

const char *gt_scan_name(const char *s/*<end*/, const char *const end);

Parameters:

  • s - points to first char of a name in a buffer (likely a char matched by regexp: [_a-zA-Z])
  • end - points one char beyond the buffer containing a name

Note: s < end

Returns: pointer beyond the last char of scanned name (pointer to char not matched by regexp: [_a-zA-Z0-9]) or end

Declared in: gtparser/name_scanner.h

Scan unsigned decimal integer

const char *gt_scan_uint(const char *s/*<end*/, const char *const end, unsigned *number/*out*/);
const char *gt_scan_uint64(const char *s/*<end*/, const char *const end, unsigned INT64_TYPE *number/*out*/);

Parameters:

  • s - points to first char of unsigned decimal integer printed in a buffer (char matched by regexp: [0-9])
  • end - points one char beyond the buffer containing printed unsigned decimal integer
  • number - (output) scanned unsigned (64-bit) integer value

Notes:

  • s < end
  • INT64_TYPE - 64-bit integer type, by default defined as long long

Returns: pointer beyond the last char of scanned unsigned decimal integer (pointer to char not matched by regexp: [0-9]) or end

Note: on unsigned integer overflow, if printed number is too big, returns NULL

Declared in: gtparser/int_scanner.h

Scan unsigned hexadecimal integer

const char *gt_scan_hex(const char *s/*<end*/, const char *const end, unsigned *number/*out*/);
const char *gt_scan_hex64(const char *s/*<end*/, const char *const end, unsigned INT64_TYPE *number/*out*/);

Parameters:

  • s - points to first char of unsigned hexadecimal integer printed in a buffer (char matched by regexp: [0-9a-fA-F])
  • end - points one char beyond the buffer containing printed unsigned hexadecimal integer
  • number - (output) scanned unsigned (64-bit) integer value

Notes:

  • s < end
  • INT64_TYPE - 64-bit integer type, by default defined as long long

Returns: pointer beyond the last char of scanned unsigned hexadecimal integer (pointer to char not matched by regexp: [0-9a-fA-F]) or end

Note: on unsigned integer overflow, if printed number is too big, returns NULL

Declared in: gtparser/int_scanner.h

Check if char is a space

int is_space(char c);

Parameters:

  • c - checked char

Returns: non-zero if c is a space - character with value in ASCII range [0..32]

Note: this fast and simple function is usable to skip all space characters, like tabulations, new lines, form feeds, bells and so on

Declared in: gtparser/parser_base.h


Initialize source text iterator structure

void src_iter_init(struct src_iter *it, const char *input, size_t size);

Parameters:

  • it - iterator structure to initialize
  • input - read-only text buffer to parse
  • size - number of chars to parse in text buffer

Note: Iterator line and column numbers are set to 1

Example:

extern const char *input;
extern size_t size;
struct src_iter it;
src_iter_init(&it, input, size);

Declared in: gtparser/parser_base.h

Step over current character

void src_iter_step(struct src_iter *it);

Parameters:

  • it - text iterator structure

Iterator column number incremented by 1

Notes:

  • assume current char was checked for <TAB> (horizontal tabulate character '\t') or <EOL> (end-of-line indicator character '\n')
  • iterator must not point to <EOF> (end-of-file indicator)

Declared in: gtparser/parser_base.h

Check if iterator points to <EOF>

int src_iter_eof(const struct src_iter *it);

Parameters:

  • it - text iterator structure

Returns: non-zero if iterator points to <EOF>, 0 - if not

Example of simple parsing loop:

extern struct src_iter *it;
while (!src_iter_eof(it)) {
	/* process current character */
	src_iter_step(it);
}

Declared in: gtparser/parser_base.h

Move iterator to next character and check it for <EOF>

int src_iter_next(struct src_iter *it);

Parameters:

  • it - text iterator structure

Returns: non-zero if current character is not <EOF>, may continue parsing

Iterator column number incremented by 1

Notes:

  • assume current char was checked for <TAB> or <EOL>
  • iterator must not point to <EOF>

Example of simple parsing loop:

extern struct src_iter *it;
if (!src_iter_eof(it)) {
	do {
		/* process current character */
	} while (src_iter_next(it));
}

Declared in: gtparser/parser_base.h

Account encountered <TAB> character

void src_iter_process_tab(struct src_iter *it);

Parameters:

  • it - text iterator structure

Iterator column number incremented by some value in range [1..GTPARSER_TAB_SIZE], depending on current column number value

Notes:

  • iterator must point to <TAB> character
  • horizontal tabulate width equals to GTPARSER_TAB_SIZE spaces, 4 by default

Declared in: gtparser/parser_base.h

Check if current character is a <TAB>

void src_iter_check_tab(struct src_iter *it);

Parameters:

  • it - text iterator structure

Check if current character is a <TAB> and account it by src_iter_process_tab() if it is

Note: iterator must not point to <EOF>

Declared in: gtparser/parser_base.h

Account encountered <EOL> character

void src_iter_inc_line(struct src_iter *it);

Parameters:

  • it - text iterator structure

Increment iterator line number, set column number to zero

Note: iterator must point to <EOL> character

Declared in: gtparser/parser_base.h

Check if current character is a <TAB> or <EOL>

void src_iter_check(struct src_iter *it);

Parameters:

  • it - text iterator structure

Check if current character is a <TAB> or <EOL>, then account it appropriately by src_iter_process_tab() or src_iter_inc_line()

Note: iterator must not point to <EOF>

Example of simple parsing loop:

extern struct src_iter *it;
if (!src_iter_eof(it)) {
	do {
		/* process current character */
		/* account <TAB> or <EOL> */
		src_iter_check(it);
	} while (src_iter_next(it));
}

Declared in: gtparser/parser_base.h

Get current character

char src_iter_current_char(const struct src_iter *it);

Parameters:

  • it - text iterator structure

Returns: current character iterator points to

Note: iterator must not point to <EOF>

Example of simple parsing loop:

extern struct src_iter *it;
if (!src_iter_eof(it)) {
	do {
		/* get current character to process */
		char c = src_iter_current_char(it);
		/* process current character */
		/* account <TAB> or <EOL> */
		src_iter_check(it);
	} while (src_iter_next(it));
}

Declared in: gtparser/parser_base.h

Get current character or '\0' as <EOF> indicator

char src_iter_char_or_eof(const struct src_iter *it);

Parameters:

  • it - text iterator structure

Returns: current non-zero character if iterator points to non-<EOF>, else returns '\0'

Note: this function may be usable for parsing texts where characters with zero value are not expected

Example of simple parsing loop:

extern struct src_iter *it;
for (;;) {
	/* get current character to process */
	char c = src_iter_char_or_eof(it);
	if (!c)
		break; /* iterator points to <EOF> */
	/* process current character */
	/* account <TAB> or <EOL> */
	src_iter_check(it);
}

Declared in: gtparser/parser_base.h

Get current column number

unsigned src_iter_get_column(const struct src_iter *it);

Parameters:

  • it - text iterator structure

Returns: current iterator column number

Note: column number may overflow for large texts, but it is not fatal for parsing

Declared in: gtparser/parser_base.h

Get iterator text position (line and column numbers)

void src_iter_get_pos(const struct src_iter *it, struct src_pos *pos/*out*/);

Parameters:

  • it - text iterator structure
  • pos - (output) current iterator text position

Declared in: gtparser/parser_base.h

Return iterator text position (line and column numbers)

struct src_pos src_iter_return_pos(const struct src_iter *it);

Parameters:

  • it - text iterator structure

Returns: current iterator text position

Declared in: gtparser/parser_base.h

Save iterator state

void src_iter_save_pos(const struct src_iter *it, struct src_save_pos *save_pos/*out*/);

Parameters:

  • it - text iterator structure
  • save_pos - (output) current iterator state

save_pos may be used to restore iterator state - unparse characters processed after save_pos was taken

Declared in: gtparser/parser_base.h

Return iterator state

struct src_save_pos src_iter_return_save_pos(const struct src_iter *it);

Parameters:

  • it - text iterator structure

Returns: current iterator state

Returned state value may be used to restore iterator state - unparse characters processed after state was taken

Declared in: gtparser/parser_base.h

Restore iterator state

void src_iter_restore_pos(struct src_iter *it, const struct src_save_pos *save_pos);

Parameters:

  • it - text iterator structure
  • save_pos - saved iterator state

Note: save_pos may be obtained either by src_iter_save_pos() or src_iter_return_save_pos()

Declared in: gtparser/parser_base.h


Skip characters until new line

void gt_skip_rest_of_line(struct src_iter *it);

Parameters:

  • it - text iterator structure

Skip current character, then next characters until <EOL>, then skip <EOL>

On return, iterator points to beginning of next line or to <EOF>

Notes:

  • this function is usable to skip one-line comment
  • before the call, iterator must not point to <EOF> (assume iterator points to char indicating start of a comment)

Declared in: gtparser/parser_base.h

Skip one-line comment

void _skip_comment(struct src_iter *it);

Just another name of gt_skip_rest_of_line() function

Declared in: gtparser/parser_base.h

Read first non-space character skipping comments

char read_non_space_skip_comments(struct src_iter *it, char comment);

Parameters:

  • it - text iterator structure
  • comment - char indicating start of one-line comment

Returns: current non-space char or '\0', if non-space char was not found and iterator points to <EOF>

Notes:

  • checks all characters, starting from current one by is_space() function
  • skips one-line comments by _skip_comment() function
  • iterator may point to <EOF>

Declared in: gtparser/parser_base.h

Read first non-space character or <EOL>

char read_non_space_stop_eol(struct src_iter *it);

Parameters:

  • it - text iterator structure

Returns: current non-space char or <EOL> or '\0', if non-space char or <EOL> was not found and iterator points to <EOF>

Declared in: gtparser/parser_base.h

Read characters of a name

const char *read_name(struct src_iter *it);

Parameters:

  • it - source text iterator structure

Returns: pointer to first char of read name

Notes:

  • before the call, it must point to first char of a name (src_iter_current_char() returns likely a char matched by regexp: [_a-zA-Z])
  • by return, it will point to non-name char (not matched by regexp [_a-zA-Z0-9]) or to <EOF>

Declared in: gtparser/name_parser.h

Read unsigned decimal integer

int read_uint(struct src_iter *it, unsigned *number/*out*/);
int read_uint64(struct src_iter *it, unsigned INT64_TYPE *number/*out*/);

Parameters:

  • it - source text iterator structure
  • number - (output) parsed unsigned (64-bit) integer value

Returns: 1 if number was successfully read, 0 - on unsigned integer overflow, if printed number is too big

Notes:

  • before the call, it must point to first char of unsigned decimal integer (src_iter_current_char() must return a char matched by regexp: [0-9])
  • by successful return, it will point beyond the last char of scanned unsigned decimal integer (points to a char not matched by regexp: [0-9] or to <EOF>)
  • on integer overflow, it not changed
  • INT64_TYPE - 64-bit integer type, by default defined as long long

Declared in: gtparser/int_parser.h

Read unsigned hexadecimal integer

int read_hex(struct src_iter *it, unsigned *number/*out*/);
int read_hex64(struct src_iter *it, unsigned INT64_TYPE *number/*out*/);

Parameters:

  • it - source text iterator structure
  • number - (output) parsed unsigned (64-bit) integer value

Returns: 1 if number was successfully read, 0 - on unsigned integer overflow, if printed number is too big

Notes:

  • before the call, it must point to first char of unsigned hexadecimal integer (src_iter_current_char() must return a char matched by regexp: [0-9a-fA-F])
  • by successful return, it will point beyond the last char of scanned unsigned hexadecimal integer (points to a char not matched by regexp: [0-9a-fA-F] or to <EOF>)
  • on integer overflow, it not changed
  • INT64_TYPE - 64-bit integer type, by default defined as long long

Declared in: gtparser/int_parser.h

Parse C-string

enum PARSE_CSTRING_ERR {
	PARSE_CSTRING_OK = 0,              /* C-string successfully parsed                                             */
	PARSE_CSTRING_UNESCAPED_NEWLINE,   /* unescaped line-feed '\n' or carriage-return '\r'                         */
	PARSE_CSTRING_EXPECTING_LINE_FEED, /* expecting line-feed '\n' after carriage-return '\r'                      */
	PARSE_CSTRING_EXPECTING_HEX_DIGIT, /* expecting hexadecimal digit in hex escape sequence after '\x'            */
	PARSE_CSTRING_TOO_BIG_OCTAL,       /* too big octal character value > 255 in string, maximum allowed is '\377' */
	PARSE_CSTRING_NULL_INSIDE_CSTRING, /* null character '\0' inside C-string is not allowed                       */
	PARSE_CSTRING_UNTERMINATED         /* unterminated string                                                      */
};

enum PARSE_CSTRING_ERR gt_parse_cstring(struct src_iter *it, size_t *removed/*out*/);

Parameters:

  • it - source text iterator structure
  • removed - (output) number of meta-characters to be removed by gt_copy_cstring()

Returns: one of enum PARSE_CSTRING_ERR values

Notes:

  • before the call, it must point to first (opening) quote of source C-string (src_iter_current_char() returns '"')
  • by successful return, it will point to last (closing) quote of source C-string
  • on error, it will point to error position

Meta-characters removed by gt_copy_cstring():

  • each line continuation-split (consists of two chars: \<EOL>) is removed
  • each '\' is removed and next char after it is unescaped (likely converted to some to non-printable char)
  • list of recognized escape sequences (a character after '\' will be replaced with byte value in {}): \a{0x07} \b{0x08} \t{0x09} \n{0x0a} \v{0x0b} \f{0x0c} \r{0x0d}
  • encoded characters in octadecimal (\377) or hexadecimal (\xff) encoding are unencoded
  • octadecimal-encoded chars (max 3 octadecimal digits after '\'): \0..\7, \00..\77, \000..\377
  • hexadecimal-encoded chars (max 2 hexadecimal digits after '\x'): \x0..\xf, \x00..\xff

Example: see gt_copy_cstring()

Declared in: gtparser/cstring_parser.h

Copy parsed C-string

void gt_copy_cstring(char dst[]/*out*/, const char *begin, const char *end, size_t removed);

Parameters:

  • dst - destination buffer to copy and unescape C-string to
  • begin - points to next char after first (opening) quote in source C-string
  • end - points to the last (closing) quote in source C-string
  • removed - number of meta-characters to be removed (determined by gt_parse_cstring())

Note: dst buffer must be large enough to read unescaped source C-string into it: dst buffer length must be >= (end - begin - removed)

Example:

extern struct src_iter *it;
extern char dst[];
extern size_t dst_size;
size_t removed;
const char *first = it->current; /* assume it points to first (opening) quote */
enum PARSE_CSTRING_ERR err = gt_parse_cstring(it, &removed/*out*/);
if (PARSE_CSTRING_OK == err) {
	const char *last = it->current; /* now it points to last (closing) quote */
	size_t need_size = (size_t)(last - first) - removed; /* size of buffer to hold unescaped C-string + terminating '\0' */
	if (dst_size >= need_size) {
		gt_copy_cstring(dst, first + 1/*quote*/, last, removed);
		dst[need_size - 1] = '\0';
	}
}

Declared in: gtparser/cstring_parser.h


Reserve a space for error message location info

char *parser_err_reserve(char err_buf[], size_t err_buf_size, size_t filename_reserve);
char *parser_err_reserve_(char err_buf[], size_t err_buf_size);

Parameters:

  • err_buf - buffer where to compose error message
  • err_buf_size - size of err_buf
  • filename_reserve - how much space to reserve in err_buf for file name passed to parser_err_prepend_at()

Returns: pointer to a space inside err_buf to print error message details to, or returns err_buf, if err_buf is too small

parser_err_reserve_() - just calls parser_err_reserve() with zero filename_reserve value

Note: if err_buf is big enough, then parser_err_prepend_at() will prepend resulting error message with something like "filename: parse error at (4294967295:4294967295):"

Example: see parser_err_prepend_at()

Declared in: gtparser/parser_err.h

Prepend location info to error message

const char *parser_err_prepend_at(
	char err_buf,
	size_t err_buf_size,
	size_t filename_reserve/*0?*/,
	const char *filename/*NULL?*/,
	const char *err,
	unsigned line/*0?*/,
	unsigned column/*0?*/);

const char *parser_err_prepend_at_line(
	char err_buf,
	size_t err_buf_size,
	size_t filename_reserve/*0?*/,
	const char *filename/*NULL?*/,
	const char *err,
	unsigned line/*!=0*/);

const char *parser_err_prepend_at_char(
	char err_buf,
	size_t err_buf_size,
	size_t filename_reserve/*0?*/,
	const char *filename/*NULL?*/,
	const char *err,
	unsigned column/*!=0*/);

const char *parser_err_prepend_at_(
	char err_buf,
	size_t err_buf_size,
	const char *err,
	unsigned line/*0?*/,
	unsigned column/*0?*/);

const char *parser_err_prepend_at_line_(
	char err_buf,
	size_t err_buf_size,
	const char *err,
	unsigned line/*!=0*/);

const char *parser_err_prepend_at_char_(
	char err_buf,
	size_t err_buf_size,
	const char *err,
	unsigned column/*!=0*/);

Parameters:

  • err_buf - buffer where to compose error message
  • err_buf_size - size of err_buf
  • filename_reserve - how much space to reserve in err_buf for file name
  • filename - '\0'-terminated source file name where an error was encountered, may be NULL
  • err - '\0'-terminated error message
  • line - source line number where a parsing error was encountered, if zero, then only column number is printed
  • column - source column number where a parsing error was encountered, if zero, then only line number is printed

Returns: pointer to composed error message with prepended location info in err_buf or err, if err_buf is too small

  • parser_err_prepend_at_line() - just calls parser_err_prepend_at() with zero column value
  • parser_err_prepend_at_char() - just calls parser_err_prepend_at() with zero line value
  • parser_err_prepend_at_() - just calls parser_err_prepend_at() with zero filename_reserve and NULL filename values
  • parser_err_prepend_at_line_() - just calls parser_err_prepend_at_line() with zero filename_reserve and NULL filename values
  • parser_err_prepend_at_char_() - just calls parser_err_prepend_at_line() with zero filename_reserve and NULL filename values

Note: if error message was printed to err_buf (i.e. err is the value returned by parser_err_reserve()), then err_buf, err_buf_size and filename_reserve must be the same that were passed to parser_err_reserve()

Example:

extern char err_buf[];
extern size_t err_buf_size;
extern size_t filename_reserve;
const char *err = parser_err_reserve(err_buf, err_buf_size, filename_reserve);
size_t err_space = (size_t)(err_buf + err_buf_size - err);
...
snprintf((char*)err, err_space, "some parameterized error message: %d", 100);
/* or */
err = "some error message without parameters";
...
extern const char *filename;
extern unsigned line;
extern unsigned column;
const char *err_msg = parser_err_prepend_at(
	err_buf,
	err_buf_size,
	filename_reserve,
	filename,
	err,
	line,
	column);

Declared in: gtparser/parser_err.h

Append character to a buffer

char *parser_err_print_char(char *buf/*<=end*/, const char *const end, char c);

Parameters:

  • buf - position in destination buffer where to append character
  • end - points one char beyond destination buffer
  • c - character to append to destination buffer

Returns: buffer position <= end after appended character

Note: character added only if there is a place for it in destination buffer

Example:

extern char *buf;
extern char *end;
if (error)
	buf = parser_err_print_char(buf, end, '.');
...

Declared in: gtparser/parser_err.h

Append characters array to a buffer

char *parser_err_print_chars(char *buf/*<=end*/, const char *const end, const char chars[], size_t count);

Parameters:

  • buf - position in destination buffer where to append chars
  • end - points one char beyond destination buffer
  • chars - characters array to append to destination buffer
  • count - number of characters to append to destination buffer

Returns: buffer position <= end after appended characters

Note: characters array tail may be trimmed if it's too long to fit in buffer

Example:

extern char *buf;
extern char *end;
extern int error;
if (error)
	buf = parser_err_print_chars(buf, end, "some error", 10);
...

Declared in: gtparser/parser_err.h

Append string constant to a buffer

char *parser_err_print_string_constant(char *buf/*<=end*/, const char *const end, const char s[]);

Parameters:

  • buf - position in destination buffer where to append string constant
  • end - points one char beyond destination buffer
  • s - string constant to append to destination buffer

Returns: buffer position <= end after appended string constant

Note: string constant tail may be trimmed if it's too long to fit in buffer

Note: implemented as a macro calling parser_err_print_chars()

Example:

extern char *buf;
extern char *end;
extern int error;
if (error)
	buf = parser_err_print_string_constant(buf, end, "some error");
...

Declared in: gtparser/parser_err.h

Append '\0'-terminated string to a buffer

char *parser_err_print_string(char *buf/*<=end*/, const char *const end, const char *string/*'\0'-terminated*/);

Parameters:

  • buf - position in destination buffer where to append string
  • end - points one char beyond destination buffer
  • string - string to append to destination buffer

Returns: buffer position <= end after appended string

Note: string tail may be trimmed if it's too long to fit in buffer

Example:

extern char *buf;
extern char *end;
extern int error;
extern const char *err_message1;
if (error)
	buf = parser_err_print_string(buf, end, err_message1);
...

Declared in: gtparser/parser_err.h

Append parametrized message to a buffer

char *parser_err_print(char *buf/*<=end*/, const char *const end, const char *format, ...);

Parameters:

  • buf - position in destination buffer where to append formatted message
  • end - points one char beyond destination buffer
  • format - printf()-like format string of parametrized message to append to destination buffer
  • ... - parameters of parametrized message

Returns: buffer position <= end after appended formatted message

Note: formatted message tail may be trimmed if it's too long to fit in buffer

Example:

extern char *buf;
extern char *end;
extern int error;
if (error)
	buf = parser_err_print(buf, end, "an error occurred: %d", error);
...

Declared in: gtparser/parser_err.h

Terminate buffer with '\0'

void parser_err_finish(char *buf/*<=end*/, const char *const end, size_t err_space);

Parameters:

  • buf - position in destination buffer where to append '\0'
  • end - points one char beyond destination buffer
  • err_space - total destination buffer size

Notes:

  • if err_space is zero, nothing is appended
  • if buf == end, then last char in buffer is replaced with '\0'

Example:

extern char err[];
extern size_t err_space;
{
	const char *buf = err;
	const char *const end = err + err_space;
	buf = parser_err_print(buf, end, "some message: %d", 100);
	buf = parser_err_print(buf, end, "some message: %d", 101);
	buf = parser_err_print(buf, end, "some message: %d", 102);
	parser_err_finish(buf, end, err_space);
}
/* err - '\0'-terminated error message */

Declared in: gtparser/parser_err.h


Installing

  1. Get clean-build build system:

    git clone https://github.com/mbuilov/clean-build

  2. For windows, get Gnu Make executable:

    git clone https://github.com/mbuilov/gnumake-windows

  3. Build library

    3.1 On Linux (example):

    $ make MTOP=/home/user/clean-build OS=LINUX CPU=x86_64

    3.2 On Windows (example):

    C:\tools\gnumake-4.2.1.exe MTOP=C:\tools\clean-build OS=WINXX CPU=x86_64 WINVARIANT=WIN7 VS="C:\Program Files (x86)\Microsoft Visual Studio 14.0" WDK="C:\Program Files (x86)\Windows Kits\10" WDK_TARGET="10.0.14393.0"

    Tips:

    • specify NO_STATIC=1 to not build static library archive
    • specify NO_SHARED=1 to not build shared library (dll)
    • specify TARGET=DEBUG to build debug versions of libraries
    • to view other possible values of OS, CPU or TARGET variables, define them as ?
    • specify V=1 for verbose build, to print executed commands

    If make target is not specified, default target all (compile the library) will be built

    By default, all variants of libraries are built:

    • for static library - GTPARSER_LIB_VARIANTS="R P D S"
    • for dynamic library - GTPARSER_DLL_VARIANTS="R S"

    Notes:

    • if some variant is unsupported under target platform, variant is filtered-out from list of variants
    • if variants list is empty, default variant R is built

    Variants of static library for LINUX:

    • R - default, position-dependent code for linking executables
    • P - position-independent code for linking executables (-fpie compiler option)
    • D - position-independent code for linking shared objects (-fpic compiler option)

    Variants of static library for WINDOWS:

    • R - default, dynamically linked multi-threaded C runtime library (/MD compiler option)
    • S - statically linked multi-threaded C runtime library (/MT compiler option)

    Variants of dynamic library for LINUX:

    • R - default, position-independent code (-fpic compiler option)

    Variants of dynamic library for WINDOWS:

    • R - default, dynamically linked multi-threaded C runtime library (/MD compiler option)
    • S - statically linked multi-threaded C runtime library (/MT compiler option)

    Tip: there are predefined targets:

    • tests - to build library and tests
    • check - to build library and tests, then run tests
    • clean - to delete built artifacts, except created directories
    • distclean - to delete all artifacts, including created directories
  4. Install library and interface headers

    Note: make command should be the same as for building, except the target should be install or uninstall

    4.1 On Linux (example):

    possibly as root, do

    $ make MTOP=/home/user/clean-build OS=LINUX CPU=x86_64 install

    4.2 On Windows (example):

    C:\tools\gnumake-4.2.1.exe MTOP=C:\tools\clean-build OS=WINXX CPU=x86_64 WINVARIANT=WIN7 VS="C:\Program Files (x86)\Microsoft Visual Studio 14.0" WDK="C:\Program Files (x86)\Windows Kits\10" WDK_TARGET="10.0.14393.0" PREFIX=C:\dst install

    Note: Headers are installed in $(INCLUDEDIR), libraries - in $(LIBDIR)

    Tips:

    • define variable PREFIX to override default install location - /usr/local (for UNIX) or artifacts (for WINDOWS)
    • define variable INCLUDEDIR to override default headers install location - $(PREFIX)/include
    • define variable LIBDIR to override default libraries install location - $(PREFIX)/lib
    • define variable DESTDIR to add prefix to $(PREFIX) - to make path to temporary install location
    • specify NO_INSTALL_HEADERS=1 to not install development library interface header files
    • specify NO_INSTALL_LA=1 to not install development libtool library files (for UNIX)
    • specify NO_INSTALL_PC=1 to not install development pkg-config library files (for UNIX)
    • specify NO_INSTALL_IMPS=1 to not install development dll import libraries (for WINDOWS)
    • specify NO_DEVEL=1 to not install all above development files (headers, .la, .pc, import libraries)

    Tip: there is one more predefined target:

    • uninstall - to delete installed files. Note: some installed directories may not be deleted.