/* call-seq: as_sym() * * *return* value as an Symbol. */ static VALUE sax_value_as_sym(VALUE self) { SaxDrive dr = DATA_PTR(self); if ('\0' == *dr->buf.str) { return Qnil; } return str2sym(dr, dr->buf.str, 0); }
int main() { char *a, *b, *c, *d, *a2; printf("SYMBOLS\n"); symtab_dump(); a = str2sym("foo"); symtab_dump(); b = str2sym("bar"); symtab_dump(); a2 = strdup("foo"); c = str2sym(a2); symtab_dump(); d = str2sym("fubar"); symtab_dump(); printf("a = %s (%p)\n", a, a); printf("a2 = %s (%p)\n", a2, a2); printf("b = %s (%p)\n", b, b); printf("c = %s (%p)\n", c, c); printf("d = %s (%p)\n", d, d); printf("DONE\n"); return 0; }
static char read_element_end(SaxDrive dr) { VALUE name = Qnil; char c; int line = dr->buf.line; int col = dr->buf.col - 2; Nv nv; if ('\0' == (c = read_name_token(dr))) { return '\0'; } // c should be > and current is one past so read another char c = buf_get(&dr->buf); nv = stack_peek(&dr->stack); if (0 != nv && 0 == strcmp(dr->buf.str, nv->name)) { name = nv->val; stack_pop(&dr->stack); } else { // Mismatched start and end char msg[256]; Nv match = stack_rev_find(&dr->stack, dr->buf.str); if (0 == match) { // Not found so open and close element. char *ename = 0; Hint h = ox_hint_find(dr->hints, dr->buf.str); if (0 != h && h->empty) { // Just close normally name = str2sym(dr, dr->buf.str, &ename); snprintf(msg, sizeof(msg) - 1, "%selement '%s' should not have a separate close element", EL_MISMATCH, dr->buf.str); ox_sax_drive_error_at(dr, msg, line, col); return c; } else { snprintf(msg, sizeof(msg) - 1, "%selement '%s' closed but not opened", EL_MISMATCH, dr->buf.str); ox_sax_drive_error_at(dr, msg, line, col); name = str2sym(dr, dr->buf.str, &ename); if (dr->has.start_element) { VALUE args[1]; if (dr->has.line) { rb_ivar_set(dr->handler, ox_at_line_id, LONG2NUM(line)); } if (dr->has.column) { rb_ivar_set(dr->handler, ox_at_column_id, LONG2NUM(col)); } args[0] = name; rb_funcall2(dr->handler, ox_start_element_id, 1, args); } } } else { // Found a match so close all up to the found element in stack. Nv n2; if (0 != (n2 = hint_try_close(dr, dr->buf.str))) { name = n2->val; } else { snprintf(msg, sizeof(msg) - 1, "%selement '%s' close does not match '%s' open", EL_MISMATCH, dr->buf.str, nv->name); ox_sax_drive_error_at(dr, msg, line, col); if (dr->has.line) { rb_ivar_set(dr->handler, ox_at_line_id, LONG2NUM(line)); } if (dr->has.column) { rb_ivar_set(dr->handler, ox_at_column_id, LONG2NUM(col)); } for (nv = stack_pop(&dr->stack); match < nv; nv = stack_pop(&dr->stack)) { if (dr->has.end_element) { rb_funcall(dr->handler, ox_end_element_id, 1, nv->val); } } name = nv->val; } } } end_element_cb(dr, name, line, col); return c; }
static char read_attrs(SaxDrive dr, char c, char termc, char term2, int is_xml, int eq_req) { VALUE name = Qnil; int is_encoding = 0; int line; int col; char *attr_value; // already protected by caller dr->buf.str = dr->buf.tail; if (is_white(c)) { c = buf_next_non_white(&dr->buf); } while (termc != c && term2 != c) { buf_backup(&dr->buf); if ('\0' == c) { ox_sax_drive_error(dr, NO_TERM "attributes not terminated"); return '\0'; } line = dr->buf.line; col = dr->buf.col; if ('\0' == (c = read_name_token(dr))) { ox_sax_drive_error(dr, NO_TERM "error reading token"); return '\0'; } if (is_xml && 0 == strcasecmp("encoding", dr->buf.str)) { is_encoding = 1; } if (dr->has.attr || dr->has.attr_value) { name = str2sym(dr, dr->buf.str, 0); } if (is_white(c)) { c = buf_next_non_white(&dr->buf); } if ('=' != c) { if (eq_req) { dr->err = 1; return c; } else { ox_sax_drive_error(dr, WRONG_CHAR "no attribute value"); attr_value = (char*)""; } } else { line = dr->buf.line; col = dr->buf.col; c = read_quoted_value(dr); attr_value = dr->buf.str; if (is_encoding) { #if HAS_ENCODING_SUPPORT dr->encoding = rb_enc_find(dr->buf.str); #elif HAS_PRIVATE_ENCODING dr->encoding = rb_str_new2(dr->buf.str); #else dr->encoding = dr->buf.str; #endif is_encoding = 0; } } if (dr->has.attr_value) { VALUE args[2]; if (dr->has.line) { rb_ivar_set(dr->handler, ox_at_line_id, LONG2NUM(line)); } if (dr->has.column) { rb_ivar_set(dr->handler, ox_at_column_id, LONG2NUM(col)); } args[0] = name; args[1] = dr->value_obj; rb_funcall2(dr->handler, ox_attr_value_id, 2, args); } else if (dr->has.attr) { VALUE args[2]; args[0] = name; ox_sax_collapse_special(dr, dr->buf.str, line, col); args[1] = rb_str_new2(attr_value); #if HAS_ENCODING_SUPPORT if (0 != dr->encoding) { rb_enc_associate(args[1], dr->encoding); } #elif HAS_PRIVATE_ENCODING if (Qnil != dr->encoding) { rb_funcall(args[1], ox_force_encoding_id, 1, dr->encoding); } #endif if (dr->has.line) { rb_ivar_set(dr->handler, ox_at_line_id, LONG2NUM(line)); } if (dr->has.column) { rb_ivar_set(dr->handler, ox_at_column_id, LONG2NUM(col)); } rb_funcall2(dr->handler, ox_attr_id, 2, args); } if (is_white(c)) { c = buf_next_non_white(&dr->buf); } } dr->buf.str = 0; return c; }
/* Entered after the '<' and the first character after that. Returns status * code. */ static char read_element_start(SaxDrive dr) { char *ename = 0; VALUE name = Qnil; char c; int closed; int line = dr->buf.line; int col = dr->buf.col - 1; Hint h = 0; int stackless = 0; if ('\0' == (c = read_name_token(dr))) { return '\0'; } if (dr->options.smart && 0 == dr->hints && stack_empty(&dr->stack) && 0 == strcasecmp("html", dr->buf.str)) { dr->hints = ox_hints_html(); } if (0 != dr->hints) { hint_clear_empty(dr); h = ox_hint_find(dr->hints, dr->buf.str); if (0 == h) { char msg[100]; sprintf(msg, "%s%s is not a valid element type for a %s document type.", INV_ELEMENT, dr->buf.str, dr->hints->name); ox_sax_drive_error(dr, msg); } else { Nv top_nv = stack_peek(&dr->stack); if (h->empty) { stackless = 1; } if (0 != top_nv) { char msg[256]; if (!h->nest && 0 == strcasecmp(top_nv->name, h->name)) { snprintf(msg, sizeof(msg) - 1, "%s%s can not be nested in a %s document, closing previous.", INV_ELEMENT, dr->buf.str, dr->hints->name); ox_sax_drive_error(dr, msg); stack_pop(&dr->stack); end_element_cb(dr, top_nv->val, line, col); top_nv = stack_peek(&dr->stack); } if (0 != h->parents) { const char **p; int ok = 0; for (p = h->parents; 0 != *p; p++) { if (0 == strcasecmp(*p, top_nv->name)) { ok = 1; break; } } if (!ok) { snprintf(msg, sizeof(msg) - 1, "%s%s can not be a child of a %s in a %s document.", INV_ELEMENT, h->name, top_nv->name, dr->hints->name); ox_sax_drive_error(dr, msg); } } } } } name = str2sym(dr, dr->buf.str, &ename); if (dr->has.start_element) { VALUE args[1]; if (dr->has.line) { rb_ivar_set(dr->handler, ox_at_line_id, LONG2NUM(line)); } if (dr->has.column) { rb_ivar_set(dr->handler, ox_at_column_id, LONG2NUM(col)); } args[0] = name; rb_funcall2(dr->handler, ox_start_element_id, 1, args); } if ('/' == c) { closed = 1; } else if ('>' == c) { closed = 0; } else { buf_protect(&dr->buf); c = read_attrs(dr, c, '/', '>', 0, 0); if (is_white(c)) { c = buf_next_non_white(&dr->buf); } closed = ('/' == c); } if (dr->has.attrs_done) { rb_funcall(dr->handler, ox_attrs_done_id, 0); } if (closed) { c = buf_next_non_white(&dr->buf); line = dr->buf.line; col = dr->buf.col - 1; end_element_cb(dr, name, line, col); } else if (stackless) { end_element_cb(dr, name, line, col); } else { stack_push(&dr->stack, ename, name, h); } if ('>' != c) { ox_sax_drive_error(dr, WRONG_CHAR "element not closed"); return c; } dr->buf.str = 0; return buf_get(&dr->buf); }