⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 grammar.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:

    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 + -