ox 2.14.4 → 2.14.8

Sign up to get free protection for your applications and to get access to all the features.
data/ext/ox/ox.h CHANGED
@@ -16,9 +16,7 @@ extern "C" {
16
16
  #define RSTRING_NOT_MODIFIED
17
17
 
18
18
  #include "ruby.h"
19
- #if HAVE_RB_ENC_ASSOCIATE
20
19
  #include "ruby/encoding.h"
21
- #endif
22
20
 
23
21
  #if HAVE_RUBY_ST_H
24
22
  #include "ruby/st.h"
@@ -27,249 +25,227 @@ extern "C" {
27
25
  #include "st.h"
28
26
  #endif
29
27
 
30
- #include "cache.h"
31
-
32
- #include "err.h"
33
- #include "type.h"
34
28
  #include "attr.h"
29
+ #include "err.h"
35
30
  #include "helper.h"
31
+ #include "slotcache.h"
32
+ #include "type.h"
36
33
 
37
34
  #define raise_error(msg, xml, current) _ox_raise_error(msg, xml, current, __FILE__, __LINE__)
38
35
 
39
- #define MAX_TEXT_LEN 4096
36
+ #define MAX_TEXT_LEN 4096
40
37
 
41
- #define SILENT 0
42
- #define TRACE 1
43
- #define DEBUG 2
38
+ #define SILENT 0
39
+ #define TRACE 1
40
+ #define DEBUG 2
44
41
 
45
- #define XSD_DATE 0x0001
46
- #define WITH_XML 0x0002
47
- #define WITH_INST 0x0004
48
- #define WITH_DTD 0x0008
49
- #define CIRCULAR 0x0010
42
+ #define XSD_DATE 0x0001
43
+ #define WITH_XML 0x0002
44
+ #define WITH_INST 0x0004
45
+ #define WITH_DTD 0x0008
46
+ #define CIRCULAR 0x0010
50
47
 
51
- #define XSD_DATE_SET 0x0100
52
- #define WITH_XML_SET 0x0200
53
- #define WITH_INST_SET 0x0400
54
- #define WITH_DTD_SET 0x0800
55
- #define CIRCULAR_SET 0x1000
48
+ #define XSD_DATE_SET 0x0100
49
+ #define WITH_XML_SET 0x0200
50
+ #define WITH_INST_SET 0x0400
51
+ #define WITH_DTD_SET 0x0800
52
+ #define CIRCULAR_SET 0x1000
56
53
 
57
54
  typedef enum {
58
- UseObj = 1,
59
- UseAttr = 2,
60
- UseAttrSet = 3,
61
- UseArray = 4,
62
- UseAMember = 5,
63
- UseHash = 6,
64
- UseHashKey = 7,
65
- UseHashVal = 8,
66
- UseRange = 9,
67
- UseRangeAttr= 10,
68
- UseRaw = 11,
55
+ UseObj = 1,
56
+ UseAttr = 2,
57
+ UseAttrSet = 3,
58
+ UseArray = 4,
59
+ UseAMember = 5,
60
+ UseHash = 6,
61
+ UseHashKey = 7,
62
+ UseHashVal = 8,
63
+ UseRange = 9,
64
+ UseRangeAttr = 10,
65
+ UseRaw = 11,
69
66
  } Use;
70
67
 
71
68
  typedef enum {
72
- StrictEffort = 's',
73
- TolerantEffort = 't',
74
- AutoEffort = 'a',
75
- NoEffort = 0,
69
+ StrictEffort = 's',
70
+ TolerantEffort = 't',
71
+ AutoEffort = 'a',
72
+ NoEffort = 0,
76
73
  } Effort;
77
74
 
78
- typedef enum {
79
- Yes = 'y',
80
- No = 'n',
81
- NotSet = 0
82
- } YesNo;
75
+ typedef enum { Yes = 'y', No = 'n', NotSet = 0 } YesNo;
83
76
 
84
- typedef enum {
85
- ObjMode = 'o',
86
- GenMode = 'g',
87
- LimMode = 'l',
88
- HashMode = 'h',
89
- HashNoAttrMode = 'n',
90
- NoMode = 0
91
- } LoadMode;
77
+ typedef enum { ObjMode = 'o', GenMode = 'g', LimMode = 'l', HashMode = 'h', HashNoAttrMode = 'n', NoMode = 0 } LoadMode;
92
78
 
93
79
  typedef enum {
94
- OffSkip = 'o',
95
- NoSkip = 'n',
96
- CrSkip = 'r',
97
- SpcSkip = 's',
80
+ OffSkip = 'o',
81
+ NoSkip = 'n',
82
+ CrSkip = 'r',
83
+ SpcSkip = 's',
98
84
  } SkipMode;
99
85
 
100
- typedef struct _pInfo *PInfo;
86
+ typedef struct _pInfo *PInfo;
101
87
 
102
88
  typedef struct _parseCallbacks {
103
- void (*instruct)(PInfo pi, const char *target, Attr attrs, const char *content);
104
- void (*add_doctype)(PInfo pi, const char *docType);
105
- void (*add_comment)(PInfo pi, const char *comment);
106
- void (*add_cdata)(PInfo pi, const char *cdata, size_t len);
107
- void (*add_text)(PInfo pi, char *text, int closed);
108
- void (*add_element)(PInfo pi, const char *ename, Attr attrs, int hasChildren);
109
- void (*end_element)(PInfo pi, const char *ename);
110
- void (*finish)(PInfo pi);
111
- } *ParseCallbacks;
89
+ void (*instruct)(PInfo pi, const char *target, Attr attrs, const char *content);
90
+ void (*add_doctype)(PInfo pi, const char *docType);
91
+ void (*add_comment)(PInfo pi, const char *comment);
92
+ void (*add_cdata)(PInfo pi, const char *cdata, size_t len);
93
+ void (*add_text)(PInfo pi, char *text, int closed);
94
+ void (*add_element)(PInfo pi, const char *ename, Attr attrs, int hasChildren);
95
+ void (*end_element)(PInfo pi, const char *ename);
96
+ void (*finish)(PInfo pi);
97
+ } * ParseCallbacks;
112
98
 
113
99
  typedef struct _circArray {
114
- VALUE obj_array[1024];
115
- VALUE *objs;
116
- unsigned long size; /* allocated size or initial array size */
117
- unsigned long cnt;
118
- } *CircArray;
100
+ VALUE obj_array[1024];
101
+ VALUE *objs;
102
+ unsigned long size; /* allocated size or initial array size */
103
+ unsigned long cnt;
104
+ } * CircArray;
119
105
 
