📄 grammar.c
字号:
return emit_push (em, (**ba).data + ((**ba).len - count), c, pos, rbc);
}
/*
byte pool typedef
*/
typedef struct bytepool_
{
byte *_F;
unsigned int _Siz;
} bytepool;
static void bytepool_destroy (bytepool **by)
{
if (*by != NULL)
{
mem_free ((void **) &(**by)._F);
mem_free ((void **) by);
}
}
static void bytepool_create (bytepool **by, int len)
{
*by = (bytepool *) (mem_alloc (sizeof (bytepool)));
if (*by != NULL)
{
(**by)._F = (byte *) (mem_alloc (sizeof (byte) * len));
(**by)._Siz = len;
if ((**by)._F == NULL)
bytepool_destroy (by);
}
}
static int bytepool_reserve (bytepool *by, unsigned int n)
{
byte *_P;
if (n <= by->_Siz)
return 0;
/* byte pool can only grow and at least by doubling its size */
n = n >= by->_Siz * 2 ? n : by->_Siz * 2;
/* reallocate the memory and adjust pointers to the new memory location */
_P = (byte *) (mem_realloc (by->_F, sizeof (byte) * by->_Siz, sizeof (byte) * n));
if (_P != NULL)
{
by->_F = _P;
by->_Siz = n;
return 0;
}
return 1;
}
/*
string to string map typedef
*/
typedef struct map_str_
{
byte *key;
byte *data;
struct map_str_ *next;
} map_str;
static void map_str_create (map_str **ma)
{
*ma = (map_str *) mem_alloc (sizeof (map_str));
if (*ma)
{
(**ma).key = NULL;
(**ma).data = NULL;
(**ma).next = NULL;
}
}
static void map_str_destroy (map_str **ma)
{
if (*ma)
{
map_str_destroy (&(**ma).next);
mem_free ((void **) &(**ma).key);
mem_free ((void **) &(**ma).data);
mem_free ((void **) ma);
}
}
GRAMMAR_IMPLEMENT_LIST_APPEND(map_str)
/*
searches the map for specified key,
if the key is matched, *data is filled with data associated with the key,
returns 0 if the key is matched,
returns 1 otherwise
*/
static int map_str_find (map_str **ma, const byte *key, byte **data)
{
while (*ma)
{
if (str_equal ((**ma).key, key))
{
*data = str_duplicate ((**ma).data);
if (*data == NULL)
return 1;
return 0;
}
ma = &(**ma).next;
}
set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1);
return 1;
}
/*
string to rule map typedef
*/
typedef struct map_rule_
{
byte *key;
rule *data;
struct map_rule_ *next;
} map_rule;
static void map_rule_create (map_rule **ma)
{
*ma = (map_rule *) mem_alloc (sizeof (map_rule));
if (*ma)
{
(**ma).key = NULL;
(**ma).data = NULL;
(**ma).next = NULL;
}
}
static void map_rule_destroy (map_rule **ma)
{
if (*ma)
{
map_rule_destroy (&(**ma).next);
mem_free ((void **) &(**ma).key);
mem_free ((void **) ma);
}
}
GRAMMAR_IMPLEMENT_LIST_APPEND(map_rule)
/*
searches the map for specified key,
if the key is matched, *data is filled with data associated with the key,
returns 0 if the is matched,
returns 1 otherwise
*/
static int map_rule_find (map_rule **ma, const byte *key, rule **data)
{
while (*ma)
{
if (str_equal ((**ma).key, key))
{
*data = (**ma).data;
return 0;
}
ma = &(**ma).next;
}
set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1);
return 1;
}
/*
returns 1 if given character is a white space,
returns 0 otherwise
*/
static int is_space (byte c)
{
return c == ' ' || c == '\t' || c == '\n' || c == '\r';
}
/*
advances text pointer by 1 if character pointed by *text is a space,
returns 1 if a space has been eaten,
returns 0 otherwise
*/
static int eat_space (const byte **text)
{
if (is_space (**text))
{
(*text)++;
return 1;
}
return 0;
}
/*
returns 1 if text points to C-style comment start string,
returns 0 otherwise
*/
static int is_comment_start (const byte *text)
{
return text[0] == '/' && text[1] == '*';
}
/*
advances text pointer to first character after C-style comment block - if any,
returns 1 if C-style comment block has been encountered and eaten,
returns 0 otherwise
*/
static int eat_comment (const byte **text)
{
if (is_comment_start (*text))
{
/* *text points to comment block - skip two characters to enter comment body */
*text += 2;
/* skip any character except consecutive '*' and '/' */
while (!((*text)[0] == '*' && (*text)[1] == '/'))
(*text)++;
/* skip those two terminating characters */
*text += 2;
return 1;
}
return 0;
}
/*
advances text pointer to first character that is neither space nor C-style comment block
*/
static void eat_spaces (const byte **text)
{
while (eat_space (text) || eat_comment (text))
;
}
/*
resizes string pointed by *ptr to successfully add character c to the end of the string,
returns 0 on success,
returns 1 otherwise
*/
static int string_grow (byte **ptr, unsigned int *len, byte c)
{
/* reallocate the string in 16-byte increments */
if ((*len & 0x0F) == 0x0F || *ptr == NULL)
{
byte *tmp = (byte *) mem_realloc (*ptr, ((*len + 1) & ~0x0F) * sizeof (byte),
((*len + 1 + 0x10) & ~0x0F) * sizeof (byte));
if (tmp == NULL)
return 1;
*ptr = tmp;
}
if (c)
{
/* append given character */
(*ptr)[*len] = c;
(*len)++;
}
(*ptr)[*len] = '\0';
return 0;
}
/*
returns 1 if given character is a valid identifier character a-z, A-Z, 0-9 or _
returns 0 otherwise
*/
static int is_identifier (byte c)
{
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
}
/*
copies characters from *text to *id until non-identifier character is encountered,
assumes that *id points to NULL object - caller is responsible for later freeing the string,
text pointer is advanced to point past the copied identifier,
returns 0 if identifier was successfully copied,
returns 1 otherwise
*/
static int get_identifier (const byte **text, byte **id)
{
const byte *t = *text;
byte *p = NULL;
unsigned int len = 0;
if (string_grow (&p, &len, '\0'))
return 1;
/* loop while next character in buffer is valid for identifiers */
while (is_identifier (*t))
{
if (string_grow (&p, &len, *t++))
{
mem_free ((void **) (void *) &p);
return 1;
}
}
*text = t;
*id = p;
return 0;
}
/*
converts sequence of DEC digits pointed by *text until non-DEC digit is encountered,
advances text pointer past the converted sequence,
returns the converted value
*/
static unsigned int dec_convert (const byte **text)
{
unsigned int value = 0;
while (**text >= '0' && **text <= '9')
{
value = value * 10 + **text - '0';
(*text)++;
}
return value;
}
/*
returns 1 if given character is HEX digit 0-9, A-F or a-f,
returns 0 otherwise
*/
static int is_hex (byte c)
{
return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
}
/*
returns value of passed character as if it was HEX digit
*/
static unsigned int hex2dec (byte c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
return c - 'a' + 10;
}
/*
converts sequence of HEX digits pointed by *text until non-HEX digit is encountered,
advances text pointer past the converted sequence,
returns the converted value
*/
static unsigned int hex_convert (const byte **text)
{
unsigned int value = 0;
while (is_hex (**text))
{
value = value * 0x10 + hex2dec (**text);
(*text)++;
}
return value;
}
/*
returns 1 if given character is OCT digit 0-7,
returns 0 otherwise
*/
static int is_oct (byte c)
{
return c >= '0' && c <= '7';
}
/*
returns value of passed character as if it was OCT digit
*/
static int oct2dec (byte c)
{
return c - '0';
}
static byte get_escape_sequence (const byte **text)
{
int value = 0;
/* skip '\' character */
(*text)++;
switch (*(*text)++)
{
case '\'':
return '\'';
case '"':
return '\"';
case '?':
return '\?';
case '\\':
return '\\';
case 'a':
return '\a';
case 'b':
return '\b';
case 'f':
return '\f';
case 'n':
return '\n';
case 'r':
return '\r';
case 't':
return '\t';
case 'v':
return '\v';
case 'x':
return (byte) hex_convert (text);
}
(*text)--;
if (is_oct (**text))
{
value = oct2dec (*(*text)++);
if (is_oct (**text))
{
value = value * 010 + oct2dec (*(*text)++);
if (is_oct (**text))
value = value * 010 + oct2dec (*(*text)++);
}
}
return (byte) value;
}
/*
copies characters from *text to *str until " or ' character is encountered,
assumes that *str points to NULL object - caller is responsible for later freeing the string,
assumes that *text points to " or ' character that starts the string,
text pointer is advanced to point past the " or ' character,
returns 0 if string was successfully copied,
returns 1 otherwise
*/
static int get_string (const byte **text, byte **str)
{
const byte *t = *text;
byte *p = NULL;
unsigned int len = 0;
byte term_char;
if (string_grow (&p, &len, '\0'))
return 1;
/* read " or ' character that starts the string */
term_char = *t++;
/* while next character is not the terminating character */
while (*t && *t != term_char)
{
byte c;
if (*t == '\\')
c = get_escape_sequence (&t);
else
c = *t++;
if (string_grow (&p, &len, c))
{
mem_free ((void **) (void *) &p);
return 1;
}
}
/* skip " or ' character that ends the string */
t++;
*text = t;
*str = p;
return 0;
}
/*
gets emit code, the syntax is:
".emtcode" " " <symbol> " " (("0x" | "0X") <hex_value>) | <dec_value> | <character>
assumes that *text already points to <symbol>,
returns 0 if emit code is successfully read,
returns 1 otherwise
*/
static int get_emtcode (const byte **text, map_byte **ma)
{
const byte *t = *text;
map_byte *m = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -