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 ************************************************************************/
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
) {
38 char *s
= (char *)realloc(a
,strlen(a
)+strlen(b
)+1);
44 static char *striptrailingws(char *s
) {
45 char *s2
= strchr(s
,0);
46 while(--s2
> s
&& isspace(*s2
)) {
52 DocNode
* doc_node_create(const char *id
) {
53 DocNode
*n
= (DocNode
*)malloc(sizeof(DocNode
));
61 // takes ownership of child
62 DocNode
* doc_node_add_child(DocNode
*n
, DocNode
*child
) {
64 n
->children
= (DocNode
**)realloc(n
->children
, (n
->n_childs
+1) * sizeof(DocNode
*));
65 n
->children
[n
->n_childs
] = child
;
71 // takes ownership of text
72 /*DocNode * doc_node_add_text(DocNode *n, char *text) {
74 char *str = strmergefree(n->text,text);
76 printf("NODE: Adding text '%s'\n",text);
83 // moves the childs from src doc_node to n
84 void doc_node_move_children(DocNode
*n
, DocNode
*src
) {
87 n
->children
= src
->children
;
88 n
->n_childs
= src
->n_childs
;
89 // src->children = NULL;
96 DocNode
* doc_node_make(const char *id
, char *text
, DocNode
*child
) {
97 DocNode
*n
= doc_node_create(id
);
99 doc_node_add_child(n
, child
);
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
);
109 void doc_node_free_tree(DocNode
*n
) {
113 for(i
=0;i
<n
->n_childs
;i
++) {
114 doc_node_free_tree(n
->children
[i
]);
120 void doc_node_fixup_tree(DocNode
*n
) {
122 if(n
->id
!= "TEXT" && n
->text
) {
123 n
->text
= striptrailingws(n
->text
);
126 DocNode
*last
= n
->children
[n
->n_childs
-1];
128 free(last
); // NL has no text or children
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
," ");
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
;
144 doc_node_fixup_tree(child
);
149 for(i
= 0; i
< n
->n_childs
; i
++) {
151 n
->children
[j
++] = n
->children
[i
];
158 static void _doc_node_dump(DocNode
*n
, int level
, int last
) {
160 for(i
=0;i
<level
;i
++) {
161 if(doc_node_dump_level_done
[i
])
168 doc_node_dump_level_done
[level
] = 1;
173 if(n
->text
) printf(" \"%s\"",n
->text
);
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
) {
193 error("scdoc_parse_file: could not open '%s'\n",fn
);
196 scdoc_current_file
= fn
;
198 n
= scdoc_parse_run(mode
);
200 doc_node_fixup_tree(n
);
204 scdoc_current_file
= NULL
;