120
106
  typedef struct _options {
121
- char encoding[64]; // encoding, stored in the option to avoid GC invalidation in default values
122
- char margin[128]; // left margin for dumping
123
- int indent; // indention for dump, default 2
124
- int trace; // trace level
125
- char margin_len; // margin length
126
- char with_dtd; // YesNo
127
- char with_xml; // YesNo
128
- char with_instruct; // YesNo
129
- char circular; // YesNo
130
- char xsd_date; // YesNo
131
- char mode; // LoadMode
132
- char effort; // Effort
133
- char sym_keys; // symbolize keys
134
- char skip; // skip mode
135
- char smart; // YesNo sax smart mode
136
- char convert_special;// boolean true or false
137
- char allow_invalid; // YesNo
138
- char no_empty; // boolean - no empty elements when dumping
139
- char with_cdata; // boolean - hash_load should include cdata
140
- char inv_repl[12]; // max 10 valid characters, first character is the length
141
- char strip_ns[64]; // namespace to strip, \0 is no-strip, \* is all, else only matches
142
- struct _hints *html_hints; // html hints
143
- VALUE attr_key_mod;
144
- VALUE element_key_mod;
145
- #if HAVE_RB_ENC_ASSOCIATE
146
- rb_encoding *rb_enc;
147
- #else
148
- void *rb_enc;
149
- #endif
150
- } *Options;
107
+ char encoding[64]; // encoding, stored in the option to avoid GC invalidation in default values
108
+ char margin[128]; // left margin for dumping
109
+ int indent; // indention for dump, default 2
110
+ int trace; // trace level
111
+ char margin_len; // margin length
112
+ char with_dtd; // YesNo
113
+ char with_xml; // YesNo
114
+ char with_instruct; // YesNo
115
+ char circular; // YesNo
116
+ char xsd_date; // YesNo
117
+ char mode; // LoadMode
118
+ char effort; // Effort
119
+ char sym_keys; // symbolize keys
120
+ char skip; // skip mode
121
+ char smart; // YesNo sax smart mode
122
+ char convert_special; // boolean true or false
123
+ char allow_invalid; // YesNo
124
+ char no_empty; // boolean - no empty elements when dumping
125
+ char with_cdata; // boolean - hash_load should include cdata
126
+ char inv_repl[12]; // max 10 valid characters, first character is the length
127
+ char strip_ns[64]; // namespace to strip, \0 is no-strip, \* is all, else only matches
128
+ struct _hints *html_hints; // html hints
129
+ VALUE attr_key_mod;
130
+ VALUE element_key_mod;
131
+ rb_encoding *rb_enc;
132
+ } * Options;
151
133
 
