patcito-rdiscount 1.6.8

Sign up to get free protection for your applications and to get access to all the features.
data/BUILDING ADDED
@@ -0,0 +1,34 @@
1
+ BUILDING rdiscount
2
+ ==================
3
+
4
+ You'll be needing Ruby, rake, and a basic build environment.
5
+
6
+ Build the rdiscount extension for tests and local development:
7
+
8
+ $ rake build
9
+
10
+ Use your rdiscount working copy when running ruby programs:
11
+
12
+ $ export RUBYLIB=~/rdiscount/lib:$RUBYLIB
13
+ $ ruby some-program.rb
14
+
15
+ Gathering changes from an upstream Orc/discount.git clone requires first
16
+ grabbing the discount submodule into the root of the project and then running
17
+ the rake gather task to copy discount source files into the ext/ directory:
18
+
19
+ $ git submodule init
20
+ Submodule 'discount' (git://github.com/rtomayko/discount.git) registered for path 'discount'
21
+ $ rake gather
22
+ $ rake build
23
+
24
+ The rtomayko/discount.git repository's master branch is the default submodule
25
+ head. It exists to merge branches for rdiscount specific patches to the upstream
26
+ discount codebase.
27
+
28
+ Do work in the submodule and then add a remote for your clone THAT YOU FORKED ON
29
+ GITHUB BECAUSE YOU'RE GOING TO SEND ME A PULL REQUEST. After you've committed
30
+ your great changes somewhere, push them up with:
31
+
32
+ $ cd discount
33
+ $ git remote add you git@github.com:you/discount.git
34
+ $ git push you HEAD:topic-branch-name
data/COPYING ADDED
@@ -0,0 +1,52 @@
1
+ The core Discount C sources are
2
+ Copyright (C) 2007 David Loren Parsons.
3
+
4
+ The Discount Ruby extension sources are
5
+ Copyright (C) 2008 Ryan Tomayko.
6
+
7
+ All rights reserved.
8
+
9
+ Permission is hereby granted, free of charge, to any person
10
+ obtaining a copy of this software and associated documentation files
11
+ (the "Software"), to deal in the Software without restriction,
12
+ including without limitation the rights to use, copy, modify, merge,
13
+ publish, distribute, sublicence, and/or sell copies of the Software,
14
+ and to permit persons to whom the Software is furnished to do so,
15
+ subject to the following conditions:
16
+
17
+ 1. Redistributions of source code must retain the above copyright
18
+ notice, this list of conditions, and the following disclaimer.
19
+
20
+ 2. Redistributions in binary form must reproduce the above
21
+ copyright notice, this list of conditions and the following
22
+ disclaimer in the documentation and/or other materials provided
23
+ with the distribution, and in the same place and form as other
24
+ copyright, license and disclaimer information.
25
+
26
+ 3. The end-user documentation included with the redistribution, if
27
+ any, must include the following acknowledgment:
28
+
29
+ This product includes software developed by
30
+ David Loren Parsons <http://www.pell.portland.or.us/~orc>
31
+
32
+ in the same place and form as other third-party acknowledgments.
33
+ Alternately, this acknowledgment may appear in the software
34
+ itself, in the same form and location as other such third-party
35
+ acknowledgments.
36
+
37
+ 4. Except as contained in this notice, the name of David Loren
38
+ Parsons shall not be used in advertising or otherwise to promote
39
+ the sale, use or other dealings in this Software without prior
40
+ written authorization from David Loren Parsons.
41
+
42
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
43
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
44
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45
+ IN NO EVENT SHALL DAVID LOREN PARSONS BE LIABLE FOR ANY DIRECT,
46
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
47
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
48
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
50
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
52
+ OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.markdown ADDED
@@ -0,0 +1,71 @@
1
+ Discount Markdown Processor for Ruby
2
+ ====================================
3
+
4
+ Discount is an implementation of John Gruber's Markdown markup language in C. It
5
+ implements all of the language described in [the markdown syntax document][1] and
6
+ passes the [Markdown 1.0 test suite][2].
7
+
8
+ CODE: `git clone git://github.com/rtomayko/rdiscount.git`
9
+ HOME: <http://github.com/rtomayko/rdiscount>
10
+ DOCS: <http://rdoc.info/projects/rtomayko/rdiscount>
11
+ BUGS: <http://github.com/rtomayko/rdiscount/issues>
12
+
13
+ Discount was developed by [David Loren Parsons][3]. The Ruby extension
14
+ is maintained by [Ryan Tomayko][4].
15
+
16
+ [1]: http://daringfireball.net/projects/markdown/syntax
17
+ [2]: http://daringfireball.net/projects/downloads/MarkdownTest_1.0.zip
18
+ [3]: http://www.pell.portland.or.us/~orc
19
+ [4]: http://tomayko.com/about
20
+
21
+ INSTALL, HACKING
22
+ ----------------
23
+
24
+ New releases of RDiscount are published to [gemcutter][]:
25
+
26
+ $ [sudo] gem install rdiscount -s http://gemcutter.org
27
+
28
+ The RDiscount sources are available via Git:
29
+
30
+ $ git clone git://github.com/rtomayko/rdiscount.git
31
+ $ cd rdiscount
32
+ $ rake --tasks
33
+
34
+ See the file [BUILDING][] for hacking instructions.
35
+
36
+ [gemcutter]: http://gemcutter.org/gems/rdiscount
37
+ [BUILDING]: BUILDING
38
+
39
+ USAGE
40
+ -----
41
+
42
+ RDiscount implements the basic protocol popularized by RedCloth and adopted
43
+ by BlueCloth:
44
+
45
+ require 'rdiscount'
46
+ markdown = RDiscount.new("Hello World!")
47
+ puts markdown.to_html
48
+
49
+ Additional processing options can be turned on when creating the
50
+ RDiscount object:
51
+
52
+ markdown = RDiscount.new("Hello World!", :smart, :filter_html)
53
+
54
+ Inject RDiscount into your BlueCloth-using code by replacing your bluecloth
55
+ require statements with the following:
56
+
57
+ begin
58
+ require 'rdiscount'
59
+ BlueCloth = RDiscount
60
+ rescue LoadError
61
+ require 'bluecloth'
62
+ end
63
+
64
+ COPYING
65
+ -------
66
+
67
+ Discount is free software; it is released under a BSD-style license
68
+ that allows you to do as you wish with it as long as you don't attempt
69
+ to claim it as your own work. RDiscount adopts Discount's license
70
+ verbatim. See the file `COPYING` for more information.
71
+
data/Rakefile ADDED
@@ -0,0 +1,182 @@
1
+ require 'date'
2
+ require 'rake/clean'
3
+ require 'digest/md5'
4
+
5
+ task :default => :test
6
+
7
+ # ==========================================================
8
+ # Ruby Extension
9
+ # ==========================================================
10
+
11
+ DLEXT = Config::MAKEFILE_CONFIG['DLEXT']
12
+ RUBYDIGEST = Digest::MD5.hexdigest(`#{RUBY} --version`)
13
+
14
+ file "ext/ruby-#{RUBYDIGEST}" do |f|
15
+ rm_f FileList["ext/ruby-*"]
16
+ touch f.name
17
+ end
18
+ CLEAN.include "ext/ruby-*"
19
+
20
+ file 'ext/Makefile' => FileList['ext/*.{c,h,rb}', "ext/ruby-#{RUBYDIGEST}"] do
21
+ chdir('ext') { ruby 'extconf.rb' }
22
+ end
23
+ CLEAN.include 'ext/Makefile', 'ext/mkmf.log'
24
+
25
+ file "ext/rdiscount.#{DLEXT}" => FileList["ext/Makefile"] do |f|
26
+ sh 'cd ext && make clean && make && rm -rf conftest.dSYM'
27
+ end
28
+ CLEAN.include 'ext/*.{o,bundle,so,dll}'
29
+
30
+ file "lib/rdiscount.#{DLEXT}" => "ext/rdiscount.#{DLEXT}" do |f|
31
+ cp f.prerequisites, "lib/", :preserve => true
32
+ end
33
+
34
+ desc 'Build the rdiscount extension'
35
+ task :build => "lib/rdiscount.#{DLEXT}"
36
+
37
+ # ==========================================================
38
+ # Manual
39
+ # ==========================================================
40
+
41
+ file 'man/rdiscount.1' => 'man/rdiscount.1.ronn' do
42
+ sh "ronn --manual=RUBY -b man/rdiscount.1.ronn"
43
+ end
44
+ CLOBBER.include 'man/rdiscount.1'
45
+
46
+ desc 'Build manpages'
47
+ task :man => 'man/rdiscount.1'
48
+
49
+ # ==========================================================
50
+ # Testing
51
+ # ==========================================================
52
+
53
+ require 'rake/testtask'
54
+ Rake::TestTask.new('test:unit') do |t|
55
+ t.test_files = FileList['test/*_test.rb']
56
+ t.ruby_opts += ['-rubygems'] if defined? Gem
57
+ end
58
+ task 'test:unit' => [:build]
59
+
60
+ desc 'Run conformance tests (MARKDOWN_TEST_VER=1.0)'
61
+ task 'test:conformance' => [:build] do |t|
62
+ script = "#{pwd}/bin/rdiscount"
63
+ test_version = ENV['MARKDOWN_TEST_VER'] || '1.0.3'
64
+ lib_dir = "#{pwd}/lib"
65
+ chdir("test/MarkdownTest_#{test_version}") do
66
+ sh "RUBYLIB=#{lib_dir} ./MarkdownTest.pl --script='#{script}' --tidy"
67
+ end
68
+ end
69
+
70
+ desc 'Run version 1.0 conformance suite'
71
+ task 'test:conformance:1.0' => [:build] do |t|
72
+ ENV['MARKDOWN_TEST_VER'] = '1.0'
73
+ Rake::Task['test:conformance'].invoke
74
+ end
75
+
76
+ desc 'Run 1.0.3 conformance suite'
77
+ task 'test:conformance:1.0.3' => [:build] do |t|
78
+ ENV['MARKDOWN_TEST_VER'] = '1.0.3'
79
+ Rake::Task['test:conformance'].invoke
80
+ end
81
+
82
+ desc 'Run unit and conformance tests'
83
+ task :test => %w[test:unit test:conformance]
84
+
85
+ desc 'Run benchmarks'
86
+ task :benchmark => :build do |t|
87
+ $:.unshift 'lib'
88
+ load 'test/benchmark.rb'
89
+ end
90
+
91
+ # ==========================================================
92
+ # Documentation
93
+ # ==========================================================
94
+
95
+ desc 'Generate API documentation'
96
+ task :doc => 'doc/index.html'
97
+
98
+ file 'doc/index.html' => FileList['lib/*.rb'] do |f|
99
+ sh((<<-end).gsub(/\s+/, ' '))
100
+ hanna --charset utf8 --fmt html --inline-source --line-numbers \
101
+ --main RDiscount --op doc --title 'RDiscount API Documentation' \
102
+ #{f.prerequisites.join(' ')}
103
+ end
104
+ end
105
+
106
+ CLEAN.include 'doc'
107
+
108
+ # ==========================================================
109
+ # Update package's Discount sources
110
+ # ==========================================================
111
+
112
+ desc 'Gather required discount sources into extension directory'
113
+ task :gather => 'discount/markdown.h' do |t|
114
+ files =
115
+ FileList[
116
+ 'discount/{markdown,mkdio,amalloc,cstring,tags}.h',
117
+ 'discount/{markdown,docheader,dumptree,generate,mkdio,resource,toc,Csio,xml,css,basename,emmatch,tags,html5}.c'
118
+ ]
119
+ cp files, 'ext/',
120
+ :preserve => true,
121
+ :verbose => true
122
+ cp 'discount/markdown.7', 'man/'
123
+ end
124
+
125
+ file 'discount/markdown.h' do |t|
126
+ abort "The discount submodule is required. See the file BUILDING for getting set up."
127
+ end
128
+
129
+ # PACKAGING =================================================================
130
+
131
+ require 'rubygems'
132
+ $spec = eval(File.read('rdiscount.gemspec'))
133
+
134
+ def package(ext='')
135
+ "pkg/rdiscount-#{$spec.version}" + ext
136
+ end
137
+
138
+ desc 'Build packages'
139
+ task :package => %w[.gem .tar.gz].map {|e| package(e)}
140
+
141
+ desc 'Build and install as local gem'
142
+ task :install => package('.gem') do
143
+ sh "gem install #{package('.gem')}"
144
+ end
145
+
146
+ directory 'pkg/'
147
+
148
+ file package('.gem') => %w[pkg/ rdiscount.gemspec] + $spec.files do |f|
149
+ sh "gem build rdiscount.gemspec"
150
+ mv File.basename(f.name), f.name
151
+ end
152
+
153
+ file package('.tar.gz') => %w[pkg/] + $spec.files do |f|
154
+ sh "git archive --format=tar HEAD | gzip > #{f.name}"
155
+ end
156
+
157
+ # GEMSPEC HELPERS ==========================================================
158
+
159
+ def source_version
160
+ line = File.read('lib/rdiscount.rb')[/^\s*VERSION = .*/]
161
+ line.match(/.*VERSION = '(.*)'/)[1]
162
+ end
163
+
164
+ file 'rdiscount.gemspec' => FileList['Rakefile','lib/rdiscount.rb'] do |f|
165
+ # read spec file and split out manifest section
166
+ spec = File.read(f.name)
167
+ head, manifest, tail = spec.split(" # = MANIFEST =\n")
168
+ head.sub!(/\.version = '.*'/, ".version = '#{source_version}'")
169
+ head.sub!(/\.date = '.*'/, ".date = '#{Date.today.to_s}'")
170
+ # determine file list from git ls-files
171
+ files = `git ls-files`.
172
+ split("\n").
173
+ sort.
174
+ reject{ |file| file =~ /^\./ || file =~ /^test\/MarkdownTest/ }.
175
+ map{ |file| " #{file}" }.
176
+ join("\n")
177
+ # piece file back together and write...
178
+ manifest = " s.files = %w[\n#{files}\n ]\n"
179
+ spec = [head,manifest,tail].join(" # = MANIFEST =\n")
180
+ File.open(f.name, 'w') { |io| io.write(spec) }
181
+ puts "updated #{f.name}"
182
+ end
data/bin/rdiscount ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # Usage: rdiscount [<file>...]
3
+ # Convert one or more Markdown files to HTML and write to standard output. With
4
+ # no <file> or when <file> is '-', read Markdown source text from standard input.
5
+ if ARGV.include?('--help')
6
+ File.read(__FILE__).split("\n").grep(/^# /).each do |line|
7
+ puts line[2..-1]
8
+ end
9
+ exit 0
10
+ end
11
+
12
+ require 'rdiscount'
13
+ STDOUT.write(RDiscount.new(ARGF.read).to_html)
data/ext/Csio.c ADDED
@@ -0,0 +1,61 @@
1
+ #include <stdio.h>
2
+ #include <string.h>
3
+ #include <stdarg.h>
4
+ #include "cstring.h"
5
+ #include "markdown.h"
6
+ #include "amalloc.h"
7
+
8
+
9
+ /* putc() into a cstring
10
+ */
11
+ void
12
+ Csputc(int c, Cstring *iot)
13
+ {
14
+ EXPAND(*iot) = c;
15
+ }
16
+
17
+
18
+ /* printf() into a cstring
19
+ */
20
+ int
21
+ Csprintf(Cstring *iot, char *fmt, ...)
22
+ {
23
+ va_list ptr;
24
+ int siz=100;
25
+
26
+ do {
27
+ RESERVE(*iot, siz);
28
+ va_start(ptr, fmt);
29
+ siz = vsnprintf(T(*iot)+S(*iot), ALLOCATED(*iot)-S(*iot), fmt, ptr);
30
+ va_end(ptr);
31
+ } while ( siz > (ALLOCATED(*iot)-S(*iot)) );
32
+
33
+ S(*iot) += siz;
34
+ return siz;
35
+ }
36
+
37
+
38
+ /* write() into a cstring
39
+ */
40
+ int
41
+ Cswrite(Cstring *iot, char *bfr, int size)
42
+ {
43
+ RESERVE(*iot, size);
44
+ memcpy(T(*iot)+S(*iot), bfr, size);
45
+ S(*iot) += size;
46
+ return size;
47
+ }
48
+
49
+
50
+ /* reparse() into a cstring
51
+ */
52
+ void
53
+ Csreparse(Cstring *iot, char *buf, int size, int flags)
54
+ {
55
+ MMIOT f;
56
+ ___mkd_initmmiot(&f, 0);
57
+ ___mkd_reparse(buf, size, 0, &f);
58
+ ___mkd_emblock(&f);
59
+ SUFFIX(*iot, T(f.out), S(f.out));
60
+ ___mkd_freemmiot(&f, 0);
61
+ }
data/ext/amalloc.h ADDED
@@ -0,0 +1,29 @@
1
+ /*
2
+ * debugging malloc()/realloc()/calloc()/free() that attempts
3
+ * to keep track of just what's been allocated today.
4
+ */
5
+ #ifndef AMALLOC_D
6
+ #define AMALLOC_D
7
+
8
+ #include "config.h"
9
+
10
+ #ifdef USE_AMALLOC
11
+
12
+ extern void *amalloc(int);
13
+ extern void *acalloc(int,int);
14
+ extern void *arealloc(void*,int);
15
+ extern void afree(void*);
16
+ extern void adump();
17
+
18
+ #define malloc amalloc
19
+ #define calloc acalloc
20
+ #define realloc arealloc
21
+ #define free afree
22
+
23
+ #else
24
+
25
+ #define adump() (void)1
26
+
27
+ #endif
28
+
29
+ #endif/*AMALLOC_D*/
data/ext/basename.c ADDED
@@ -0,0 +1,43 @@
1
+ /*
2
+ * mkdio -- markdown front end input functions
3
+ *
4
+ * Copyright (C) 2007 David L Parsons.
5
+ * The redistribution terms are provided in the COPYRIGHT file that must
6
+ * be distributed with this source code.
7
+ */
8
+ #include "config.h"
9
+ #include <stdio.h>
10
+ #include <stdlib.h>
11
+ #include <ctype.h>
12
+
13
+ #include "mkdio.h"
14
+ #include "cstring.h"
15
+ #include "amalloc.h"
16
+
17
+ static char *
18
+ e_basename(const char *string, const int size, void *context)
19
+ {
20
+ char *ret;
21
+ char *base = (char*)context;
22
+
23
+ if ( base && string && (*string == '/') && (ret=malloc(strlen(base)+size+2)) ) {
24
+ strcpy(ret, base);
25
+ strncat(ret, string, size);
26
+ return ret;
27
+ }
28
+ return 0;
29
+ }
30
+
31
+ static void
32
+ e_free(char *string, void *context)
33
+ {
34
+ if ( string ) free(string);
35
+ }
36
+
37
+ void
38
+ mkd_basename(MMIOT *document, char *base)
39
+ {
40
+ mkd_e_url(document, e_basename);
41
+ mkd_e_data(document, base);
42
+ mkd_e_free(document, e_free);
43
+ }
data/ext/config.h ADDED
@@ -0,0 +1,23 @@
1
+ /*
2
+ * rdiscount extension discount configuration
3
+ */
4
+ #ifndef __MARKDOWN_D
5
+ #define __MARKDOWN_D 1
6
+
7
+ /* tabs are four spaces */
8
+ #define TABSTOP 4
9
+
10
+ /* these are setup by extconf.rb */
11
+ #if HAVE_RANDOM
12
+ #define COINTOSS() (random()&1)
13
+ #elif HAVE_RAND
14
+ #define COINTOSS() (rand()&1)
15
+ #endif
16
+
17
+ #if HAVE_SRANDOM
18
+ #define INITRNG(x) srandom((unsigned int)x)
19
+ #elif HAVE_SRAND
20
+ #define INITRNG(x) srand((unsigned int)x)
21
+ #endif
22
+
23
+ #endif/* __MARKDOWN_D */
data/ext/css.c ADDED
@@ -0,0 +1,85 @@
1
+ /* markdown: a C implementation of John Gruber's Markdown markup language.
2
+ *
3
+ * Copyright (C) 2009 David L Parsons.
4
+ * The redistribution terms are provided in the COPYRIGHT file that must
5
+ * be distributed with this source code.
6
+ */
7
+ #include <stdio.h>
8
+ #include <string.h>
9
+ #include <stdarg.h>
10
+ #include <stdlib.h>
11
+ #include <time.h>
12
+ #include <ctype.h>
13
+
14
+ #include "config.h"
15
+
16
+ #include "cstring.h"
17
+ #include "markdown.h"
18
+ #include "amalloc.h"
19
+
20
+
21
+ /*
22
+ * dump out stylesheet sections.
23
+ */
24
+ static void
25
+ stylesheets(Paragraph *p, Cstring *f)
26
+ {
27
+ Line* q;
28
+
29
+ for ( ; p ; p = p->next ) {
30
+ if ( p->typ == STYLE ) {
31
+ for ( q = p->text; q ; q = q->next ) {
32
+ Cswrite(f, T(q->text), S(q->text));
33
+ Csputc('\n', f);
34
+ }
35
+ }
36
+ if ( p->down )
37
+ stylesheets(p->down, f);
38
+ }
39
+ }
40
+
41
+
42
+ /* dump any embedded styles to a string
43
+ */
44
+ int
45
+ mkd_css(Document *d, char **res)
46
+ {
47
+ Cstring f;
48
+ int size;
49
+
50
+ if ( res && d && d->compiled ) {
51
+ *res = 0;
52
+ CREATE(f);
53
+ RESERVE(f, 100);
54
+ stylesheets(d->code, &f);
55
+
56
+ if ( (size = S(f)) > 0 ) {
57
+ EXPAND(f) = 0;
58
+ /* HACK ALERT! HACK ALERT! HACK ALERT! */
59
+ *res = T(f);/* we know that a T(Cstring) is a character pointer */
60
+ /* so we can simply pick it up and carry it away, */
61
+ /* leaving the husk of the Ctring on the stack */
62
+ /* END HACK ALERT */
63
+ }
64
+ else
65
+ DELETE(f);
66
+ return size;
67
+ }
68
+ return EOF;
69
+ }
70
+
71
+
72
+ /* dump any embedded styles to a file
73
+ */
74
+ int
75
+ mkd_generatecss(Document *d, FILE *f)
76
+ {
77
+ char *res;
78
+ int written = EOF, size = mkd_css(d, &res);
79
+
80
+ if ( size > 0 )
81
+ written = fwrite(res, 1, size, f);
82
+ if ( res )
83
+ free(res);
84
+ return (written == size) ? size : EOF;
85
+ }
data/ext/cstring.h ADDED
@@ -0,0 +1,77 @@
1
+ /* two template types: STRING(t) which defines a pascal-style string
2
+ * of element (t) [STRING(char) is the closest to the pascal string],
3
+ * and ANCHOR(t) which defines a baseplate that a linked list can be
4
+ * built up from. [The linked list /must/ contain a ->next pointer
5
+ * for linking the list together with.]
6
+ */
7
+ #ifndef _CSTRING_D
8
+ #define _CSTRING_D
9
+
10
+ #include <string.h>
11
+ #include <stdlib.h>
12
+
13
+ #ifndef __WITHOUT_AMALLOC
14
+ # include "amalloc.h"
15
+ #endif
16
+
17
+ /* expandable Pascal-style string.
18
+ */
19
+ #define STRING(type) struct { type *text; int size, alloc; }
20
+
21
+ #define CREATE(x) ( (T(x) = (void*)0), (S(x) = (x).alloc = 0) )
22
+ #define EXPAND(x) (S(x)++)[(S(x) < (x).alloc) \
23
+ ? (T(x)) \
24
+ : (T(x) = T(x) ? realloc(T(x), sizeof T(x)[0] * ((x).alloc += 100)) \
25
+ : malloc(sizeof T(x)[0] * ((x).alloc += 100)) )]
26
+
27
+ #define DELETE(x) ALLOCATED(x) ? (free(T(x)), S(x) = (x).alloc = 0) \
28
+ : ( S(x) = 0 )
29
+ #define CLIP(t,i,sz) \
30
+ ( ((i) >= 0) && ((sz) > 0) && (((i)+(sz)) <= S(t)) ) ? \
31
+ (memmove(&T(t)[i], &T(t)[i+sz], (S(t)-(i+sz)+1)*sizeof(T(t)[0])), \
32
+ S(t) -= (sz)) : -1
33
+
34
+ #define RESERVE(x, sz) T(x) = ((x).alloc > S(x) + (sz) \
35
+ ? T(x) \
36
+ : T(x) \
37
+ ? realloc(T(x), sizeof T(x)[0] * ((x).alloc = 100+(sz)+S(x))) \
38
+ : malloc(sizeof T(x)[0] * ((x).alloc = 100+(sz)+S(x))))
39
+ #define SUFFIX(t,p,sz) \
40
+ memcpy(((S(t) += (sz)) - (sz)) + \
41
+ (T(t) = T(t) ? realloc(T(t), sizeof T(t)[0] * ((t).alloc += sz)) \
42
+ : malloc(sizeof T(t)[0] * ((t).alloc += sz))), \
43
+ (p), sizeof(T(t)[0])*(sz))
44
+
45
+ #define PREFIX(t,p,sz) \
46
+ RESERVE( (t), (sz) ); \
47
+ if ( S(t) ) { memmove(T(t)+(sz), T(t), S(t)); } \
48
+ memcpy( T(t), (p), (sz) ); \
49
+ S(t) += (sz)
50
+
51
+ /* reference-style links (and images) are stored in an array
52
+ */
53
+ #define T(x) (x).text
54
+ #define S(x) (x).size
55
+ #define ALLOCATED(x) (x).alloc
56
+
57
+ /* abstract anchor type that defines a list base
58
+ * with a function that attaches an element to
59
+ * the end of the list.
60
+ *
61
+ * the list base field is named .text so that the T()
62
+ * macro will work with it.
63
+ */
64
+ #define ANCHOR(t) struct { t *text, *end; }
65
+ #define E(t) ((t).end)
66
+
67
+ #define ATTACH(t, p) ( T(t) ? ( (E(t)->next = (p)), (E(t) = (p)) ) \
68
+ : ( (T(t) = E(t) = (p)) ) )
69
+
70
+ typedef STRING(char) Cstring;
71
+
72
+ extern void Csputc(int, Cstring *);
73
+ extern int Csprintf(Cstring *, char *, ...);
74
+ extern int Cswrite(Cstring *, char *, int);
75
+ extern void Csreparse(Cstring *, char *, int, int);
76
+
77
+ #endif/*_CSTRING_D*/