Ejemplo n.º 1
0
static int generate_val (NCDValue *value, ExpString *out_str)
{
    switch (NCDValue_Type(value)) {
        case NCDVALUE_STRING: {
            const char *str = NCDValue_StringValue(value);
            size_t len = NCDValue_StringLength(value);
            
            if (!ExpString_AppendChar(out_str, '"')) {
                goto fail;
            }
            
            for (size_t i = 0; i < len; i++) {
                if (str[i] == '\0') {
                    char buf[5];
                    snprintf(buf, sizeof(buf), "\\x%02"PRIx8, (uint8_t)str[i]);
                    
                    if (!ExpString_Append(out_str, buf)) {
                        goto fail;
                    }
                    
                    continue;
                }
                
                if (str[i] == '"' || str[i] == '\\') {
                    if (!ExpString_AppendChar(out_str, '\\')) {
                        goto fail;
                    }
                }
                
                if (!ExpString_AppendChar(out_str, str[i])) {
                    goto fail;
                }
            }
            
            if (!ExpString_AppendChar(out_str, '"')) {
                goto fail;
            }
        } break;
        
        case NCDVALUE_LIST: {
            if (!ExpString_AppendChar(out_str, '{')) {
                goto fail;
            }
            
            int is_first = 1;
            
            for (NCDValue *e = NCDValue_ListFirst(value); e; e = NCDValue_ListNext(value, e)) {
                if (!is_first) {
                    if (!ExpString_Append(out_str, ", ")) {
                        goto fail;
                    }
                }
                
                if (!generate_val(e, out_str)) {
                    goto fail;
                }
                
                is_first = 0;
            }
            
            if (!ExpString_AppendChar(out_str, '}')) {
                goto fail;
            }
        } break;
        
        case NCDVALUE_MAP: {
            if (!ExpString_AppendChar(out_str, '[')) {
                goto fail;
            }
            
            int is_first = 1;
            
            for (NCDValue *ekey = NCDValue_MapFirstKey(value); ekey; ekey = NCDValue_MapNextKey(value, ekey)) {
                NCDValue *eval = NCDValue_MapKeyValue(value, ekey);
                
                if (!is_first) {
                    if (!ExpString_Append(out_str, ", ")) {
                        goto fail;
                    }
                }
                
                if (!generate_val(ekey, out_str)) {
                    goto fail;
                }
                
                if (!ExpString_AppendChar(out_str, ':')) {
                    goto fail;
                }
                
                if (!generate_val(eval, out_str)) {
                    goto fail;
                }
                
                is_first = 0;
            }
            
            if (!ExpString_AppendChar(out_str, ']')) {
                goto fail;
            }
        } break;
        
        case NCDVALUE_VAR: {
            if (!ExpString_Append(out_str, NCDValue_VarName(value))) {
                goto fail;
            }
        } break;
        
        case NCDVALUE_INVOC: {
            if (!generate_val(NCDValue_InvocFunc(value), out_str)) {
                goto fail;
            }
            
            if (!ExpString_AppendChar(out_str, '(')) {
                goto fail;
            }
            
            if (!generate_val(NCDValue_InvocArg(value), out_str)) {
                goto fail;
            }
            
            if (!ExpString_AppendChar(out_str, ')')) {
                goto fail;
            }
        } break;
        
        default: ASSERT(0);
    }
    
    return 1;
    
fail:
    return 0;
}
Ejemplo n.º 2
0
void NCDConfigTokenizer_Tokenize (char *str, size_t left, NCDConfigTokenizer_output output, void *user)
{
    size_t line = 1;
    size_t line_char = 1;
    
    while (left > 0) {
        size_t l;
        int error = 0;
        int token;
        void *token_val = NULL;
        
        if (*str == '#') {
            l = 1;
            while (l < left && str[l] != '\n') {
                l++;
            }
            token = 0;
        }
        else if (l = data_begins_with(str, left, "{")) {
            token = NCD_TOKEN_CURLY_OPEN;
        }
        else if (l = data_begins_with(str, left, "}")) {
            token = NCD_TOKEN_CURLY_CLOSE;
        }
        else if (l = data_begins_with(str, left, "(")) {
            token = NCD_TOKEN_ROUND_OPEN;
        }
        else if (l = data_begins_with(str, left, ")")) {
            token = NCD_TOKEN_ROUND_CLOSE;
        }
        else if (l = data_begins_with(str, left, ";")) {
            token = NCD_TOKEN_SEMICOLON;
        }
        else if (l = data_begins_with(str, left, ".")) {
            token = NCD_TOKEN_DOT;
        }
        else if (l = data_begins_with(str, left, ",")) {
            token = NCD_TOKEN_COMMA;
        }
        else if (l = data_begins_with(str, left, ":")) {
            token = NCD_TOKEN_COLON;
        }
        else if (l = data_begins_with(str, left, "[")) {
            token = NCD_TOKEN_BRACKET_OPEN;
        }
        else if (l = data_begins_with(str, left, "]")) {
            token = NCD_TOKEN_BRACKET_CLOSE;
        }
        else if (l = data_begins_with(str, left, "->")) {
            token = NCD_TOKEN_ARROW;
        }
        else if (is_name_first_char(*str)) {
            l = 1;
            while (l < left && is_name_char(str[l])) {
                l++;
            }
            
            // allocate buffer
            bsize_t bufsize = bsize_add(bsize_fromsize(l), bsize_fromint(1));
            char *buf;
            if (bufsize.is_overflow || !(buf = malloc(bufsize.value))) {
                BLog(BLOG_ERROR, "malloc failed");
                error = 1;
                goto out;
            }
            
            // copy and terminate
            memcpy(buf, str, l);
            buf[l] = '\0';
            
            if (!strcmp(buf, "process")) {
                token = NCD_TOKEN_PROCESS;
                free(buf);
            }
            else if (!strcmp(buf, "template")) {
                token = NCD_TOKEN_TEMPLATE;
                free(buf);
            }
            else {
                token = NCD_TOKEN_NAME;
                token_val = buf;
            }
        }
        else if (*str == '"') do {
            // init string
            ExpString estr;
            if (!ExpString_Init(&estr)) {
                BLog(BLOG_ERROR, "ExpString_Init failed");
                goto string_fail0;
            }
            
            // skip start quote
            l = 1;
            
            // decode string
            while (l < left) {
                char dec_ch;
                
                // get character
                if (str[l] == '\\') {
                    if (left - l < 2) {
                        BLog(BLOG_ERROR, "escape character found in string but nothing follows");
                        goto string_fail1;
                    }
                    
                    dec_ch = str[l + 1];
                    l += 2;
                }
                else if (str[l] == '"') {
                    break;
                }
                else {
                    dec_ch = str[l];
                    l++;
                }
                
                // string cannot contain zeros bytes
                if (dec_ch == '\0') {
                    BLog(BLOG_ERROR, "string contains zero byte");
                    goto string_fail1;
                }
                
                // append character to string
                if (!ExpString_AppendChar(&estr, dec_ch)) {
                    BLog(BLOG_ERROR, "ExpString_AppendChar failed");
                    goto string_fail1;
                }
            }
            
            // make sure ending quote was found
            if (l == left) {
                BLog(BLOG_ERROR, "missing ending quote for string");
                goto string_fail1;
            }
            
            // skip ending quote
            l++;
            
            token = NCD_TOKEN_STRING;
            token_val = ExpString_Get(&estr);
            break;
            
        string_fail1:
            ExpString_Free(&estr);
        string_fail0:
            error = 1;
        } while (0);
        else if (is_space_char(*str)) {
            token = 0;
            l = 1;
        }
        else {
            BLog(BLOG_ERROR, "unrecognized character");
            error = 1;
        }
        
    out:
        // report error
        if (error) {
            output(user, NCD_ERROR, NULL, line, line_char);
            return;
        }
        
        // output token
        if (token) {
            if (!output(user, token, token_val, line, line_char)) {
                return;
            }
        }
        
        // update line/char counters
        for (size_t i = 0; i < l; i++) {
            if (str[i] == '\n') {
                line++;
                line_char = 1;
            } else {
                line_char++;
            }
        }
        
        str += l;
        left -= l;
    }
    
    output(user, NCD_EOF, NULL, line, line_char);
}