📄 grammar.c
字号:
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; map_byte_create (&m); if (m == NULL) return 1; if (get_identifier (&t, &m->key)) { map_byte_destroy (&m); return 1; } eat_spaces (&t); if (*t == '\'') { byte *c; if (get_string (&t, &c)) { map_byte_destroy (&m); return 1; } m->data = (byte) c[0]; mem_free ((void **) (void *) &c); } else if (t[0] == '0' && (t[1] == 'x' || t[1] == 'X')) { /* skip HEX "0x" or "0X" prefix */ t += 2; m->data = (byte) hex_convert (&t); } else { m->data = (byte) dec_convert (&t); } eat_spaces (&t); *text = t; *ma = m; return 0;}/* gets regbyte declaration, the syntax is: ".regbyte" " " <symbol> " " (("0x" | "0X") <hex_value>) | <dec_value> | <character> assumes that *text already points to <symbol>, returns 0 if regbyte is successfully read, returns 1 otherwise
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -