DiskIn help: prioritise object-style example over OSC example
[supercollider.git] / SCDoc / SCDoc.cpp
blobeadf69fbe474d758aa0519fd5689dfd3c65baa61
1 /************************************************************************
3 * Copyright 2012 Jonatan Liljedahl <lijon@kymatica.com>
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 3 of the License, or
8 * (at your option) any later version.
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.
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/>.
18 ************************************************************************/
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <ctype.h>
24 #include "SCDoc.h"
26 DocNode * scdoc_parse_run(int partial);
27 void scdocrestart (FILE *input_file);
28 int scdoclex_destroy(void);
30 char * scdoc_current_file = NULL;
32 static int doc_node_dump_level_done[32] = {0,};
34 // merge a+b and free b
35 char *strmerge(char *a, char *b) {
36 if(a==NULL) return b;
37 if(b==NULL) return a;
38 char *s = (char *)realloc(a,strlen(a)+strlen(b)+1);
39 strcat(s,b);
40 free(b);
41 return s;
44 static char *striptrailingws(char *s) {
45 char *s2 = strchr(s,0);
46 while(--s2 > s && isspace(*s2)) {
47 *s2 = 0;
49 return s;
52 DocNode * doc_node_create(const char *id) {
53 DocNode *n = (DocNode *)malloc(sizeof(DocNode));
54 n->id = id;
55 n->text = NULL;
56 n->n_childs = 0;
57 n->children = NULL;
58 return n;
61 // takes ownership of child
62 DocNode * doc_node_add_child(DocNode *n, DocNode *child) {
63 if(child) {
64 n->children = (DocNode **)realloc(n->children, (n->n_childs+1) * sizeof(DocNode*));
65 n->children[n->n_childs] = child;
66 n->n_childs++;
68 return n;
71 // takes ownership of text
72 /*DocNode * doc_node_add_text(DocNode *n, char *text) {
73 if(n->text) {
74 char *str = strmergefree(n->text,text);
75 n->text = str;
76 printf("NODE: Adding text '%s'\n",text);
77 } else {
78 n->text = text;
80 return n;
81 }*/
83 // moves the childs from src doc_node to n
84 void doc_node_move_children(DocNode *n, DocNode *src) {
85 if(src) {
86 free(n->children);
87 n->children = src->children;
88 n->n_childs = src->n_childs;
89 // src->children = NULL;
90 // src->n_childs = 0;
91 free(src->text);
92 free(src);
96 DocNode * doc_node_make(const char *id, char *text, DocNode *child) {
97 DocNode *n = doc_node_create(id);
98 n->text = text;
99 doc_node_add_child(n, child);
100 return n;
103 DocNode * doc_node_make_take_children(const char *id, char *text, DocNode *src) {
104 DocNode *n = doc_node_make(id, text, NULL);
105 doc_node_move_children(n, src);
106 return n;
109 void doc_node_free_tree(DocNode *n) {
110 int i;
111 if(!n) return;
112 free(n->text);
113 for(i=0;i<n->n_childs;i++) {
114 doc_node_free_tree(n->children[i]);
116 free(n->children);
117 free(n);
120 void doc_node_fixup_tree(DocNode *n) {
121 int i;
122 if(n->id != "TEXT" && n->text) {
123 n->text = striptrailingws(n->text);
125 if(n->n_childs) {
126 DocNode *last = n->children[n->n_childs-1];
127 if(last->id=="NL") {
128 free(last); // NL has no text or children
129 n->n_childs--;
131 last = NULL;
132 for(i = 0; i < n->n_childs; i++) {
133 DocNode *child = n->children[i];
134 if((child->id=="TEXT" || child->id=="NL") && last && last->id=="TEXT") {
135 if(child->id=="NL") {
136 last->text = (char*)realloc(last->text,strlen(last->text)+2);
137 strcat(last->text," ");
138 } else {
139 last->text = strmerge(last->text,child->text);
141 free(child); // we took childs text and it has no children
142 n->children[i] = NULL;
143 } else {
144 doc_node_fixup_tree(child);
145 last = child;
148 int j = 0;
149 for(i = 0; i < n->n_childs; i++) {
150 if(n->children[i]) {
151 n->children[j++] = n->children[i];
154 n->n_childs = j;
158 static void _doc_node_dump(DocNode *n, int level, int last) {
159 int i;
160 for(i=0;i<level;i++) {
161 if(doc_node_dump_level_done[i])
162 printf(" ");
163 else
164 printf("| ");
166 if(last) {
167 printf("`-- ");
168 doc_node_dump_level_done[level] = 1;
169 } else {
170 printf("|-- ");
172 printf("%s",n->id);
173 if(n->text) printf(" \"%s\"",n->text);
174 printf("\n");
175 for(i = 0; i < n->n_childs; i++) {
176 _doc_node_dump(n->children[i], level+1, i==n->n_childs-1);
178 doc_node_dump_level_done[level] = 0;
181 void doc_node_dump(DocNode *n) {
182 _doc_node_dump(n,0,1);
185 extern void error(const char *fmt, ...);
187 DocNode * scdoc_parse_file(char *fn, int mode) {
188 FILE *fp;
189 DocNode *n;
191 fp = fopen(fn,"r");
192 if(!fp) {
193 error("scdoc_parse_file: could not open '%s'\n",fn);
194 return NULL;
196 scdoc_current_file = fn;
197 scdocrestart(fp);
198 n = scdoc_parse_run(mode);
199 if(n) {
200 doc_node_fixup_tree(n);
202 fclose(fp);
203 scdoclex_destroy();
204 scdoc_current_file = NULL;
205 return n;