1 /************************************************************************
2 *
3 * Copyright 2012 Jonatan Liljedahl <lijon@kymatica.com>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 ************************************************************************/
19
20 #include "GC.h"
21 #include "PyrKernel.h"
22 #include "PyrPrimitive.h"
23 #include "PyrSymbol.h"
24 #include "SCBase.h"
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdarg.h>
29 #include <cerrno>
30
31 // extern "C" {
32 #include "SCDoc.h"
33 //}
34
35 PyrSymbol* s_scdoc_node;
36
_doc_traverse(struct VMGlobals * g,DocNode * n,PyrObject * parent,PyrSlot * slot)37 static void _doc_traverse(struct VMGlobals* g, DocNode* n, PyrObject* parent, PyrSlot* slot) {
38 PyrObject* result = instantiateObject(g->gc, s_scdoc_node->u.classobj, 0, false, true);
39 SetObject(slot, result);
40 if (parent) {
41 assert(isKindOf(parent, class_array));
42 g->gc->GCWriteNew(parent, result); // we know result is white so we can use GCWriteNew
43 parent->size++;
44 }
45
46 // initialise the instance vars
47 PyrSymbol* id = getsym(n->id);
48 SetSymbol(result->slots, id); // id
49
50 // text
51 if (n->text) {
52 PyrObject* str = (PyrObject*)newPyrString(g->gc, n->text, 0, true);
53 SetObject(result->slots + 1, str);
54 g->gc->GCWriteNew(result, str); // we know str is white so we can use GCWriteNew
55 }
56
57 // children
58 if (n->n_childs) {
59 PyrObject* array = newPyrArray(g->gc, n->n_childs, 0, true);
60 SetObject(result->slots + 2, array);
61 g->gc->GCWriteNew(result, array); // we know array is white so we can use GCWriteNew
62 for (int i = 0; i < n->n_childs; i++) {
63 _doc_traverse(g, n->children[i], array, array->slots + i);
64 }
65 }
66 // makeDiv, notPrivOnly, sort remain nil for now
67 }
68
69
prSCDoc_ParseFile(struct VMGlobals * g,int numArgsPushed)70 int prSCDoc_ParseFile(struct VMGlobals* g, int numArgsPushed) {
71 PyrSlot *a, *b, *c;
72 char filename[PATH_MAX];
73 int mode, err;
74
75 a = g->sp - 2;
76 b = g->sp - 1;
77 c = g->sp;
78
79 err = slotStrVal(b, filename, PATH_MAX);
80 if (err)
81 return err;
82
83 err = slotIntVal(c, &mode);
84 if (err)
85 return err;
86
87 DocNode* n = scdoc_parse_file(filename, mode);
88 if (n) {
89 // doc_node_dump(n);
90 _doc_traverse(g, n, NULL, a);
91 doc_node_free_tree(n);
92 } else {
93 SetNil(a);
94 }
95 return errNone;
96 }
97
initSCDocPrimitives()98 void initSCDocPrimitives() {
99 int base, index = 0;
100
101 s_scdoc_node = getsym("SCDocNode");
102
103 base = nextPrimitiveIndex();
104
105 definePrimitive(base, index++, "_SCDoc_ParseFile", prSCDoc_ParseFile, 3, 0);
106 }
107