ox 2.14.4 → 2.14.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
  }