aboutsummaryrefslogtreecommitdiffstats
path: root/modules/yaml
diff options
context:
space:
mode:
Diffstat (limited to 'modules/yaml')
-rw-r--r--modules/yaml/Makefile.in15
-rw-r--r--modules/yaml/tests/alias.yaml14
-rw-r--r--modules/yaml/tests/map.yaml4
-rw-r--r--modules/yaml/tests/multi.yaml16
-rw-r--r--modules/yaml/tests/nest.yaml12
-rw-r--r--modules/yaml/tests/scal.yaml2
-rw-r--r--modules/yaml/tests/seq.yaml5
-rw-r--r--modules/yaml/yaml-test.el24
-rw-r--r--modules/yaml/yaml.c232
9 files changed, 324 insertions, 0 deletions
diff --git a/modules/yaml/Makefile.in b/modules/yaml/Makefile.in
new file mode 100644
index 00000000000..32f61e9df4f
--- /dev/null
+++ b/modules/yaml/Makefile.in
@@ -0,0 +1,15 @@
1ROOT = ../..
2
3CFLAGS = `pkg-config yaml-0.1 --cflags`
4LDFLAGS = `pkg-config yaml-0.1 --libs`
5
6all: yaml.so yaml.doc
7
8%.so: %.o
9 gcc -shared $(LDFLAGS) -o $@ $<
10
11%.o: %.c
12 gcc -ggdb3 -Wall -I$(ROOT)/src -I$(ROOT)/lib $(CFLAGS) -fPIC -c $<
13
14%.doc: %.c
15 $(ROOT)/lib-src/make-docfile $< > $@
diff --git a/modules/yaml/tests/alias.yaml b/modules/yaml/tests/alias.yaml
new file mode 100644
index 00000000000..c3dade3a011
--- /dev/null
+++ b/modules/yaml/tests/alias.yaml
@@ -0,0 +1,14 @@
1---
2invoice: 34843
3date : 2001-01-23
4bill-to: &id001
5 given : Chris
6 family : Dumars
7 address:
8 lines: |
9 458 Walkman Dr.
10 Suite #292
11 city : Royal Oak
12 state : MI
13 postal : 48046
14ship-to: *id001
diff --git a/modules/yaml/tests/map.yaml b/modules/yaml/tests/map.yaml
new file mode 100644
index 00000000000..4021d74248a
--- /dev/null
+++ b/modules/yaml/tests/map.yaml
@@ -0,0 +1,4 @@
1---
2a: 1
3b: 2
4c: 3
diff --git a/modules/yaml/tests/multi.yaml b/modules/yaml/tests/multi.yaml
new file mode 100644
index 00000000000..1eb61f7df3e
--- /dev/null
+++ b/modules/yaml/tests/multi.yaml
@@ -0,0 +1,16 @@
1---
2a: 1
3b:
4 - 1
5 - 2
6 - 3
7---
8foo:
9 bar: 1
10 baz: 2
11 bad: 3
12zob:
13 - 42
14 - 43
15---
16abc
diff --git a/modules/yaml/tests/nest.yaml b/modules/yaml/tests/nest.yaml
new file mode 100644
index 00000000000..8a453dfc771
--- /dev/null
+++ b/modules/yaml/tests/nest.yaml
@@ -0,0 +1,12 @@
1---
2product:
3 - sku : BL394D
4 quantity : 4
5 description : Basketball
6 price : 450.00
7 - sku : BL4438H
8 quantity : 1
9 description : Super Hoop
10 price : 2392.00
11tax : 251.42
12total: 4443.52
diff --git a/modules/yaml/tests/scal.yaml b/modules/yaml/tests/scal.yaml
new file mode 100644
index 00000000000..aecd198b598
--- /dev/null
+++ b/modules/yaml/tests/scal.yaml
@@ -0,0 +1,2 @@
1---
2abc
diff --git a/modules/yaml/tests/seq.yaml b/modules/yaml/tests/seq.yaml
new file mode 100644
index 00000000000..15b6a9e3dc0
--- /dev/null
+++ b/modules/yaml/tests/seq.yaml
@@ -0,0 +1,5 @@
1---
2- abc
3- def
4- ghi
5- jkl
diff --git a/modules/yaml/yaml-test.el b/modules/yaml/yaml-test.el
new file mode 100644
index 00000000000..5f9b5c0ef10
--- /dev/null
+++ b/modules/yaml/yaml-test.el
@@ -0,0 +1,24 @@
1
2(defun yaml-expand-file (file)
3 (if (not (string-match-p "/" file))
4 (expand-file-name
5 (concat "~/prog/c/emacs/dyn/modules/yaml/tests/" file))
6 file))
7
8(defun yaml-test-file (file)
9 (require 'yaml)
10 (require 'json)
11 (with-current-buffer (get-buffer-create "out")
12 (erase-buffer)
13 (insert (json-encode (yaml-parse-file (yaml-expand-file file))))
14 (json-pretty-print (point-min) (point-max))))
15
16(defun yaml-test-buffer (file)
17 (require 'yaml)
18 (require 'json)
19 (with-current-buffer (get-buffer-create "out")
20 (erase-buffer)
21 (insert (json-encode (with-temp-buffer
22 (insert-file-contents (yaml-expand-file file))
23 (yaml-parse))))
24 (json-pretty-print (point-min) (point-max))))
diff --git a/modules/yaml/yaml.c b/modules/yaml/yaml.c
new file mode 100644
index 00000000000..3ff133476ee
--- /dev/null
+++ b/modules/yaml/yaml.c
@@ -0,0 +1,232 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <yaml.h>
5
6
7#include <config.h>
8#include <lisp.h>
9
10#include <character.h> /* buffer.h needs it */
11#include <buffer.h>
12
13int plugin_is_GPL_compatible;
14static Lisp_Object Qyaml;
15
16typedef unsigned char uchar;
17
18struct context
19{
20 yaml_parser_t p;
21 int error;
22 Lisp_Object anchors; /* hashtable mapping alias to values */
23};
24
25static Lisp_Object parse_scalar (struct context *ctx, yaml_event_t *e);
26static Lisp_Object parse_sequence (struct context *ctx, yaml_event_t *e);
27static Lisp_Object parse_mapping (struct context *ctx, yaml_event_t *e);
28
29static Lisp_Object
30parse_element (struct context *ctx)
31{
32 Lisp_Object res = Qnil;
33 yaml_event_t e;
34
35 redo:
36 yaml_parser_parse (&ctx->p, &e);
37 const char *s = (char*)e.data.alias.anchor;
38
39 switch (e.type)
40 {
41 case YAML_STREAM_START_EVENT:
42 /* a stream is a sequence of documents */
43 res = parse_sequence (ctx, &e);
44 break;
45
46 case YAML_DOCUMENT_START_EVENT:
47 case YAML_DOCUMENT_END_EVENT:
48 /* keep reading */
49 yaml_event_delete (&e);
50 goto redo;
51
52 case YAML_ALIAS_EVENT:
53 res = Fgethash (make_string (s, strlen (s)), ctx->anchors, Qnil);
54 break;
55
56 case YAML_SCALAR_EVENT:
57 res = parse_scalar (ctx, &e);
58 if (s)
59 Fputhash (make_string (s, strlen (s)), res, ctx->anchors);
60 break;
61
62 case YAML_SEQUENCE_START_EVENT:
63 res = parse_sequence (ctx, &e);
64 if (s)
65 Fputhash (make_string (s, strlen (s)), res, ctx->anchors);
66 break;
67
68 case YAML_MAPPING_START_EVENT:
69 res = parse_mapping (ctx, &e);
70 if (s)
71 Fputhash (make_string (s, strlen (s)), res, ctx->anchors);
72 break;
73
74 case YAML_NO_EVENT:
75 case YAML_MAPPING_END_EVENT:
76 case YAML_SEQUENCE_END_EVENT:
77 case YAML_STREAM_END_EVENT:
78 res = Qnil;
79 break;
80 }
81
82 yaml_event_delete (&e);
83 return res;
84}
85
86static Lisp_Object
87parse_scalar (struct context *ctx, yaml_event_t *e)
88{
89 return make_string ((char*)e->data.scalar.value, e->data.scalar.length);
90}
91
92static Lisp_Object
93parse_sequence (struct context *ctx, yaml_event_t *e)
94{
95 /* always >= 1 elements in sequence */
96 Lisp_Object cons = Fcons (parse_element (ctx), Qnil);
97 Lisp_Object res = cons;
98
99 while (1)
100 {
101 Lisp_Object e = parse_element (ctx);
102
103 if (NILP (e))
104 break;
105
106 XSETCDR (cons, Fcons(e, Qnil));
107 cons = XCDR (cons);
108 }
109
110 return res;
111}
112
113static Lisp_Object
114parse_mapping (struct context *ctx, yaml_event_t *e)
115{
116 Lisp_Object args[2];
117 args[0] = QCtest;
118 args[1] = Qequal;
119 Lisp_Object res = Fmake_hash_table (2, args);
120
121 while (1)
122 {
123 Lisp_Object key = parse_element (ctx);
124
125 if (NILP (key))
126 break;
127
128 Lisp_Object val = parse_element (ctx);
129
130 Fputhash (key, val, res);
131 }
132
133 return res;
134}
135
136static void
137context_init (struct context *ctx)
138{
139 memset (ctx, 0, sizeof (*ctx));
140 Lisp_Object args[2];
141 args[0] = QCtest;
142 args[1] = Qequal;
143 ctx->anchors = Fmake_hash_table (2, args);
144}
145
146EXFUN (Fyaml_parse_string, 1);
147DEFUN ("yaml-parse-string", Fyaml_parse_string, Syaml_parse_string, 1, 1, 0,
148 doc: "Parse STRING as yaml.")
149 (Lisp_Object string)
150{
151 struct context ctx;
152 Lisp_Object res = Qnil;
153
154 context_init (&ctx);
155
156 yaml_parser_initialize (&ctx.p);
157 yaml_parser_set_input_string (&ctx.p, SDATA (string), SBYTES (string));
158 res = parse_element (&ctx);
159 yaml_parser_delete (&ctx.p);
160
161 return res;
162}
163
164
165EXFUN (Fyaml_parse_buffer, 0);
166DEFUN ("yaml-parse-buffer", Fyaml_parse_buffer, Syaml_parse_buffer, 0, 0, 0,
167 doc: "Parse current buffer as yaml.")
168 (void)
169{
170 struct context ctx;
171 Lisp_Object res = Qnil;
172
173 context_init (&ctx);
174
175 yaml_parser_initialize (&ctx.p);
176 yaml_parser_set_input_string (&ctx.p, BYTE_POS_ADDR (BEGV_BYTE), ZV_BYTE - BEGV_BYTE);
177 res = parse_element (&ctx);
178 yaml_parser_delete (&ctx.p);
179
180 return res;
181}
182
183
184EXFUN (Fyaml_parse_file, 1);
185DEFUN ("yaml-parse-file", Fyaml_parse_file, Syaml_parse_file, 1, 1, 0,
186 doc: "Parse FILE as yaml.")
187 (Lisp_Object file)
188{
189 struct gcpro gcpro1;
190 struct context ctx;
191
192 context_init (&ctx);
193
194 int r;
195 FILE *fh;
196 Lisp_Object res = Qnil;
197
198 fh = fopen((char*)SDATA (file), "r");
199
200 if (!fh)
201 goto out;
202
203 r = yaml_parser_initialize (&ctx.p);
204
205 if (!r)
206 goto out_close;
207
208 yaml_parser_set_input_file (&ctx.p, fh);
209
210 GCPRO1 (ctx.anchors);
211 res = parse_element (&ctx);
212 UNGCPRO;
213
214 yaml_parser_delete (&ctx.p);
215
216 out_close:
217 fclose (fh);
218
219 out:
220 return res;
221}
222
223void init ()
224{
225 DEFSYM (Qyaml, "yaml");
226
227 defsubr (&Syaml_parse_file);
228 defsubr (&Syaml_parse_string);
229 defsubr (&Syaml_parse_buffer);
230
231 Fprovide (Qyaml, Qnil);
232}