152
134
  // parse information structure
153
135
  struct _pInfo {
154
- struct _helperStack helpers;
155
- struct _err err;
156
- char *str; // buffer being read from
157
- char *end; // end of original string
158
- char *s; // current position in buffer
159
- VALUE obj;
160
- ParseCallbacks pcb;
161
- CircArray circ_array;
162
- unsigned long id; // set for text types when cirs_array is set
163
- Options options;
164
- VALUE *marked;
165
- int mark_size; // allocated size
166
- int mark_cnt;
167
- char last; // last character read, rarely set
136
+ struct _helperStack helpers;
137
+ struct _err err;
138
+ char *str; // buffer being read from
139
+ char *end; // end of original string
140
+ char *s; // current position in buffer
141
+ VALUE obj;
142
+ ParseCallbacks pcb;
143
+ CircArray circ_array;
144
+ unsigned long id; // set for text types when cirs_array is set
145
+ Options options;
146
+ VALUE *marked;
147
+ int mark_size; // allocated size
148
+ int mark_cnt;
149
+ char last; // last character read, rarely set
168
150
  };
169
151
 
170
- extern VALUE ox_parse(char *xml, size_t len, ParseCallbacks pcb, char **endp, Options options, Err err);
171
- extern void _ox_raise_error(const char *msg, const char *xml, const char *current, const char* file, int line);
172
-
173
- extern void ox_sax_define(void);
174
-
175
- extern char* ox_write_obj_to_str(VALUE obj, Options copts);
176
- extern void ox_write_obj_to_file(VALUE obj, const char *path, Options copts);
177
-
178
- extern struct _options ox_default_options;
179
-
180
- extern VALUE Ox;
181
-
182
- extern ID ox_abort_id;
183
- extern ID ox_at_column_id;
184
- extern ID ox_at_content_id;
185
- extern ID ox_at_id;
186
- extern ID ox_at_line_id;
187
- extern ID ox_at_pos_id;
188
- extern ID ox_at_value_id;
189
- extern ID ox_attr_id;
190
- extern ID ox_attr_value_id;
191
- extern ID ox_attrs_done_id;
192
- extern ID ox_attributes_id;
193
- extern ID ox_beg_id;
194
- extern ID ox_bigdecimal_id;
195
- extern ID ox_call_id;
196
- extern ID ox_cdata_id;
197
- extern ID ox_comment_id;
198
- extern ID ox_den_id;
199
- extern ID ox_doctype_id;
200
- extern ID ox_end_element_id;
201
- extern ID ox_end_id;
202
- extern ID ox_end_instruct_id;
203
- extern ID ox_error_id;
204
- extern ID ox_excl_id;
205
- extern ID ox_external_encoding_id;
206
- extern ID ox_fileno_id;
207
- extern ID ox_force_encoding_id;
208
- extern ID ox_inspect_id;
209
- extern ID ox_instruct_id;
210
- extern ID ox_jd_id;
211
- extern ID ox_keys_id;
212
- extern ID ox_local_id;
213
- extern ID ox_mesg_id;
214
- extern ID ox_message_id;
215
- extern ID ox_new_id;
216
- extern ID ox_nodes_id;
217
- extern ID ox_num_id;
218
- extern ID ox_parse_id;
219
- extern ID ox_pos_id;
220
- extern ID ox_read_id;
221
- extern ID ox_readpartial_id;
222
- extern ID ox_start_element_id;
223
- extern ID ox_string_id;
224
- extern ID ox_text_id;
225
- extern ID ox_to_c_id;
226
- extern ID ox_to_s_id;
227
- extern ID ox_to_sym_id;
228
- extern ID ox_tv_sec_id;
229
- extern ID ox_tv_nsec_id;
230
- extern ID ox_tv_usec_id;
231
- extern ID ox_value_id;
232
-
233
- #if HAVE_RB_ENC_ASSOCIATE
234
- extern rb_encoding *ox_utf8_encoding;
235
- #else
236
- extern void *ox_utf8_encoding;
237
- #endif
238
-
239
- extern VALUE ox_empty_string;
240
- extern VALUE ox_encoding_sym;
241
- extern VALUE ox_indent_sym;
242
- extern VALUE ox_size_sym;
243
- extern VALUE ox_standalone_sym;
244
- extern VALUE ox_sym_bank; // Array
245
- extern VALUE ox_version_sym;
246
- extern VALUE ox_zero_fixnum;
247
-
248
- extern VALUE ox_bigdecimal_class;
249
- extern VALUE ox_date_class;
250
- extern VALUE ox_stringio_class;
251
- extern VALUE ox_struct_class;
252
- extern VALUE ox_time_class;
253
-
254
- extern VALUE ox_document_clas;
255
- extern VALUE ox_element_clas;
256
- extern VALUE ox_instruct_clas;
257
- extern VALUE ox_bag_clas;
258
- extern VALUE ox_comment_clas;
259
- extern VALUE ox_raw_clas;
260
- extern VALUE ox_doctype_clas;
261
- extern VALUE ox_cdata_clas;
262
-
263
- extern Cache ox_symbol_cache;
264
- extern Cache ox_class_cache;
265
- extern Cache ox_attr_cache;
266
-
267
- extern void ox_init_builder(VALUE ox);
152
+ extern VALUE ox_parse(char *xml, size_t len, ParseCallbacks pcb, char **endp, Options options, Err err);
153
+ extern void _ox_raise_error(const char *msg, const char *xml, const char *current, const char *file, int line);
154
+
155
+ extern void ox_sax_define(void);
156
+
157
+ extern char *ox_write_obj_to_str(VALUE obj, Options copts);
158
+ extern void ox_write_obj_to_file(VALUE obj, const char *path, Options copts);
159
+
160
+ extern struct _options ox_default_options;
161
+
162
+ extern VALUE Ox;
163
+
164
+ extern ID ox_abort_id;
165
+ extern ID ox_at_column_id;
166
+ extern ID ox_at_content_id;
167
+ extern ID ox_at_id;
168
+ extern ID ox_at_line_id;
169
+ extern ID ox_at_pos_id;
170
+ extern ID ox_at_value_id;
171
+ extern ID ox_attr_id;
172
+ extern ID ox_attr_value_id;
173
+ extern ID ox_attrs_done_id;
174
+ extern ID ox_attributes_id;
175
+ extern ID ox_beg_id;
176
+ extern ID ox_bigdecimal_id;
177
+ extern ID ox_call_id;
178
+ extern ID ox_cdata_id;
179
+ extern ID ox_comment_id;
180
+ extern ID ox_den_id;
181
+ extern ID ox_doctype_id;
182
+ extern ID ox_end_element_id;
183
+ extern ID ox_end_id;
184
+ extern ID ox_end_instruct_id;
185
+ extern ID ox_error_id;
186
+ extern ID ox_excl_id;
187
+ extern ID ox_external_encoding_id;
188
+ extern ID ox_fileno_id;
189
+ extern ID ox_force_encoding_id;
190
+ extern ID ox_inspect_id;
191
+ extern ID ox_instruct_id;
192
+ extern ID ox_jd_id;
193
+ extern ID ox_keys_id;
194
+ extern ID ox_local_id;
195
+ extern ID ox_mesg_id;
196
+ extern ID ox_message_id;
197
+ extern ID ox_new_id;
198
+ extern ID ox_nodes_id;
199
+ extern ID ox_num_id;
200
+ extern ID ox_parse_id;
201
+ extern ID ox_pos_id;
202
+ extern ID ox_read_id;
203
+ extern ID ox_readpartial_id;
204
+ extern ID ox_start_element_id;
205
+ extern ID ox_string_id;
206
+ extern ID ox_text_id;
207
+ extern ID ox_to_c_id;
208
+ extern ID ox_to_s_id;
209
+ extern ID ox_to_sym_id;
210
+ extern ID ox_tv_sec_id;
211
+ extern ID ox_tv_nsec_id;
212
+ extern ID ox_tv_usec_id;
213
+ extern ID ox_value_id;
214
+
215
+ extern rb_encoding *ox_utf8_encoding;
216
+
217
+ extern VALUE ox_empty_string;
218
+ extern VALUE ox_encoding_sym;
219
+ extern VALUE ox_indent_sym;
220
+ extern VALUE ox_size_sym;
221
+ extern VALUE ox_standalone_sym;
222
+ extern VALUE ox_sym_bank; // Array
223
+ extern VALUE ox_version_sym;
224
+ extern VALUE ox_zero_fixnum;
225
+
226
+ extern VALUE ox_bigdecimal_class;
227
+ extern VALUE ox_date_class;
228
+ extern VALUE ox_stringio_class;
229
+ extern VALUE ox_struct_class;
230
+ extern VALUE ox_time_class;
231
+
232
+ extern VALUE ox_document_clas;
233
+ extern VALUE ox_element_clas;
234
+ extern VALUE ox_instruct_clas;
235
+ extern VALUE ox_bag_clas;
236
+ extern VALUE ox_comment_clas;
237
+ extern VALUE ox_raw_clas;
238
+ extern VALUE ox_doctype_clas;
239
+ extern VALUE ox_cdata_clas;
240
+
241
+ extern SlotCache ox_class_cache;
242
+
243
+ extern void ox_init_builder(VALUE ox);
268
244
 
