redcarpet 2.0.0b3 → 2.0.0b4

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

Potentially problematic release.


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

data/README.markdown CHANGED
@@ -19,7 +19,7 @@ library so awesome.
19
19
  This library is written by people
20
20
  -------------------------------------------------------
21
21
 
22
- Redcarpet 2 has been rewritten from scratch by Vicent Marti (@tanoku). Why
22
+ Redcarpet 2 has been rewritten from scratch by Vicent Martí (@tanoku). Why
23
23
  are you not following me on Twitter?
24
24
 
25
25
  Redcarpet would not be possible without the Sundown library and its authors
@@ -56,7 +56,7 @@ settings, and reused between parses.
56
56
  If the given object has not been instantiated, the library
57
57
  will do it with default arguments.
58
58
 
59
- extensions - a hash containing the Markdown extesions which the parser
59
+ extensions - a hash containing the Markdown extensions which the parser
60
60
  will identify. The following extensions are accepted:
61
61
 
62
62
  :no_intra_emphasis - do not parse emphasis inside of words.
@@ -85,7 +85,7 @@ settings, and reused between parses.
85
85
  by an empty line as in the Markdown standard.
86
86
 
87
87
  :space_after_headers - A space is always required between the
88
- hash at the beggining of a header and its name, e.g.
88
+ hash at the beginning of a header and its name, e.g.
89
89
  `#this is my header` would not be a valid header.
90
90
 
91
91
  :superscript - parse superscripts after the `^` character;
@@ -123,6 +123,40 @@ renderers are actually implemented in C, and hence offer a brilliant
123
123
  performance, several degrees of magnitude faster than other Ruby Markdown
124
124
  solutions.
125
125
 
126
+ All the rendering flags that previously applied only to HTML output have
127
+ now been moved to the `Render::HTML` class, and may be enabled when
128
+ instantiating the renderer:
129
+
130
+ Render::HTML.new(render_options={})
131
+
132
+ Initializes an HTML renderer. The following flags are available:
133
+
134
+ :filter_html - do not allow any user-inputted HTML in the output
135
+
136
+ :no_images - do not generate any `<img>` tags
137
+
138
+ :no_links - do not generate any `<a>` tags
139
+
140
+ :no_styles - do not generate any `<style>` tags
141
+
142
+ :safe_links_only - only generate links for protocols which are considered safe
143
+
144
+ :with_toc_data - add HTML anchors to each header in the output HTML,
145
+ to allow liking to each section.
146
+
147
+ :hard_wrap - insert HTML `<br>` tags inside on paragraphs where the origin
148
+ Markdown document had newlines (by default, Markdown ignores these
149
+ newlines).
150
+
151
+ :xhtml - output XHTML-conformant tags. This option is always enabled in the
152
+ `Render::XHTML` renderer.
153
+
154
+
155
+ Example:
156
+
157
+ rndr = Redcarpet::Render::HTML.new(:no_links => true, :hard_wrap => true)
158
+
159
+
126
160
  The `HTML` renderer has an alternate version, `Redcarpet::Render::HTML_TOC`,
127
161
  which will output a table of contents in HTML based on the headers of the
128
162
  Markdown document.
@@ -136,7 +170,7 @@ And you can even cook your own
136
170
  ------------------------------
137
171
 
138
172
  Custom renderers are created by inheriting from an existing renderer. The
139
- builtin renderers, `HTML` and `XHTML` may be extended as such:
173
+ built-in renderers, `HTML` and `XHTML` may be extended as such:
140
174
 
141
175
  ~~~~~ ruby
142
176
  # create a custom renderer that allows highlighting of code blocks
@@ -226,7 +260,7 @@ Also, now our Pants are much smarter
226
260
 
