static atom_p parse_list(parsebuf_p pb, expression_callback_t out, int indentation) { int c, i, terminator; atom_p first, prev, curr; struct __operator * operator; parsebuf_t buf; DEBUG(); // Grab the opening parenthesis, or whatever it is __consume_whitespace(pb); __parsebuf_snapshot(pb, &buf); if((c = __parsebuf_next(pb)) == '(') { terminator = ')'; } else if(c == '[') { terminator = ']'; } else if(c == '<') { terminator = '>'; } else if(c == '{') { terminator = '}'; } else { splinter_error_return(NULL, "%s invalid list opening @ %d:%d", buf.n, buf.l, buf.c); } __consume_whitespace(pb); if ((operator = __find_closest_token(pb, terminator)) == NULL) return NULL; __parse_out_indentation(out, indentation); __parse_out_char(out, c); __parse_out_string(out, operator->token, (int)strlen(operator->token)); for(first = prev = curr = NULL; 1;) { __consume_whitespace(pb); i = pb->i; __parse_out_char(out, '\n'); if((c = __parsebuf_next(pb)) <= 0) { splinter_error_set("%s missing list closing @ %d:%d", buf.n, pb->l, pb->c); return atom_free(first); } else if(c == terminator) { if ((curr = atom_alloc_list(operator->exec_call, first)) == NULL) { return atom_free(first); } __parse_out_indentation(out, indentation); __parse_out_char(out, terminator); return curr; } else if(c == '0' && (__parsebuf_peek(pb) == 'x' || __parsebuf_peek(pb) == 'X')) { __parsebuf_prev(pb); curr = parse_hex(pb, operator->mode); if (curr != NULL) __parse_out_line(out, pb->s + i, pb->i - i, indentation + 2); } else if('0' <= c && c <= '9') { __parsebuf_prev(pb); curr = (c == '0') ? parse_oct(pb, operator->mode) : parse_uint(pb, operator->mode); if (curr != NULL) __parse_out_line(out, pb->s + i, pb->i - i, indentation + 2); } else if(c == '-' && ('0' <= __parsebuf_peek(pb) && __parsebuf_peek(pb) <= '9')) { __parsebuf_prev(pb); curr = parse_int(pb, operator->mode); if (curr != NULL) __parse_out_line(out, pb->s + i, pb->i - i, indentation + 2); } else if(c == '(' || c == '[' || c == '<' || c == '{') { __parsebuf_prev(pb); curr = parse_list(pb, out, indentation + 2); } else if(c == '\'') { curr = parse_string(pb, '\'', operator->mode); if (curr != NULL) __parse_out_line(out, pb->s + i, pb->i - i, indentation + 2); } else if(c == '"') { curr = parse_string(pb, '"', operator->mode); if (curr != NULL) __parse_out_line(out, pb->s + i, pb->i - i, indentation + 2); } else if (c == '$') { __parsebuf_prev(pb); curr = parse_variable(pb, terminator, operator->mode); if (curr != NULL) __parse_out_line(out, (char *)curr->data, strlen((char *)curr->data), indentation + 2); } else if (c == '@') { __parsebuf_prev(pb); curr = parse_symbol(pb, terminator, operator->mode); if (curr != NULL) __parse_out_line(out, pb->s + i, pb->i - i, indentation + 2); } else { curr = NULL; } if(curr == NULL) { return atom_free(first); } if(first == NULL) { first = prev = curr; } else { prev->next = curr; prev = curr; } } }
STATIC char * parse_value(char *source, int len) { char *value, *v, *end; int error = 0; value = (char *)malloc(len + 1); end = v = value; /* * printf( "parse_value <%.*s>\n", len, source); */ for ( ; len; len--, source++) { if (*source != '\\') { *v++ = *source; if (*source != ' ') { end = v; } continue; } source++; len--; if (len == 0) { break; } if (*source == '\\') { *v++ = *source; } else if (*source == 'n') { *v++ = '\n'; } else if (*source == 'r') { *v++ = '\r'; } else if (*source == ' ') { *v++ = ' '; } else if (*source == 'x') { source++; len--; if (len < 2) { break; } *v++ = parse_hex(source, 2, &error); if (error) { break; } source++; len--; } else if (isdigit((unsigned char)*source)) { if (len < 3) { break; } *v++ = parse_oct(source, 3, &error); if (error) { break; } source++; len--; source++; len--; } else { error = 1; REPORT_ERROR((stderr, "Invalid character escape \"%.*s\"", 2, source - 1)); break; } end = v; } if (error) { free(value); return (NULL); } value_len = end - value; memcpy(token_buf, value, value_len); token_buf[value_len] = '\0'; free(value); return (&token_buf[0]); }