269
245
  #if defined(__cplusplus)
270
246
  #if 0
271
247
  { /* satisfy cc-mode */
272
248
  #endif
273
- } /* extern "C" { */
249
+ } /* extern "C" { */
274
250
  #endif
275
251
  #endif /* OX_H */
data/ext/ox/parse.c CHANGED
@@ -5,13 +5,16 @@
5
5
 
6
6
  #include <stdlib.h>
7
7
  #include <errno.h>
8
+ #include <stdbool.h>
8
9
  #include <stdio.h>
9
10
  #include <string.h>
11
+ #include <strings.h>
10
12
 
11
13
  #include "ruby.h"
12
14
  #include "ox.h"
13
15
  #include "err.h"
14
16
  #include "attr.h"
17
+ #include "intern.h"
15
18
  #include "helper.h"
16
19
  #include "special.h"
17
20
 
@@ -93,6 +96,30 @@ next_white(PInfo pi) {
93
96
  }
94
97
  }
95
98
 
99
+ static void fix_newlines(char *buf) {
100
+ #if HAVE_INDEX
101
+ if (NULL != index(buf, '\r')) {
102
+ #endif
103
+ char *s = buf;
104
+ char *d = buf;
105
+
106
+ for (; '\0' != *s; s++) {
107
+ if ('\r' == *s) {
108
+ if ('\n' == *(s + 1)) {
109
+ continue;
110
+ }
111
+ *s = '\n';
112
+ } else if (d < s) {
113
+ *d = *s;
114
+ }
115
+ d++;
116
+ }
117
+ *d = '\0';
118
+ #if HAVE_INDEX
119
+ }
120
+ #endif
121
+ }
122
+
96
123
  static void
