ox 2.4.0 → 2.4.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ox might be problematic. Click here for more details.

@@ -50,11 +50,11 @@ static char read_element_start(SaxDrive dr);
50
50
  static char read_element_end(SaxDrive dr);
51
51
  static char read_text(SaxDrive dr);
52
52
  static char read_jump(SaxDrive dr, const char *pat);
53
- static char read_attrs(SaxDrive dr, char c, char termc, char term2, int is_xml, int eq_req);
53
+ static char read_attrs(SaxDrive dr, char c, char termc, char term2, int is_xml, int eq_req, Hint h);
54
54
  static char read_name_token(SaxDrive dr);
55
55
  static char read_quoted_value(SaxDrive dr);
56
56
 
57
- static void end_element_cb(SaxDrive dr, VALUE name, int pos, int line, int col);
57
+ static void end_element_cb(SaxDrive dr, VALUE name, int pos, int line, int col, Hint h);
58
58
 
59
59
  static void hint_clear_empty(SaxDrive dr);
60
60
  static Nv hint_try_close(SaxDrive dr, const char *name);
@@ -181,8 +181,9 @@ sax_drive_init(SaxDrive dr, VALUE handler, VALUE io, SaxOptions options) {
181
181
  #endif
182
182
  rb_gc_register_address(&dr->value_obj);
183
183
  dr->options = *options;
184
- dr->hints = 0;
185
184
  dr->err = 0;
185
+ dr->blocked = 0;
186
+ dr->abort = false;
186
187
  has_init(&dr->has, handler);
187
188
  #if HAS_ENCODING_SUPPORT
188
189
  if ('\0' == *ox_default_options.encoding) {
@@ -355,7 +356,7 @@ parse(SaxDrive dr) {
355
356
  break;
356
357
  case '/': /* element end */
357
358
  parent = stack_peek(&dr->stack);
358
- if (0 != parent && 0 == parent->childCnt && dr->has.text) {
359
+ if (0 != parent && 0 == parent->childCnt && dr->has.text && !dr->blocked) {
359
360
  VALUE args[1];
360
361
  int pos = dr->buf.pos;
361
362
  int line = dr->buf.line;
@@ -407,6 +408,9 @@ parse(SaxDrive dr) {
407
408
  }
408
409
  }
409
410
  DONE:
411
+ if (dr->abort) {
412
+ return;
413
+ }
410
414
  if (dr->stack.head < dr->stack.tail) {
411
415
  char msg[256];
412
416
  Nv sp;
@@ -423,12 +427,15 @@ parse(SaxDrive dr) {
423
427
  for (sp = dr->stack.tail - 1; dr->stack.head <= sp; sp--) {
424
428
  snprintf(msg, sizeof(msg) - 1, "%selement '%s' not closed", EL_MISMATCH, sp->name);
425
429
  ox_sax_drive_error_at(dr, msg, dr->buf.pos, dr->buf.line, dr->buf.col);
426
- if (dr->has.end_element) {
430
+ if (dr->has.end_element && 0 >= dr->blocked && (NULL == sp->hint || ActiveOverlay == sp->hint->overlay)) {
427
431
  VALUE args[1];
428
432
 
429
433
  args[0] = sp->val;
430
434
  rb_funcall2(dr->handler, ox_end_element_id, 1, args);
431
435
  }
436
+ if (dr->blocked && NULL != sp->hint && BlockOverlay == sp->hint->overlay) {
437
+ dr->blocked--;
438
+ }
432
439
  }
433
440
  }
434
441
  }
@@ -504,7 +511,7 @@ read_instruction(SaxDrive dr) {
504
511
  cend = dr->buf.tail;
505
512
  buf_reset(&dr->buf);
506
513
  dr->err = 0;
507
- c = read_attrs(dr, c, '?', '?', is_xml, 1);
514
+ c = read_attrs(dr, c, '?', '?', is_xml, 1, NULL);
508
515
  if (dr->has.attrs_done) {
509
516
  rb_funcall(dr->handler, ox_attrs_done_id, 0);
510
517
  }
@@ -626,10 +633,10 @@ read_doctype(SaxDrive dr) {
626
633
  buf_backup(&dr->buf); /* back up to the start in case the doctype is empty */
627
634
  buf_protect(&dr->buf);
628
635
  read_delimited(dr, '>');
629
- if (dr->options.smart && 0 == dr->hints) {
636
+ if (dr->options.smart && 0 == dr->options.hints) {
630
637
  for (s = dr->buf.str; is_white(*s); s++) { }
631
638
  if (0 == strncasecmp("HTML", s, 4)) {
632
- dr->hints = ox_hints_html();
639
+ dr->options.hints = ox_hints_html();
633
640
  }
634
641
  }
635
642
  *(dr->buf.tail - 1) = '\0';
@@ -669,6 +676,7 @@ read_cdata(SaxDrive dr) {
669
676
  struct _CheckPt cp = CHECK_PT_INIT;
670
677
  Nv parent = stack_peek(&dr->stack);
671
678
 
679
+ // TBD check parent overlay
672
680
  if (0 != parent) {
673
681
  parent->childCnt++;
674
682
  }
@@ -716,29 +724,31 @@ read_cdata(SaxDrive dr) {
716
724
  }
717
725
  }
718
726
  CB:
719
- if (dr->has.cdata) {
720
- VALUE args[1];
727
+ if (!dr->blocked && (NULL == parent || NULL == parent->hint || OffOverlay != parent->hint->overlay)) {
728
+ if (dr->has.cdata) {
729
+ VALUE args[1];
721
730
 
722
- args[0] = rb_str_new2(dr->buf.str);
731
+ args[0] = rb_str_new2(dr->buf.str);
723
732
  #if HAS_ENCODING_SUPPORT
724
- if (0 != dr->encoding) {
725
- rb_enc_associate(args[0], dr->encoding);
726
- }
733
+ if (0 != dr->encoding) {
734
+ rb_enc_associate(args[0], dr->encoding);
735
+ }
727
736
  #elif HAS_PRIVATE_ENCODING
728
- if (Qnil != dr->encoding) {
729
- rb_funcall(args[0], ox_force_encoding_id, 1, dr->encoding);
730
- }
737
+ if (Qnil != dr->encoding) {
738
+ rb_funcall(args[0], ox_force_encoding_id, 1, dr->encoding);
739
+ }
731
740
  #endif
732
- if (dr->has.pos) {
733
- rb_ivar_set(dr->handler, ox_at_pos_id, LONG2NUM(pos));
734
- }
735
- if (dr->has.line) {
736
- rb_ivar_set(dr->handler, ox_at_line_id, LONG2NUM(line));
737
- }
738
- if (dr->has.column) {
739
- rb_ivar_set(dr->handler, ox_at_column_id, LONG2NUM(col));
741
+ if (dr->has.pos) {
742
+ rb_ivar_set(dr->handler, ox_at_pos_id, LONG2NUM(pos));
743
+ }
744
+ if (dr->has.line) {
745
+ rb_ivar_set(dr->handler, ox_at_line_id, LONG2NUM(line));
746
+ }
747
+ if (dr->has.column) {
748
+ rb_ivar_set(dr->handler, ox_at_column_id, LONG2NUM(col));
749
+ }
750
+ rb_funcall2(dr->handler, ox_cdata_id, 1, args);
740
751
  }
741
- rb_funcall2(dr->handler, ox_cdata_id, 1, args);
742
752
  }
743
753
  if ('\0' != zero) {
744
754
  *(dr->buf.tail - 1) = zero;
@@ -804,29 +814,33 @@ read_comment(SaxDrive dr) {
804
814
  }
805
815
  }
806
816
  CB:
807
- if (dr->has.comment) {
808
- VALUE args[1];
817
+ // TBD check parent overlay
818
+ if (dr->has.comment && !dr->blocked) {
819
+ VALUE args[1];
820
+ Nv parent = stack_peek(&dr->stack);
809
821
 
810
- args[0] = rb_str_new2(dr->buf.str);
822
+ if (NULL == parent || NULL == parent->hint || OffOverlay != parent->hint->overlay) {
823
+ args[0] = rb_str_new2(dr->buf.str);
811
824
  #if HAS_ENCODING_SUPPORT
812
- if (0 != dr->encoding) {
813
- rb_enc_associate(args[0], dr->encoding);
814
- }
825
+ if (0 != dr->encoding) {
826
+ rb_enc_associate(args[0], dr->encoding);
827
+ }
815
828
  #elif HAS_PRIVATE_ENCODING
816
- if (Qnil != dr->encoding) {
817
- rb_funcall(args[0], ox_force_encoding_id, 1, dr->encoding);
818
- }
829
+ if (Qnil != dr->encoding) {
830
+ rb_funcall(args[0], ox_force_encoding_id, 1, dr->encoding);
831
+ }
819
832
  #endif
820
- if (dr->has.pos) {
821
- rb_ivar_set(dr->handler, ox_at_pos_id, LONG2NUM(pos));
822
- }
823
- if (dr->has.line) {
824
- rb_ivar_set(dr->handler, ox_at_line_id, LONG2NUM(line));
825
- }
826
- if (dr->has.column) {
827
- rb_ivar_set(dr->handler, ox_at_column_id, LONG2NUM(col));
833
+ if (dr->has.pos) {
834
+ rb_ivar_set(dr->handler, ox_at_pos_id, LONG2NUM(pos));
835
+ }
836
+ if (dr->has.line) {
837
+ rb_ivar_set(dr->handler, ox_at_line_id, LONG2NUM(line));
838
+ }
839
+ if (dr->has.column) {
840
+ rb_ivar_set(dr->handler, ox_at_column_id, LONG2NUM(col));
841
+ }
842
+ rb_funcall2(dr->handler, ox_comment_id, 1, args);
828
843
  }
829
- rb_funcall2(dr->handler, ox_comment_id, 1, args);
830
844
  }
831
845
  if ('\0' != zero) {
832
846
  *(dr->buf.tail - 1) = zero;
@@ -848,7 +862,7 @@ read_element_start(SaxDrive dr) {
848
862
  int pos = dr->buf.pos;
849
863
  int line = dr->buf.line;
850
864
  int col = dr->buf.col;
851
- Hint h = 0;
865
+ Hint h = NULL;
852
866
  int stackless = 0;
853
867
  Nv parent = stack_peek(&dr->stack);
854
868
 
@@ -866,32 +880,45 @@ read_element_start(SaxDrive dr) {
866
880
  if (0 != parent) {
867
881
  parent->childCnt++;
868
882
  }
869
- if (dr->options.smart && 0 == dr->hints && stack_empty(&dr->stack) && 0 == strcasecmp("html", dr->buf.str)) {
870
- dr->hints = ox_hints_html();
883
+ if (dr->options.smart && 0 == dr->options.hints && stack_empty(&dr->stack) && 0 == strcasecmp("html", dr->buf.str)) {
884
+ dr->options.hints = ox_hints_html();
871
885
  }
872
- if (0 != dr->hints) {
886
+ if (NULL != dr->options.hints) {
873
887
  hint_clear_empty(dr);
874
- h = ox_hint_find(dr->hints, dr->buf.str);
875
- if (0 == h) {
876
- char msg[100];
888
+ h = ox_hint_find(dr->options.hints, dr->buf.str);
889
+ if (NULL == h) {
890
+ char msg[256];
877
891
 
878
- sprintf(msg, "%s%s is not a valid element type for a %s document type.", INV_ELEMENT, dr->buf.str, dr->hints->name);
892
+ snprintf(msg, sizeof(msg), "%s%s is not a valid element type for a %s document type.", INV_ELEMENT, dr->buf.str, dr->options.hints->name);
879
893
  ox_sax_drive_error(dr, msg);
880
894
  } else {
881
895
  Nv top_nv = stack_peek(&dr->stack);
882
896
 
897
+ if (AbortOverlay == h->overlay) {
898
+ if (rb_respond_to(dr->handler, ox_abort_id)) {
899
+ VALUE args[1];
900
+
901
+ args[0] = str2sym(dr, dr->buf.str, NULL);
902
+ rb_funcall2(dr->handler, ox_abort_id, 1, args);
903
+ }
904
+ dr->abort = true;
905
+ return '\0';
906
+ }
907
+ if (BlockOverlay == h->overlay) {
908
+ dr->blocked++;
909
+ }
883
910
  if (h->empty) {
884
911
  stackless = 1;
885
912
  }
886
913
  if (0 != top_nv) {
887
914
  char msg[256];
888
-
915
+
889
916
  if (!h->nest && 0 == strcasecmp(top_nv->name, h->name)) {
890
917
  snprintf(msg, sizeof(msg) - 1, "%s%s can not be nested in a %s document, closing previous.",
891
- INV_ELEMENT, dr->buf.str, dr->hints->name);
918
+ INV_ELEMENT, dr->buf.str, dr->options.hints->name);
892
919
  ox_sax_drive_error(dr, msg);
893
920
  stack_pop(&dr->stack);
894
- end_element_cb(dr, top_nv->val, pos, line, col);
921
+ end_element_cb(dr, top_nv->val, pos, line, col, top_nv->hint);
895
922
  top_nv = stack_peek(&dr->stack);
896
923
  }
897
924
  if (0 != h->parents) {
@@ -906,7 +933,7 @@ read_element_start(SaxDrive dr) {
906
933
  }
907
934
  if (!ok) {
908
935
  snprintf(msg, sizeof(msg) - 1, "%s%s can not be a child of a %s in a %s document.",
909
- INV_ELEMENT, h->name, top_nv->name, dr->hints->name);
936
+ INV_ELEMENT, h->name, top_nv->name, dr->options.hints->name);
910
937
  ox_sax_drive_error(dr, msg);
911
938
  }
912
939
  }
@@ -914,7 +941,7 @@ read_element_start(SaxDrive dr) {
914
941
  }
915
942
  }
916
943
  name = str2sym(dr, dr->buf.str, &ename);
917
- if (dr->has.start_element) {
944
+ if (dr->has.start_element && 0 >= dr->blocked && (NULL == h || ActiveOverlay == h->overlay)) {
918
945
  VALUE args[1];
919
946
 
920
947
  if (dr->has.pos) {
@@ -935,13 +962,13 @@ read_element_start(SaxDrive dr) {
935
962
  closed = 0;
936
963
  } else {
937
964
  buf_protect(&dr->buf);
938
- c = read_attrs(dr, c, '/', '>', 0, 0);
965
+ c = read_attrs(dr, c, '/', '>', 0, 0, h);
939
966
  if (is_white(c)) {
940
967
  c = buf_next_non_white(&dr->buf);
941
968
  }
942
969
  closed = ('/' == c);
943
970
  }
944
- if (dr->has.attrs_done) {
971
+ if (dr->has.attrs_done && 0 >= dr->blocked && (NULL == h || ActiveOverlay == h->overlay)) {
945
972
  rb_funcall(dr->handler, ox_attrs_done_id, 0);
946
973
  }
947
974
  if (closed) {
@@ -949,9 +976,9 @@ read_element_start(SaxDrive dr) {
949
976
  pos = dr->buf.pos;
950
977
  line = dr->buf.line;
951
978
  col = dr->buf.col;
952
- end_element_cb(dr, name, pos, line, col);
979
+ end_element_cb(dr, name, pos, line, col, h);
953
980
  } else if (stackless) {
954
- end_element_cb(dr, name, pos, line, col);
981
+ end_element_cb(dr, name, pos, line, col, h);
955
982
  } else if (0 != h && h->jump) {
956
983
  stack_push(&dr->stack, ename, name, h);
957
984
  if ('>' != c) {
@@ -992,7 +1019,8 @@ read_element_end(SaxDrive dr) {
992
1019
  int line = dr->buf.line;
993
1020
  int col = dr->buf.col - 1;
994
1021
  Nv nv;
995
-
1022
+ Hint h = NULL;
1023
+
996
1024
  if ('\0' == (c = read_name_token(dr))) {
997
1025
  return '\0';
998
1026
  }
@@ -1004,6 +1032,7 @@ read_element_end(SaxDrive dr) {
1004
1032
  nv = stack_peek(&dr->stack);
1005
1033
  if (0 != nv && 0 == strcmp(dr->buf.str, nv->name)) {
1006
1034
  name = nv->val;
1035
+ h = nv->hint;
1007
1036
  stack_pop(&dr->stack);
1008
1037
  } else {
1009
1038
  // Mismatched start and end
@@ -1012,9 +1041,8 @@ read_element_end(SaxDrive dr) {
1012
1041
 
1013
1042
  if (0 == match) {
1014
1043
  // Not found so open and close element.
1015
- Hint h = ox_hint_find(dr->hints, dr->buf.str);
1016
-
1017
- if (0 != h && h->empty) {
1044
+ h = ox_hint_find(dr->options.hints, dr->buf.str);
1045
+ if (NULL != h && h->empty) {
1018
1046
  // Just close normally
1019
1047
  name = str2sym(dr, dr->buf.str, 0);
1020
1048
  snprintf(msg, sizeof(msg) - 1, "%selement '%s' should not have a separate close element", EL_MISMATCH, dr->buf.str);
@@ -1024,7 +1052,7 @@ read_element_end(SaxDrive dr) {
1024
1052
  snprintf(msg, sizeof(msg) - 1, "%selement '%s' closed but not opened", EL_MISMATCH, dr->buf.str);
1025
1053
  ox_sax_drive_error_at(dr, msg, pos, line, col);
1026
1054
  name = str2sym(dr, dr->buf.str, 0);
1027
- if (dr->has.start_element) {
1055
+ if (dr->has.start_element && 0 >= dr->blocked && (NULL == h || ActiveOverlay == h->overlay)) {
1028
1056
  VALUE args[1];
1029
1057
 
1030
1058
  if (dr->has.pos) {
@@ -1039,6 +1067,9 @@ read_element_end(SaxDrive dr) {
1039
1067
  args[0] = name;
1040
1068
  rb_funcall2(dr->handler, ox_start_element_id, 1, args);
1041
1069
  }
1070
+ if (NULL != h && BlockOverlay == h->overlay && 0 < dr->blocked) {
1071
+ dr->blocked--;
1072
+ }
1042
1073
  }
1043
1074
  } else {
1044
1075
  // Found a match so close all up to the found element in stack.
@@ -1046,6 +1077,7 @@ read_element_end(SaxDrive dr) {
1046
1077
 
1047
1078
  if (0 != (n2 = hint_try_close(dr, dr->buf.str))) {
1048
1079
  name = n2->val;
1080
+ h = n2->hint;
1049
1081
  } else {
1050
1082
  snprintf(msg, sizeof(msg) - 1, "%selement '%s' close does not match '%s' open", EL_MISMATCH, dr->buf.str, nv->name);
1051
1083
  ox_sax_drive_error_at(dr, msg, pos, line, col);
@@ -1059,15 +1091,19 @@ read_element_end(SaxDrive dr) {
1059
1091
  rb_ivar_set(dr->handler, ox_at_column_id, LONG2NUM(col));
1060
1092
  }
1061
1093
  for (nv = stack_pop(&dr->stack); match < nv; nv = stack_pop(&dr->stack)) {
1062
- if (dr->has.end_element) {
1094
+ if (dr->has.end_element && 0 >= dr->blocked && (NULL == nv->hint || ActiveOverlay == nv->hint->overlay)) {
1063
1095
  rb_funcall(dr->handler, ox_end_element_id, 1, nv->val);
1064
1096
  }
1097
+ if (NULL != nv->hint && BlockOverlay == nv->hint->overlay && 0 < dr->blocked) {
1098
+ dr->blocked--;
1099
+ }
1065
1100
  }
1066
1101
  name = nv->val;
1102
+ h = nv->hint;
1067
1103
  }
1068
1104
  }
1069
1105
  }
1070
- end_element_cb(dr, name, pos, line, col);
1106
+ end_element_cb(dr, name, pos, line, col, h);
1071
1107
 
1072
1108
  return c;
1073
1109
  }
@@ -1119,52 +1155,54 @@ read_text(SaxDrive dr) {
1119
1155
  if (0 != parent) {
1120
1156
  parent->childCnt++;
1121
1157
  }
1122
- if (dr->has.value) {
1123
- if (dr->has.pos) {
1124
- rb_ivar_set(dr->handler, ox_at_pos_id, LONG2NUM(pos));
1125
- }
1126
- if (dr->has.line) {
1127
- rb_ivar_set(dr->handler, ox_at_line_id, LONG2NUM(line));
1128
- }
1129
- if (dr->has.column) {
1130
- rb_ivar_set(dr->handler, ox_at_column_id, LONG2NUM(col));
1131
- }
1132
- *args = dr->value_obj;
1133
- rb_funcall2(dr->handler, ox_value_id, 1, args);
1134
- } else if (dr->has.text) {
1135
- if (dr->options.convert_special) {
1136
- ox_sax_collapse_special(dr, dr->buf.str, pos, line, col);
1137
- }
1138
- switch (dr->options.skip) {
1139
- case CrSkip:
1140
- buf_collapse_return(dr->buf.str);
1141
- break;
1142
- case SpcSkip:
1143
- buf_collapse_white(dr->buf.str);
1144
- break;
1145
- default:
1146
- break;
1147
- }
1148
- args[0] = rb_str_new2(dr->buf.str);
1158
+ if (!dr->blocked && (NULL == parent || NULL == parent->hint || OffOverlay != parent->hint->overlay)) {
1159
+ if (dr->has.value) {
1160
+ if (dr->has.pos) {
1161
+ rb_ivar_set(dr->handler, ox_at_pos_id, LONG2NUM(pos));
1162
+ }
1163
+ if (dr->has.line) {
1164
+ rb_ivar_set(dr->handler, ox_at_line_id, LONG2NUM(line));
1165
+ }
1166
+ if (dr->has.column) {
1167
+ rb_ivar_set(dr->handler, ox_at_column_id, LONG2NUM(col));
1168
+ }
1169
+ *args = dr->value_obj;
1170
+ rb_funcall2(dr->handler, ox_value_id, 1, args);
1171
+ } else if (dr->has.text) {
1172
+ if (dr->options.convert_special) {
1173
+ ox_sax_collapse_special(dr, dr->buf.str, pos, line, col);
1174
+ }
1175
+ switch (dr->options.skip) {
1176
+ case CrSkip:
1177
+ buf_collapse_return(dr->buf.str);
1178
+ break;
1179
+ case SpcSkip:
1180
+ buf_collapse_white(dr->buf.str);
1181
+ break;
1182
+ default:
1183
+ break;
1184
+ }
1185
+ args[0] = rb_str_new2(dr->buf.str);
1149
1186
  #if HAS_ENCODING_SUPPORT
1150
- if (0 != dr->encoding) {
1151
- rb_enc_associate(args[0], dr->encoding);
1152
- }
1187
+ if (0 != dr->encoding) {
1188
+ rb_enc_associate(args[0], dr->encoding);
1189
+ }
1153
1190
  #elif HAS_PRIVATE_ENCODING
1154
- if (Qnil != dr->encoding) {
1155
- rb_funcall(args[0], ox_force_encoding_id, 1, dr->encoding);
1156
- }
1191
+ if (Qnil != dr->encoding) {
1192
+ rb_funcall(args[0], ox_force_encoding_id, 1, dr->encoding);
1193
+ }
1157
1194
  #endif
1158
- if (dr->has.pos) {
1159
- rb_ivar_set(dr->handler, ox_at_pos_id, LONG2NUM(pos));
1160
- }
1161
- if (dr->has.line) {
1162
- rb_ivar_set(dr->handler, ox_at_line_id, LONG2NUM(line));
1163
- }
1164
- if (dr->has.column) {
1165
- rb_ivar_set(dr->handler, ox_at_column_id, LONG2NUM(col));
1195
+ if (dr->has.pos) {
1196
+ rb_ivar_set(dr->handler, ox_at_pos_id, LONG2NUM(pos));
1197
+ }
1198
+ if (dr->has.line) {
1199
+ rb_ivar_set(dr->handler, ox_at_line_id, LONG2NUM(line));
1200
+ }
1201
+ if (dr->has.column) {
1202
+ rb_ivar_set(dr->handler, ox_at_column_id, LONG2NUM(col));
1203
+ }
1204
+ rb_funcall2(dr->handler, ox_text_id, 1, args);
1166
1205
  }
1167
- rb_funcall2(dr->handler, ox_text_id, 1, args);
1168
1206
  }
1169
1207
  dr->buf.str = 0;
1170
1208
 
@@ -1228,7 +1266,8 @@ read_jump(SaxDrive dr, const char *pat) {
1228
1266
  if (0 != parent) {
1229
1267
  parent->childCnt++;
1230
1268
  }
1231
- if (dr->has.text) {
1269
+ // TBD check parent overlay
1270
+ if (dr->has.text && !dr->blocked) {
1232
1271
  args[0] = rb_str_new2(dr->buf.str);
1233
1272
  #if HAS_ENCODING_SUPPORT
1234
1273
  if (0 != dr->encoding) {
@@ -1258,7 +1297,7 @@ read_jump(SaxDrive dr, const char *pat) {
1258
1297
  }
1259
1298
 
1260
1299
  static char
1261
- read_attrs(SaxDrive dr, char c, char termc, char term2, int is_xml, int eq_req) {
1300
+ read_attrs(SaxDrive dr, char c, char termc, char term2, int is_xml, int eq_req, Hint h) {
1262
1301
  VALUE name = Qnil;
1263
1302
  int is_encoding = 0;
1264
1303
  int pos;
@@ -1318,49 +1357,51 @@ read_attrs(SaxDrive dr, char c, char termc, char term2, int is_xml, int eq_req)
1318
1357
  is_encoding = 0;
1319
1358
  }
1320
1359
  }
1321
- if (dr->has.attr_value) {
1322
- VALUE args[2];
1323
-
1324
- if (dr->has.pos) {
1325
- rb_ivar_set(dr->handler, ox_at_pos_id, LONG2NUM(pos));
1326
- }
1327
- if (dr->has.line) {
1328
- rb_ivar_set(dr->handler, ox_at_line_id, LONG2NUM(line));
1329
- }
1330
- if (dr->has.column) {
1331
- rb_ivar_set(dr->handler, ox_at_column_id, LONG2NUM(col));
1332
- }
1333
- args[0] = name;
1334
- args[1] = dr->value_obj;
1335
- rb_funcall2(dr->handler, ox_attr_value_id, 2, args);
1336
- } else if (dr->has.attr) {
1337
- VALUE args[2];
1360
+ if (0 >= dr->blocked && (NULL == h || ActiveOverlay == h->overlay)) {
1361
+ if (dr->has.attr_value) {
1362
+ VALUE args[2];
1338
1363
 
1339
- args[0] = name;
1340
- if (dr->options.convert_special) {
1341
- ox_sax_collapse_special(dr, dr->buf.str, pos, line, col);
1342
- }
1343
- args[1] = rb_str_new2(attr_value);
1364
+ if (dr->has.pos) {
1365
+ rb_ivar_set(dr->handler, ox_at_pos_id, LONG2NUM(pos));
1366
+ }
1367
+ if (dr->has.line) {
1368
+ rb_ivar_set(dr->handler, ox_at_line_id, LONG2NUM(line));
1369
+ }
1370
+ if (dr->has.column) {
1371
+ rb_ivar_set(dr->handler, ox_at_column_id, LONG2NUM(col));
1372
+ }
1373
+ args[0] = name;
1374
+ args[1] = dr->value_obj;
1375
+ rb_funcall2(dr->handler, ox_attr_value_id, 2, args);
1376
+ } else if (dr->has.attr) {
1377
+ VALUE args[2];
1378
+
1379
+ args[0] = name;
1380
+ if (dr->options.convert_special) {
1381
+ ox_sax_collapse_special(dr, dr->buf.str, pos, line, col);
1382
+ }
1383
+ args[1] = rb_str_new2(attr_value);
1344
1384
  #if HAS_ENCODING_SUPPORT
1345
- if (0 != dr->encoding) {
1346
- rb_enc_associate(args[1], dr->encoding);
1347
- }
1385
+ if (0 != dr->encoding) {
1386
+ rb_enc_associate(args[1], dr->encoding);
1387
+ }
1348
1388
  #elif HAS_PRIVATE_ENCODING
1349
- if (Qnil != dr->encoding) {
1350
- rb_funcall(args[1], ox_force_encoding_id, 1, dr->encoding);
1351
- }
1389
+ if (Qnil != dr->encoding) {
1390
+ rb_funcall(args[1], ox_force_encoding_id, 1, dr->encoding);
1391
+ }
1352
1392
  #endif
1353
- if (dr->has.pos) {
1354
- rb_ivar_set(dr->handler, ox_at_pos_id, LONG2NUM(pos));
1355
- }
1356
- if (dr->has.line) {
1357
- rb_ivar_set(dr->handler, ox_at_line_id, LONG2NUM(line));
1358
- }
1359
- if (dr->has.column) {
1360
- rb_ivar_set(dr->handler, ox_at_column_id, LONG2NUM(col));
1393
+ if (dr->has.pos) {
1394
+ rb_ivar_set(dr->handler, ox_at_pos_id, LONG2NUM(pos));
1395
+ }
1396
+ if (dr->has.line) {
1397
+ rb_ivar_set(dr->handler, ox_at_line_id, LONG2NUM(line));
1398
+ }
1399
+ if (dr->has.column) {
1400
+ rb_ivar_set(dr->handler, ox_at_column_id, LONG2NUM(col));
1401
+ }
1402
+ rb_funcall2(dr->handler, ox_attr_id, 2, args);
1361
1403
  }
1362
- rb_funcall2(dr->handler, ox_attr_id, 2, args);
1363
- }
1404
+ }
1364
1405
  if (is_white(c)) {
1365
1406
  c = buf_next_non_white(&dr->buf);
1366
1407
  }
@@ -1450,7 +1491,7 @@ read_quoted_value(SaxDrive dr) {
1450
1491
  while ('\0' != (c = buf_get(&dr->buf))) {
1451
1492
  switch (c) {
1452
1493
  case ' ':
1453
- case '/':
1494
+ //case '/':
1454
1495
  case '>':
1455
1496
  case '?': // for instructions
1456
1497
  case '\t':
@@ -1623,7 +1664,7 @@ hint_clear_empty(SaxDrive dr) {
1623
1664
  break;
1624
1665
  }
1625
1666
  if (nv->hint->empty) {
1626
- end_element_cb(dr, nv->val, dr->buf.pos, dr->buf.line, dr->buf.col);
1667
+ end_element_cb(dr, nv->val, dr->buf.pos, dr->buf.line, dr->buf.col, nv->hint);
1627
1668
  stack_pop(&dr->stack);
1628
1669
  } else {
1629
1670
  break;
@@ -1633,7 +1674,7 @@ hint_clear_empty(SaxDrive dr) {
1633
1674
 
1634
1675
  static Nv
1635
1676
  hint_try_close(SaxDrive dr, const char *name) {
1636
- Hint h = ox_hint_find(dr->hints, name);
1677
+ Hint h = ox_hint_find(dr->options.hints, name);
1637
1678
  Nv nv;
1638
1679
 
1639
1680
  if (0 == h) {
@@ -1648,7 +1689,7 @@ hint_try_close(SaxDrive dr, const char *name) {
1648
1689
  break;
1649
1690
  }
1650
1691
  if (nv->hint->empty) {
1651
- end_element_cb(dr, nv->val, dr->buf.pos, dr->buf.line, dr->buf.col);
1692
+ end_element_cb(dr, nv->val, dr->buf.pos, dr->buf.line, dr->buf.col, nv->hint);
1652
1693
  dr->stack.tail = nv;
1653
1694
  } else {
1654
1695
  break;
@@ -1658,8 +1699,8 @@ hint_try_close(SaxDrive dr, const char *name) {
1658
1699
  }
1659
1700
 
1660
1701
  static void
1661
- end_element_cb(SaxDrive dr, VALUE name, int pos, int line, int col) {
1662
- if (dr->has.end_element) {
1702
+ end_element_cb(SaxDrive dr, VALUE name, int pos, int line, int col, Hint h) {
1703
+ if (dr->has.end_element && 0 >= dr->blocked && (NULL == h || ActiveOverlay == h->overlay)) {
1663
1704
  if (dr->has.pos) {
1664
1705
  rb_ivar_set(dr->handler, ox_at_pos_id, LONG2NUM(pos));
1665
1706
  }
@@ -1671,4 +1712,7 @@ end_element_cb(SaxDrive dr, VALUE name, int pos, int line, int col) {
1671
1712
  }
1672
1713
  rb_funcall(dr->handler, ox_end_element_id, 1, name);
1673
1714
  }
1715
+ if (NULL != h && BlockOverlay == h->overlay && 0 < dr->blocked) {
1716
+ dr->blocked--;
1717
+ }
1674
1718
  }