227
261
  Redcarpet 2 comes with a standalone [SmartyPants](
228
262
  http://daringfireball.net/projects/smartypants/) implementation. It is fully
229
- compilant with the original implementation. It is the fastest SmartyPants
263
+ compliant with the original implementation. It is the fastest SmartyPants
230
264
  parser there is, with a difference of several orders of magnitude.
231
265
 
232
266
  The SmartyPants parser can be found in `Redcarpet::Render::SmartyPants`. It has
data/Rakefile CHANGED
@@ -113,8 +113,8 @@ desc 'Gather required Sundown sources into extension directory'
113
113
  task :gather => 'sundown/src/markdown.h' do |t|
114
114
  files =
115
115
  FileList[
116
- 'sundown/src/{markdown,buffer,array,autolink}.h',
117
- 'sundown/src/{markdown,buffer,array,autolink}.c',
116
+ 'sundown/src/{markdown,buffer,stack,autolink,html_blocks}.h',
117
+ 'sundown/src/{markdown,buffer,stack,autolink}.c',
118
118
  'sundown/html/{html,html_smartypants}.c',
119
119
  'sundown/html/html.h',
120
120
  ]
@@ -22,7 +22,7 @@
22
22
  #include <ctype.h>
23
23
 
24
24
  int
25
- sd_autolink_issafe(const char *link, size_t link_len)
25
+ sd_autolink_issafe(const uint8_t *link, size_t link_len)
26
26
  {
27
27
  static const size_t valid_uris_count = 4;
28
28
  static const char *valid_uris[] = {
@@ -35,7 +35,7 @@ sd_autolink_issafe(const char *link, size_t link_len)
35
35
  size_t len = strlen(valid_uris[i]);
36
36
 
37
37
  if (link_len > len &&
38
- strncasecmp(link, valid_uris[i], len) == 0 &&
38
+ strncasecmp((char *)link, valid_uris[i], len) == 0 &&
39
39
  isalnum(link[len]))
40
40
  return 1;
41
41
  }
@@ -44,9 +44,9 @@ sd_autolink_issafe(const char *link, size_t link_len)
44
44
  }
45
45
 
46
46
  static size_t
47
- autolink_delim(char *data, size_t link_end, size_t offset, size_t size)
47
+ autolink_delim(uint8_t *data, size_t link_end, size_t offset, size_t size)
48
48
  {
49
- char cclose, copen = 0;
49
+ uint8_t cclose, copen = 0;
50
50
  size_t i;
51
51
 
52
52
  for (i = 0; i < link_end; ++i)
@@ -128,7 +128,7 @@ autolink_delim(char *data, size_t link_end, size_t offset, size_t size)
128
128
  }
129
129
 
130
130
  static size_t
131
- check_domain(char *data, size_t size)
131
+ check_domain(uint8_t *data, size_t size)
132
132
  {
133
133
  size_t i, np = 0;
134
134
 
@@ -147,14 +147,14 @@ check_domain(char *data, size_t size)
147
147
  }
148
148
 
149
149
  size_t
150
- sd_autolink__www(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size)
150
+ sd_autolink__www(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size)
151
151
  {
152
152
  size_t link_end;
153
153
 
154
154
  if (offset > 0 && !ispunct(data[-1]) && !isspace(data[-1]))
155
155
  return 0;
156
156
 
157
- if (size < 4 || memcmp(data, "www.", STRLEN("www.")) != 0)
157
+ if (size < 4 || memcmp(data, "www.", strlen("www.")) != 0)
158
158
  return 0;
159
159
 
160
160
  link_end = check_domain(data, size);
@@ -177,13 +177,13 @@ sd_autolink__www(size_t *rewind_p, struct buf *link, char *data, size_t offset,
177
177
  }
178
178
 
179
179
  size_t
180
- sd_autolink__email(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size)
180
+ sd_autolink__email(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size)
181
181
  {
182
182
  size_t link_end, rewind;
183
183
  int nb = 0, np = 0;
184
184
 
185
185
  for (rewind = 0; rewind < offset; ++rewind) {
186
- char c = data[-rewind - 1];
186
+ uint8_t c = data[-rewind - 1];
187
187
 
188
188
  if (isalnum(c))
189
189
  continue;
@@ -198,7 +198,7 @@ sd_autolink__email(size_t *rewind_p, struct buf *link, char *data, size_t offset
198
198
  return 0;
199
199
 
200
200
  for (link_end = 0; link_end < size; ++link_end) {
201
- char c = data[link_end];
201
+ uint8_t c = data[link_end];
202
202
 
203
203
  if (isalnum(c))
204
204
  continue;
@@ -226,7 +226,7 @@ sd_autolink__email(size_t *rewind_p, struct buf *link, char *data, size_t offset
226
226
  }
227
227
 
228
228
  size_t
229
- sd_autolink__url(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size)
229
+ sd_autolink__url(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size)
230
230
  {
231
231
  size_t link_end, rewind = 0, domain_len;
232
232
 
@@ -238,7 +238,7 @@ sd_autolink__url(size_t *rewind_p, struct buf *link, char *data, size_t offset,
238
238
 
239
239
  if (!sd_autolink_issafe(data - rewind, size + rewind))
240
240
  return 0;
241
- link_end = STRLEN("://");
241
+ link_end = strlen("://");
242
242
 
243
243
  domain_len = check_domain(data + link_end, size - link_end);
244
244
  if (domain_len == 0)
@@ -20,16 +20,16 @@
20
20
  #include "buffer.h"
21
21
 
22
22
  extern int
23
- sd_autolink_issafe(const char *link, size_t link_len);
23
+ sd_autolink_issafe(const uint8_t *link, size_t link_len);
24
24
 
25
25
  extern size_t
26
- sd_autolink__www(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size);
26
+ sd_autolink__www(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size);
27
27
 
28
28
  extern size_t
29
- sd_autolink__email(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size);
29
+ sd_autolink__email(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size);
30
30
 
31
31
  extern size_t
32
- sd_autolink__url(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size);
32
+ sd_autolink__url(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size);
33
33
 
34
34
  #endif
35
35
 
@@ -1,7 +1,6 @@
1
- /* buffer.c - automatic buffer structure */
2
-
3
1
  /*
4
2
  * Copyright (c) 2008, Natacha Porté
3
+ * Copyright (c) 2011, Vicent Martí
5
4
  *
6
5
  * Permission to use, copy, modify, and distribute this software for any
7
6
  * purpose with or without fee is hereby granted, provided that the above
@@ -16,13 +15,6 @@
16
15
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
16
  */
18
17
 
19
- /*
20
- * COMPILE TIME OPTIONS
21
- *
22
- * BUFFER_STATS • if defined, stats are kept about memory usage
23
- */
24
-
25
- #define BUFFER_STDARG
26
18
  #define BUFFER_MAX_ALLOC_SIZE (1024 * 1024 * 16) //16mb
27
19
 
28
20
  #include "buffer.h"
@@ -31,78 +23,13 @@
31
23
  #include <stdlib.h>
32
24
  #include <string.h>
33
25
 
34
-
35
- /********************
36
- * GLOBAL VARIABLES *
37
- ********************/
38
-
39
- #ifdef BUFFER_STATS
40
- long buffer_stat_nb = 0;
41
- size_t buffer_stat_alloc_bytes = 0;
26
+ /* MSVC compat */
27
+ #if defined(_MSC_VER)
28
+ # define _buf_vsnprintf _vsnprintf
29
+ #else
30
+ # define _buf_vsnprintf vsnprintf
42
31
  #endif
43
32
 
44
-
45
- /***************************
46
- * STATIC HELPER FUNCTIONS *
47
- ***************************/
48
-
49
- /* lower • retruns the lower-case variant of the input char */
50
- static char
51
- lower(char c) {
52
- return (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c; }
53
-
54
-
55
-
56
- /********************
57
- * BUFFER FUNCTIONS *
58
- ********************/
59
-
60
- /* bufcasecmp • case-insensitive buffer comparison */
61
- int
62
- bufcasecmp(const struct buf *a, const struct buf *b) {
63
- size_t i = 0;
64
- size_t cmplen;
65
- if (a == b) return 0;
66
- if (!a) return -1; else if (!b) return 1;
67
- cmplen = (a->size < b->size) ? a->size : b->size;
68
- while (i < cmplen && lower(a->data[i]) == lower(b->data[i])) ++i;
69
- if (i < a->size) {
70
- if (i < b->size) return lower(a->data[i]) - lower(b->data[i]);
71
- else return 1; }
72
- else { if (i < b->size) return -1;
73
- else return 0; } }
74
-
75
-
76
- /* bufcmp • case-sensitive buffer comparison */
77
- int
78
- bufcmp(const struct buf *a, const struct buf *b) {
79
- size_t i = 0;
80
- size_t cmplen;
81
- if (a == b) return 0;
82
- if (!a) return -1; else if (!b) return 1;
83
- cmplen = (a->size < b->size) ? a->size : b->size;
84
- while (i < cmplen && a->data[i] == b->data[i]) ++i;
85
- if (i < a->size) {
86
- if (i < b->size) return a->data[i] - b->data[i];
87
- else return 1; }
88
- else { if (i < b->size) return -1;
89
- else return 0; } }
90
-
91
-
92
- /* bufcmps • case-sensitive comparison of a string to a buffer */
93
- int
94
- bufcmps(const struct buf *a, const char *b) {
95
- const size_t len = strlen(b);
96
- size_t cmplen = len;
97
- int r;
98
- if (!a || !a->size) return b ? 0 : -1;
99
- if (len < a->size) cmplen = a->size;
100
- r = strncmp(a->data, b, cmplen);
101
- if (r) return r;
102
- else if (a->size == len) return 0;
103
- else if (a->size < len) return -1;
104
- else return 1; }
105
-
106
33
  int
107
34
  bufprefix(const struct buf *buf, const char *prefix)
108
35
  {
@@ -119,200 +46,179 @@ bufprefix(const struct buf *buf, const char *prefix)
119
46
  return 0;
120
47
  }
121
48
 
122
-
123
- /* bufdup • buffer duplication */
124
- struct buf *
125
- bufdup(const struct buf *src, size_t dupunit) {
126
- size_t blocks;
127
- struct buf *ret;
128
- if (src == 0) return 0;
129
- ret = malloc(sizeof (struct buf));
130
- if (ret == 0) return 0;
131
- ret->unit = dupunit;
132
- ret->size = src->size;
133
- ret->ref = 1;
134
- if (!src->size) {
135
- ret->asize = 0;
136
- ret->data = 0;
137
- return ret; }
138
- blocks = (src->size + dupunit - 1) / dupunit;
139
- ret->asize = blocks * dupunit;
140
- ret->data = malloc(ret->asize);
141
- if (ret->data == 0) {
142
- free(ret);
143
- return 0; }
144
- memcpy(ret->data, src->data, src->size);
145
- #ifdef BUFFER_STATS
146
- buffer_stat_nb += 1;
147
- buffer_stat_alloc_bytes += ret->asize;
148
- #endif
149
- return ret; }
150
-
151
- /* bufgrow • increasing the allocated size to the given value */
49
+ /* bufgrow: increasing the allocated size to the given value */
152
50
  int
153
- bufgrow(struct buf *buf, size_t neosz) {
51
+ bufgrow(struct buf *buf, size_t neosz)
52
+ {
154
53
  size_t neoasz;
155
54
  void *neodata;
156
- if (!buf || !buf->unit || neosz > BUFFER_MAX_ALLOC_SIZE) return 0;
157
- if (buf->asize >= neosz) return 1;
55
+ if (!buf || !buf->unit || neosz > BUFFER_MAX_ALLOC_SIZE)
56
+ return BUF_ENOMEM;
57
+
58
+ if (buf->asize >= neosz)
59
+ return BUF_OK;
60
+
158
61
  neoasz = buf->asize + buf->unit;
159
- while (neoasz < neosz) neoasz += buf->unit;
62
+ while (neoasz < neosz)
63
+ neoasz += buf->unit;
64
+
160
65
  neodata = realloc(buf->data, neoasz);
161
- if (!neodata) return 0;
162
- #ifdef BUFFER_STATS
163
- buffer_stat_alloc_bytes += (neoasz - buf->asize);
164
- #endif
66
+ if (!neodata)
67
+ return BUF_ENOMEM;
68
+
165
69
  buf->data = neodata;
166
70
  buf->asize = neoasz;
167
- return 1; }
71
+ return BUF_OK;
72
+ }
168
73
 
169
74
 
170
- /* bufnew allocation of a new buffer */
75
+ /* bufnew: allocation of a new buffer */
171
76
  struct buf *
172
- bufnew(size_t unit) {
77
+ bufnew(size_t unit)
78
+ {
173
79
  struct buf *ret;
174
80
  ret = malloc(sizeof (struct buf));
81
+
175
82
  if (ret) {
176
- #ifdef BUFFER_STATS
177
- buffer_stat_nb += 1;
178
- #endif
179
83
  ret->data = 0;
180
84
  ret->size = ret->asize = 0;
181
- ret->ref = 1;
182
- ret->unit = unit; }
183
- return ret; }
85
+ ret->unit = unit;
86
+ }
87
+ return ret;
88
+ }
184
89
 
90
+ /* bufnullterm: NULL-termination of the string array */
91
+ const char *
92
+ bufcstr(struct buf *buf)
93
+ {
94
+ if (!buf || !buf->unit)
95
+ return NULL;
185
96
 
186
- /* bufnullterm NUL-termination of the string array (making a C-string) */
187
- void
188
- bufnullterm(struct buf *buf) {
189
- if (!buf || !buf->unit) return;
190
- if (buf->size < buf->asize && buf->data[buf->size] == 0) return;
191
- if (buf->size + 1 <= buf->asize || bufgrow(buf, buf->size + 1))
192
- buf->data[buf->size] = 0; }
97
+ if (buf->size < buf->asize && buf->data[buf->size] == 0)
98
+ return (char *)buf->data;
193
99
 
100
+ if (buf->size + 1 <= buf->asize || bufgrow(buf, buf->size + 1) == 0) {
101
+ buf->data[buf->size] = 0;
102
+ return (char *)buf->data;
103
+ }
104
+
105
+ return NULL;
106
+ }
194
107
 
195
- /* bufprintf formatted printing to a buffer */
108
+ /* bufprintf: formatted printing to a buffer */
196
109
  void
197
- bufprintf(struct buf *buf, const char *fmt, ...) {
110
+ bufprintf(struct buf *buf, const char *fmt, ...)
111
+ {
198
112
  va_list ap;
199
- if (!buf || !buf->unit) return;
113
+ if (!buf || !buf->unit)
114
+ return;
115
+
200
116
  va_start(ap, fmt);
201
117
  vbufprintf(buf, fmt, ap);
202
- va_end(ap); }
203
-
118
+ va_end(ap);
119
+ }
204
120
 
205
- /* bufput appends raw data to a buffer */
121
+ /* bufput: appends raw data to a buffer */
206
122
  void
207
- bufput(struct buf *buf, const void *data, size_t len) {
208
- if (!buf) return;
209
- if (buf->size + len > buf->asize && !bufgrow(buf, buf->size + len))
123
+ bufput(struct buf *buf, const void *data, size_t len)
124
+ {
125
+ if (!buf)
210
126
  return;
211
- memcpy(buf->data + buf->size, data, len);
212
- buf->size += len; }
213
127
 
128
+ if (buf->size + len > buf->asize && bufgrow(buf, buf->size + len) < 0)
129
+ return;
214
130
 
215
- /* bufputs appends a NUL-terminated string to a buffer */
131
+ memcpy(buf->data + buf->size, data, len);
132
+ buf->size += len;
133
+ }
134
+
135
+ /* bufputs: appends a NUL-terminated string to a buffer */
216
136
  void
217
- bufputs(struct buf *buf, const char *str) {
218
- bufput(buf, str, strlen (str)); }
137
+ bufputs(struct buf *buf, const char *str)
138
+ {
139
+ bufput(buf, str, strlen(str));
140
+ }
219
141
 
220
142
 
221
- /* bufputc appends a single char to a buffer */
143
+ /* bufputc: appends a single uint8_t to a buffer */
222
144
  void
223
- bufputc(struct buf *buf, char c) {
224
- if (!buf) return;
225
- if (buf->size + 1 > buf->asize && !bufgrow(buf, buf->size + 1))
145
+ bufputc(struct buf *buf, int c)
146
+ {
147
+ if (!buf)
226
148
  return;
227
- buf->data[buf->size] = c;
228
- buf->size += 1; }
229
-
230
149
 
231
- /* bufrelease decrease the reference count and free the buffer if needed */
232
- void
233
- bufrelease(struct buf *buf) {
234
- if (!buf) return;
235
- buf->ref -= 1;
236
- if (buf->ref == 0) {
237
- #ifdef BUFFER_STATS
238
- buffer_stat_nb -= 1;
239
- buffer_stat_alloc_bytes -= buf->asize;
240
- #endif
241
- free(buf->data);
242
- free(buf); } }
150
+ if (buf->size + 1 > buf->asize && bufgrow(buf, buf->size + 1) < 0)
151
+ return;
243
152
 
153
+ buf->data[buf->size] = c;
154
+ buf->size += 1;
155
+ }
244
156
 
245
- /* bufreset frees internal data of the buffer */
157
+ /* bufrelease: decrease the reference count and free the buffer if needed */
246
158
  void
247
- bufreset(struct buf *buf) {
248
- if (!buf) return;
249
- #ifdef BUFFER_STATS
250
- buffer_stat_alloc_bytes -= buf->asize;
251
- #endif
159
+ bufrelease(struct buf *buf)
160
+ {
161
+ if (!buf)
162
+ return;
163
+
252
164
  free(buf->data);
253
- buf->data = 0;
254
- buf->size = buf->asize = 0; }
165
+ free(buf);
166
+ }
255
167
 
256
168
 
257
- /* bufset safely assigns a buffer to another */
169
+ /* bufreset: frees internal data of the buffer */
258
170
  void
259
- bufset(struct buf **dest, struct buf *src) {
260
- if (src) {
261
- if (!src->asize) src = bufdup(src, 1);
262
- else src->ref += 1; }
263
- bufrelease(*dest);
264
- *dest = src; }
171
+ bufreset(struct buf *buf)
172
+ {
173
+ if (!buf)
174
+ return;
265
175
 
176
+ free(buf->data);
177
+ buf->data = NULL;
178
+ buf->size = buf->asize = 0;
179
+ }
266
180
 
267
- /* bufslurp removes a given number of bytes from the head of the array */
181
+ /* bufslurp: removes a given number of bytes from the head of the array */
268
182
  void
269
- bufslurp(struct buf *buf, size_t len) {
270
- if (!buf || !buf->unit || len <= 0) return;
183
+ bufslurp(struct buf *buf, size_t len)
184
+ {
185
+ if (!buf || !buf->unit || len <= 0)
186
+ return;
187
+
271
188
  if (len >= buf->size) {
272
189
  buf->size = 0;
273
- return; }
274
- buf->size -= len;
275
- memmove(buf->data, buf->data + len, buf->size); }
190
+ return;
191
+ }
276
192
 
193
+ buf->size -= len;
194
+ memmove(buf->data, buf->data + len, buf->size);
195
+ }
277
196
 
278
- /* buftoi converts the numbers at the beginning of the buf into an int */
279
- int
280
- buftoi(struct buf *buf, size_t offset_i, size_t *offset_o) {
281
- int r = 0, neg = 0;
282
- size_t i = offset_i;
283
- if (!buf || !buf->size) return 0;
284
- if (buf->data[i] == '+') i += 1;
285
- else if (buf->data[i] == '-') {
286
- neg = 1;
287
- i += 1; }
288
- while (i < buf->size && buf->data[i] >= '0' && buf->data[i] <= '9') {
289
- r = (r * 10) + buf->data[i] - '0';
290
- i += 1; }
291
- if (offset_o) *offset_o = i;
292
- return neg ? -r : r; }
293
-
294
-
295
-
296
- /* vbufprintf • stdarg variant of formatted printing into a buffer */
197
+ /* vbufprintf: stdarg variant of formatted printing into a buffer */
297
198
  void
298
- vbufprintf(struct buf *buf, const char *fmt, va_list ap) {
199
+ vbufprintf(struct buf *buf, const char *fmt, va_list ap)
200
+ {
299
201
  int n;
300
- va_list ap_save;
301
- if (buf == 0
302
- || (buf->size >= buf->asize && !bufgrow (buf, buf->size + 1)))
202
+
203
+ if (buf == 0 || (buf->size >= buf->asize && bufgrow(buf, buf->size + 1)) < 0)
303
204
  return;
304
205
 
305
- va_copy(ap_save, ap);
306
- n = vsnprintf(buf->data + buf->size, buf->asize - buf->size, fmt, ap);
206
+ n = _buf_vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);
207
+
208
+ if (n < 0) {
209
+ #ifdef _MSC_VER
210
+ n = _vscprintf(fmt, ap);
211
+ #else
212
+ return;
213
+ #endif
214
+ }
307
215
 
308
- if (n < 0 || (size_t)n >= buf->asize - buf->size) {
309
- size_t new_size = (n > 0) ? n : buf->size;
310
- if (!bufgrow (buf, buf->size + new_size + 1))
216
+ if ((size_t)n >= buf->asize - buf->size) {
217
+ if (bufgrow(buf, buf->size + n + 1) < 0)
311
218
  return;
312
219
 
313
- n = vsnprintf(buf->data + buf->size, buf->asize - buf->size, fmt, ap_save);
220
+ n = _buf_vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);
314
221
  }
315
- va_end(ap_save);
316
222
 
317
223
  if (n < 0)
318
224
  return;
@@ -320,4 +226,3 @@ vbufprintf(struct buf *buf, const char *fmt, va_list ap) {
320
226
  buf->size += n;
321
227
  }
322
228
 
323
- /* vim: set filetype=c: */