diff options
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/.gitignore | 2 | ||||
| -rw-r--r-- | modules/ChangeLog | 11 | ||||
| -rw-r--r-- | modules/curl/Makefile.in | 15 | ||||
| -rw-r--r-- | modules/curl/curl.c | 118 | ||||
| -rw-r--r-- | modules/elisp/Makefile.in | 12 | ||||
| -rw-r--r-- | modules/elisp/elisp.c | 38 | ||||
| -rw-r--r-- | modules/fmod/Makefile.in | 12 | ||||
| -rw-r--r-- | modules/fmod/fmod.c | 60 | ||||
| -rw-r--r-- | modules/opaque/Makefile.in | 12 | ||||
| -rw-r--r-- | modules/opaque/opaque.c | 64 | ||||
| -rw-r--r-- | modules/yaml/Makefile.in | 15 | ||||
| -rw-r--r-- | modules/yaml/tests/alias.yaml | 14 | ||||
| -rw-r--r-- | modules/yaml/tests/map.yaml | 4 | ||||
| -rw-r--r-- | modules/yaml/tests/multi.yaml | 16 | ||||
| -rw-r--r-- | modules/yaml/tests/nest.yaml | 12 | ||||
| -rw-r--r-- | modules/yaml/tests/scal.yaml | 2 | ||||
| -rw-r--r-- | modules/yaml/tests/seq.yaml | 5 | ||||
| -rw-r--r-- | modules/yaml/yaml-test.el | 24 | ||||
| -rw-r--r-- | modules/yaml/yaml.c | 232 |
19 files changed, 668 insertions, 0 deletions
diff --git a/modules/.gitignore b/modules/.gitignore new file mode 100644 index 00000000000..fc15e0a56d7 --- /dev/null +++ b/modules/.gitignore | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | */*.doc | ||
| 2 | */*.so | ||
diff --git a/modules/ChangeLog b/modules/ChangeLog new file mode 100644 index 00000000000..180d48e5bc4 --- /dev/null +++ b/modules/ChangeLog | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | 2014-12-02 Aurélien Aptel <aurelien.aptel@gmail.com> | ||
| 2 | |||
| 3 | * curl: Add new module. | ||
| 4 | |||
| 5 | * elisp: Add new module. | ||
| 6 | |||
| 7 | * fmod: Add new module. | ||
| 8 | |||
| 9 | * yaml: Add new module. | ||
| 10 | |||
| 11 | * opaque: Add new module. | ||
diff --git a/modules/curl/Makefile.in b/modules/curl/Makefile.in new file mode 100644 index 00000000000..2e7fda08bae --- /dev/null +++ b/modules/curl/Makefile.in | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | ROOT = ../.. | ||
| 2 | |||
| 3 | CFLAGS = `pkg-config libcurl --cflags` | ||
| 4 | LDFLAGS = `pkg-config libcurl --libs` | ||
| 5 | |||
| 6 | all: curl.so curl.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/curl/curl.c b/modules/curl/curl.c new file mode 100644 index 00000000000..b8b2bb63a44 --- /dev/null +++ b/modules/curl/curl.c | |||
| @@ -0,0 +1,118 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include <stdlib.h> | ||
| 3 | #include <string.h> | ||
| 4 | #include <curl/curl.h> | ||
| 5 | |||
| 6 | #include <config.h> | ||
| 7 | #include <lisp.h> | ||
| 8 | |||
| 9 | int plugin_is_GPL_compatible; | ||
| 10 | static Lisp_Object Qcurl; | ||
| 11 | |||
| 12 | struct buffer | ||
| 13 | { | ||
| 14 | char *p; | ||
| 15 | size_t size, capacity; | ||
| 16 | }; | ||
| 17 | |||
| 18 | struct Lisp_CURL | ||
| 19 | { | ||
| 20 | struct buffer buf; | ||
| 21 | CURL *curl; | ||
| 22 | }; | ||
| 23 | |||
| 24 | #define XCURL(x) ((struct Lisp_CURL*)XSAVE_POINTER (x, 0)) | ||
| 25 | |||
| 26 | /* curl write callback */ | ||
| 27 | static size_t | ||
| 28 | write_cb (void *src, size_t size, size_t nb, void *userp) | ||
| 29 | { | ||
| 30 | struct buffer *buf = userp; | ||
| 31 | size_t total = size*nb; | ||
| 32 | |||
| 33 | if (buf->size + total > buf->capacity) | ||
| 34 | { | ||
| 35 | buf->capacity = 2 * (buf->size + total); | ||
| 36 | buf->p = realloc (buf->p, buf->capacity); | ||
| 37 | } | ||
| 38 | |||
| 39 | memcpy (buf->p + buf->size, src, total); | ||
| 40 | buf->size += total; | ||
| 41 | buf->p[buf->size] = 0; | ||
| 42 | |||
| 43 | return total; | ||
| 44 | } | ||
| 45 | |||
| 46 | |||
| 47 | EXFUN (Fcurl_make, 0); | ||
| 48 | DEFUN ("curl-make", Fcurl_make, Scurl_make, 0, 0, 0, | ||
| 49 | doc: "Return a new CURL handle.") | ||
| 50 | (void) | ||
| 51 | { | ||
| 52 | struct Lisp_CURL *p = calloc (sizeof (*p), 1); | ||
| 53 | p->buf.p = calloc (1, 1); /* so that realloc always work */ | ||
| 54 | p->buf.capacity = 0; | ||
| 55 | p->curl = curl_easy_init (); | ||
| 56 | return make_save_ptr ((void*)p); | ||
| 57 | } | ||
| 58 | |||
| 59 | |||
| 60 | EXFUN (Fcurl_fetch_url, 2); | ||
| 61 | DEFUN ("curl-fetch-url", Fcurl_fetch_url, Scurl_fetch_url, 2, 2, 0, | ||
| 62 | doc: "Fetch and store the content of URL using HANDLE.\n" | ||
| 63 | "Return t if successful otherwise return an error string.") | ||
| 64 | (Lisp_Object handle, Lisp_Object url) | ||
| 65 | { | ||
| 66 | CURLcode res; | ||
| 67 | struct Lisp_CURL *c = XCURL (handle); | ||
| 68 | |||
| 69 | curl_easy_setopt (c->curl, CURLOPT_URL, SSDATA (url)); | ||
| 70 | curl_easy_setopt (c->curl, CURLOPT_WRITEFUNCTION, write_cb); | ||
| 71 | curl_easy_setopt (c->curl, CURLOPT_WRITEDATA, (void*)&c->buf); | ||
| 72 | curl_easy_setopt (c->curl, CURLOPT_USERAGENT, "curl-in-emacs/1.0"); | ||
| 73 | res = curl_easy_perform (c->curl); | ||
| 74 | |||
| 75 | if (res != CURLE_OK) | ||
| 76 | { | ||
| 77 | const char* error = curl_easy_strerror (res); | ||
| 78 | return make_string (error, strlen (error)); | ||
| 79 | } | ||
| 80 | |||
| 81 | return Qt; | ||
| 82 | } | ||
| 83 | |||
| 84 | EXFUN (Fcurl_content, 1); | ||
| 85 | DEFUN ("curl-content", Fcurl_content, Scurl_content, 1, 1, 0, | ||
| 86 | doc: "Return the content of a successful fetch made in HANDLE.") | ||
| 87 | (Lisp_Object handle) | ||
| 88 | { | ||
| 89 | struct Lisp_CURL *c = XCURL (handle); | ||
| 90 | return make_string (c->buf.p, c->buf.size); | ||
| 91 | } | ||
| 92 | |||
| 93 | EXFUN (Fcurl_free, 1); | ||
| 94 | DEFUN ("curl-free", Fcurl_free, Scurl_free, 1, 1, 0, | ||
| 95 | doc: "Free curl HANDLE.") | ||
| 96 | (Lisp_Object handle) | ||
| 97 | { | ||
| 98 | struct Lisp_CURL *c = XCURL (handle); | ||
| 99 | free (c->buf.p); | ||
| 100 | curl_easy_cleanup (c->curl); | ||
| 101 | |||
| 102 | return Qt; | ||
| 103 | } | ||
| 104 | |||
| 105 | void init () | ||
| 106 | { | ||
| 107 | curl_global_init (CURL_GLOBAL_ALL); | ||
| 108 | /* when unloading: curl_global_cleanup(); */ | ||
| 109 | |||
| 110 | DEFSYM (Qcurl, "curl"); | ||
| 111 | |||
| 112 | defsubr (&Scurl_make); | ||
| 113 | defsubr (&Scurl_fetch_url); | ||
| 114 | defsubr (&Scurl_content); | ||
| 115 | defsubr (&Scurl_free); | ||
| 116 | |||
| 117 | Fprovide (Qcurl, Qnil); | ||
| 118 | } | ||
diff --git a/modules/elisp/Makefile.in b/modules/elisp/Makefile.in new file mode 100644 index 00000000000..8df325e76b7 --- /dev/null +++ b/modules/elisp/Makefile.in | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | ROOT = ../.. | ||
| 2 | |||
| 3 | all: elisp.so elisp.doc | ||
| 4 | |||
| 5 | %.so: %.o | ||
| 6 | gcc -shared -o $@ $< | ||
| 7 | |||
| 8 | %.o: %.c | ||
| 9 | gcc -ggdb3 -Wall -I$(ROOT)/src -I$(ROOT)/lib -fPIC -c $< | ||
| 10 | |||
| 11 | %.doc: %.c | ||
| 12 | $(ROOT)/lib-src/make-docfile $< > $@ | ||
diff --git a/modules/elisp/elisp.c b/modules/elisp/elisp.c new file mode 100644 index 00000000000..aabb24e01c6 --- /dev/null +++ b/modules/elisp/elisp.c | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | #include <string.h> | ||
| 2 | #include <config.h> | ||
| 3 | #include <lisp.h> | ||
| 4 | |||
| 5 | int plugin_is_GPL_compatible; | ||
| 6 | |||
| 7 | static Lisp_Object Qelisp, Qreplace_regexp_in_string; | ||
| 8 | |||
| 9 | #define MAKE_STRING(s) (make_string (s, sizeof(s)-1)) | ||
| 10 | |||
| 11 | EXFUN (Felisp_test, 0); | ||
| 12 | DEFUN ("elisp-test", Felisp_test, Selisp_test, 0, 0, 0, | ||
| 13 | doc: "Eval some lisp.") | ||
| 14 | (void) | ||
| 15 | { | ||
| 16 | Lisp_Object string = MAKE_STRING ("no-more-dash"); | ||
| 17 | Lisp_Object regex = MAKE_STRING ("[-]"); | ||
| 18 | Lisp_Object replace = MAKE_STRING (" "); | ||
| 19 | Lisp_Object res; | ||
| 20 | |||
| 21 | struct gcpro gcpro1, gcpro2, gcpro3; | ||
| 22 | GCPRO3 (string, regex, replace); | ||
| 23 | res = call3 (Qreplace_regexp_in_string, regex, replace, string); | ||
| 24 | UNGCPRO; | ||
| 25 | |||
| 26 | return res; | ||
| 27 | } | ||
| 28 | |||
| 29 | |||
| 30 | void init () | ||
| 31 | { | ||
| 32 | DEFSYM (Qelisp, "elisp"); | ||
| 33 | DEFSYM (Qreplace_regexp_in_string, "replace-regexp-in-string"); | ||
| 34 | |||
| 35 | defsubr (&Selisp_test); | ||
| 36 | |||
| 37 | Fprovide (Qelisp, Qnil); | ||
| 38 | } | ||
diff --git a/modules/fmod/Makefile.in b/modules/fmod/Makefile.in new file mode 100644 index 00000000000..ad9016a1cee --- /dev/null +++ b/modules/fmod/Makefile.in | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | ROOT = ../.. | ||
| 2 | |||
| 3 | all: fmod.so fmod.doc | ||
| 4 | |||
| 5 | %.so: %.o | ||
| 6 | gcc -shared -o $@ $< | ||
| 7 | |||
| 8 | %.o: %.c | ||
| 9 | gcc -ggdb3 -Wall -I$(ROOT)/src -I$(ROOT)/lib -fPIC -c $< | ||
| 10 | |||
| 11 | %.doc: %.c | ||
| 12 | $(ROOT)/lib-src/make-docfile $< > $@ | ||
diff --git a/modules/fmod/fmod.c b/modules/fmod/fmod.c new file mode 100644 index 00000000000..57da6168ae2 --- /dev/null +++ b/modules/fmod/fmod.c | |||
| @@ -0,0 +1,60 @@ | |||
| 1 | #include <config.h> | ||
| 2 | #include <lisp.h> | ||
| 3 | |||
| 4 | #include <math.h> | ||
| 5 | |||
| 6 | /* emacs checks for this symbol before running the module */ | ||
| 7 | |||
| 8 | int plugin_is_GPL_compatible; | ||
| 9 | |||
| 10 | /* module feature name */ | ||
| 11 | static Lisp_Object Qfmod; | ||
| 12 | |||
| 13 | /* define a new lisp function */ | ||
| 14 | |||
| 15 | EXFUN (Ffmod, 2); | ||
| 16 | DEFUN ("fmod", Ffmod, Sfmod, 2, 2, 0, | ||
| 17 | doc: "Returns the floating-point remainder of NUMER/DENOM") | ||
| 18 | (Lisp_Object numer, Lisp_Object denom) | ||
| 19 | { | ||
| 20 | return make_float (fmod (extract_float (numer), extract_float (denom))); | ||
| 21 | } | ||
| 22 | |||
| 23 | EXFUN (Ffmod_test1, 0); | ||
| 24 | DEFUN ("fmod-test1", Ffmod_test1, Sfmod_test1, 0, 0, 0, | ||
| 25 | doc: "Return 1") | ||
| 26 | (void) | ||
| 27 | { | ||
| 28 | return make_float (1.); | ||
| 29 | } | ||
| 30 | |||
| 31 | EXFUN (Ffmod_test2, 0); | ||
| 32 | DEFUN ("fmod-test2", Ffmod_test2, Sfmod_test2, 0, 0, 0, | ||
| 33 | doc: "Return 2") | ||
| 34 | (void) | ||
| 35 | { | ||
| 36 | return make_float (2.); | ||
| 37 | } | ||
| 38 | |||
| 39 | |||
| 40 | EXFUN (Ffmod_test3, 0); | ||
| 41 | DEFUN ("fmod-test3", Ffmod_test3, Sfmod_test3, 0, 0, 0, | ||
| 42 | doc: "Return 3") | ||
| 43 | (void) | ||
| 44 | { | ||
| 45 | return make_float (3.); | ||
| 46 | } | ||
| 47 | |||
| 48 | /* entry point of the module */ | ||
| 49 | |||
| 50 | void init () | ||
| 51 | { | ||
| 52 | DEFSYM (Qfmod, "fmod"); | ||
| 53 | |||
| 54 | defsubr (&Sfmod); | ||
| 55 | defsubr (&Sfmod_test1); | ||
| 56 | defsubr (&Sfmod_test2); | ||
| 57 | defsubr (&Sfmod_test3); | ||
| 58 | |||
| 59 | Fprovide (Qfmod, Qnil); | ||
| 60 | } | ||
diff --git a/modules/opaque/Makefile.in b/modules/opaque/Makefile.in new file mode 100644 index 00000000000..7f507326cfe --- /dev/null +++ b/modules/opaque/Makefile.in | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | ROOT = ../.. | ||
| 2 | |||
| 3 | all: opaque.so opaque.doc | ||
| 4 | |||
| 5 | %.so: %.o | ||
| 6 | gcc -shared -o $@ $< | ||
| 7 | |||
| 8 | %.o: %.c | ||
| 9 | gcc -ggdb3 -Wall -I$(ROOT)/src -I$(ROOT)/lib -fPIC -c $< | ||
| 10 | |||
| 11 | %.doc: %.c | ||
| 12 | $(ROOT)/lib-src/make-docfile $< > $@ | ||
diff --git a/modules/opaque/opaque.c b/modules/opaque/opaque.c new file mode 100644 index 00000000000..2366b2ed2e9 --- /dev/null +++ b/modules/opaque/opaque.c | |||
| @@ -0,0 +1,64 @@ | |||
| 1 | #include <config.h> | ||
| 2 | #include <lisp.h> | ||
| 3 | |||
| 4 | int plugin_is_GPL_compatible; | ||
| 5 | static Lisp_Object Qopaque; | ||
| 6 | |||
| 7 | struct opaque | ||
| 8 | { | ||
| 9 | int a, b, c; | ||
| 10 | }; | ||
| 11 | |||
| 12 | static Lisp_Object Qa, Qb, Qc; | ||
| 13 | |||
| 14 | EXFUN (Fopaque_make, 3); | ||
| 15 | DEFUN ("opaque-make", Fopaque_make, Sopaque_make, 3, 3, 0, | ||
| 16 | doc: "Make opaque type.") | ||
| 17 | (Lisp_Object a, Lisp_Object b, Lisp_Object c) | ||
| 18 | { | ||
| 19 | struct opaque *p = malloc (sizeof (*p)); | ||
| 20 | p->a = XINT (a); | ||
| 21 | p->b = XINT (b); | ||
| 22 | p->c = XINT (c); | ||
| 23 | |||
| 24 | /* | ||
| 25 | store p as a the first slot (index 0) of a Lisp_Save_Value (which | ||
| 26 | is a Lisp_Misc) | ||
| 27 | */ | ||
| 28 | return make_save_ptr ((void*)p); | ||
| 29 | } | ||
| 30 | |||
| 31 | EXFUN (Fopaque_free, 1); | ||
| 32 | DEFUN ("opaque-free", Fopaque_free, Sopaque_free, 1, 1, 0, | ||
| 33 | doc: "Free opaque object OBJ.") | ||
| 34 | (Lisp_Object obj) | ||
| 35 | { | ||
| 36 | /* the pointer is in the first slot (index 0) */ | ||
| 37 | free (XSAVE_POINTER (obj, 0)); | ||
| 38 | return Qnil; | ||
| 39 | } | ||
| 40 | |||
| 41 | EXFUN (Fopaque_get, 2); | ||
| 42 | DEFUN ("opaque-get", Fopaque_get, Sopaque_get, 2, 2, 0, | ||
| 43 | doc: "Return the field F (`a', `b', `c') of the opaque object OBJ.") | ||
| 44 | (Lisp_Object obj, Lisp_Object f) | ||
| 45 | { | ||
| 46 | struct opaque *p = XSAVE_POINTER (obj, 0); | ||
| 47 | int val = EQ (f, Qa) ? p->a : EQ (f, Qb) ? p->b : EQ (f, Qc) ? p->c : -1; | ||
| 48 | return make_number (val); | ||
| 49 | } | ||
| 50 | |||
| 51 | void init () | ||
| 52 | { | ||
| 53 | DEFSYM (Qopaque, "opaque"); | ||
| 54 | |||
| 55 | DEFSYM (Qa, "a"); | ||
| 56 | DEFSYM (Qb, "b"); | ||
| 57 | DEFSYM (Qc, "c"); | ||
| 58 | |||
| 59 | defsubr (&Sopaque_make); | ||
| 60 | defsubr (&Sopaque_free); | ||
| 61 | defsubr (&Sopaque_get); | ||
| 62 | |||
| 63 | Fprovide (Qopaque, Qnil); | ||
| 64 | } | ||
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 @@ | |||
| 1 | ROOT = ../.. | ||
| 2 | |||
| 3 | CFLAGS = `pkg-config yaml-0.1 --cflags` | ||
| 4 | LDFLAGS = `pkg-config yaml-0.1 --libs` | ||
| 5 | |||
| 6 | all: 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 | --- | ||
| 2 | invoice: 34843 | ||
| 3 | date : 2001-01-23 | ||
| 4 | bill-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 | ||
| 14 | ship-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 | --- | ||
| 2 | a: 1 | ||
| 3 | b: 2 | ||
| 4 | c: 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 | --- | ||
| 2 | a: 1 | ||
| 3 | b: | ||
| 4 | - 1 | ||
| 5 | - 2 | ||
| 6 | - 3 | ||
| 7 | --- | ||
| 8 | foo: | ||
| 9 | bar: 1 | ||
| 10 | baz: 2 | ||
| 11 | bad: 3 | ||
| 12 | zob: | ||
| 13 | - 42 | ||
| 14 | - 43 | ||
| 15 | --- | ||
| 16 | abc | ||
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 | --- | ||
| 2 | product: | ||
| 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 | ||
| 11 | tax : 251.42 | ||
| 12 | total: 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 | --- | ||
| 2 | abc | ||
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 | |||
| 13 | int plugin_is_GPL_compatible; | ||
| 14 | static Lisp_Object Qyaml; | ||
| 15 | |||
| 16 | typedef unsigned char uchar; | ||
| 17 | |||
| 18 | struct context | ||
| 19 | { | ||
| 20 | yaml_parser_t p; | ||
| 21 | int error; | ||
| 22 | Lisp_Object anchors; /* hashtable mapping alias to values */ | ||
| 23 | }; | ||
| 24 | |||
| 25 | static Lisp_Object parse_scalar (struct context *ctx, yaml_event_t *e); | ||
| 26 | static Lisp_Object parse_sequence (struct context *ctx, yaml_event_t *e); | ||
| 27 | static Lisp_Object parse_mapping (struct context *ctx, yaml_event_t *e); | ||
| 28 | |||
| 29 | static Lisp_Object | ||
| 30 | parse_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 | |||
| 86 | static Lisp_Object | ||
| 87 | parse_scalar (struct context *ctx, yaml_event_t *e) | ||
| 88 | { | ||
| 89 | return make_string ((char*)e->data.scalar.value, e->data.scalar.length); | ||
| 90 | } | ||
| 91 | |||
| 92 | static Lisp_Object | ||
| 93 | parse_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 | |||
| 113 | static Lisp_Object | ||
| 114 | parse_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 | |||
| 136 | static void | ||
| 137 | context_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 | |||
| 146 | EXFUN (Fyaml_parse_string, 1); | ||
| 147 | DEFUN ("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 | |||
| 165 | EXFUN (Fyaml_parse_buffer, 0); | ||
| 166 | DEFUN ("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 | |||
| 184 | EXFUN (Fyaml_parse_file, 1); | ||
| 185 | DEFUN ("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 | |||
| 223 | void 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 | } | ||