97
124
  mark_pi_cb(void *ptr) {
98
125
  if (NULL != ptr) {
@@ -211,31 +238,11 @@ ox_parse(char *xml, size_t len, ParseCallbacks pcb, char **endp, Options options
211
238
  return pi.obj;
212
239
  }
213
240
 
214
- static char*
215
- gather_content(const char *src, char *content, size_t len) {
216
- for (; 0 < len; src++, content++, len--) {
217
- switch (*src) {
218
- case '?':
219
- if ('>' == *(src + 1)) {
220
- *content = '\0';
221
- return (char*)(src + 1);
222
- }
223
- *content = *src;
224
- break;
225
- case '\0':
226
- return 0;
227
- default:
228
- *content = *src;
229
- break;
230
- }
231
- }
232
- return 0;
233
- }
234
-
235
241
  // Entered after the "<?" sequence. Ready to read the rest.
236
242
  static void
237
243
  read_instruction(PInfo pi) {
238
- char content[1024];
244
+ char content[256];
245
+ char *content_ptr;
239
246
  struct _attrStack attrs;
240
247
  char *attr_name;
241
248
  char *attr_value;
@@ -243,7 +250,8 @@ read_instruction(PInfo pi) {
243
250
  char *end;
244
251
  char c;
245
252
  char *cend;
246
- int attrs_ok = 1;
253
+ size_t size;
254
+ bool attrs_ok = true;
247
255
 
248
256
  *content = '\0';
249
257
  attr_stack_init(&attrs);
@@ -251,10 +259,33 @@ read_instruction(PInfo pi) {
251
259
  return;
252
260
  }
253
261
  end = pi->s;
254
- if (0 == (cend = gather_content(pi->s, content, sizeof(content) - 1))) {
255
- set_error(&pi->err, "processing instruction content too large or not terminated", pi->str, pi->s);
256
- return;
262
+ for (; true; pi->s++) {
263
+ switch (*pi->s) {
264
+ case '?':
265
+ if ('>' == *(pi->s + 1)) {
266
+ pi->s++;
267
+ goto DONE;
268
+ }
269
+ break;
270
+ case '\0':
271
+ set_error(&pi->err, "processing instruction not terminated", pi->str, pi->s);
272
+ return;
273
+ default:
274
+ break;
275
+ }
257
276
  }
277
+ DONE:
278
+ cend = pi->s;
279
+ size = cend - end - 1;
280
+ pi->s = end;
281
+ if (size < sizeof(content)) {
282
+ content_ptr = content;
283
+ } else {
284
+ content_ptr = ALLOC_N(char, size + 1);
285
+ }
286
+ memcpy(content_ptr, end, size);
287
+ content_ptr[size] = '\0';
288
+
258
289
  next_non_white(pi);
259
290
  c = *pi->s;
260
291
  *end = '\0'; // terminate name
@@ -274,7 +305,7 @@ read_instruction(PInfo pi) {
274
305
  end = pi->s;
275
306
  next_non_white(pi);
276
307
  if ('=' != *pi->s++) {
277
- attrs_ok = 0;
308
+ attrs_ok = false;
278
309
  break;
279
310
  }
280
311
  *end = '\0'; // terminate name
@@ -311,10 +342,13 @@ read_instruction(PInfo pi) {
311
342
  if (attrs_ok) {
312
343
  pi->pcb->instruct(pi, target, attrs.head, 0);
313
344
  } else {
314
- pi->pcb->instruct(pi, target, attrs.head, content);
345
+ pi->pcb->instruct(pi, target, attrs.head, content_ptr);
315
346
  }
316
347
  }
317
348
  attr_stack_cleanup(&attrs);
349
+ if (content_ptr != content) {
350
+ xfree(content_ptr);
351
+ }
318
352
  }
319
353
 
320
354
  static void
@@ -361,10 +395,10 @@ read_delimited(PInfo pi, char end) {
361
395
  // that. Ready to read the rest.
362
396
  static void
363
397
  read_doctype(PInfo pi) {
364
- char *docType;
398
+ char *doctype;
365
399
 
366
400
  next_non_white(pi);
367
- docType = pi->s;
401
+ doctype = pi->s;
368
402
  read_delimited(pi, '>');
369
403
  if (err_has(&pi->err)) {
370
404
  return;
@@ -373,7 +407,8 @@ read_doctype(PInfo pi) {
373
407
  *pi->s = '\0';
374
408
  pi->s++;
375
409
  if (0 != pi->pcb->add_doctype) {
376
- pi->pcb->add_doctype(pi, docType);
410
+ fix_newlines(doctype);
411
+ pi->pcb->add_doctype(pi, doctype);
377
412
  }
378
413
  }
379
414
 
@@ -409,6 +444,7 @@ read_comment(PInfo pi) {
409
444
  *end = '\0'; // in case the comment was blank
410
445
  pi->s = end + 3;
411
446
  if (0 != pi->pcb->add_comment) {
447
+ fix_newlines(comment);
412
448
  pi->pcb->add_comment(pi, comment);
413
449
  }
414
450
  }
@@ -769,9 +805,11 @@ read_text(PInfo pi) {
769
805
  }
770
806
  *b = '\0';
771
807
  if (0 != alloc_buf) {
808
+ fix_newlines(alloc_buf);
772
809
  pi->pcb->add_text(pi, alloc_buf, ('/' == *(pi->s + 1)));
773
810
  xfree(alloc_buf);
774
811
  } else {
812
+ fix_newlines(buf);
775
813
  pi->pcb->add_text(pi, buf, ('/' == *(pi->s + 1)));
776
814
  }
777
815
  }
@@ -838,9 +876,11 @@ read_reduced_text(PInfo pi) {
838
876
  }
839
877
  *b = '\0';
840
878
  if (0 != alloc_buf) {
879
+ fix_newlines(alloc_buf);
841
880
  pi->pcb->add_text(pi, alloc_buf, ('/' == *(pi->s + 1)));
842
881
  xfree(alloc_buf);
843
882
  } else {
883
+ fix_newlines(buf);
844
884
  pi->pcb->add_text(pi, buf, ('/' == *(pi->s + 1)));
845
885
  }
846
886
  }
@@ -899,6 +939,7 @@ read_cdata(PInfo pi) {
899
939
  *end = '\0';
900
940
  pi->s = end + 3;
901
941
  if (0 != pi->pcb->add_cdata) {
942
+ fix_newlines(start);
902
943
  pi->pcb->add_cdata(pi, start, end - start);
903
944
  }
904
945
  }