12 static inline char *add_node(const char *s
, knaux_t
*aux
, int x
)
14 char *p
, *nbeg
, *nend
= 0;
16 if (aux
->n
== aux
->max
) {
17 aux
->max
= aux
->max
? aux
->max
<<1 : 8;
18 aux
->node
= (knhx1_t
*)realloc(aux
->node
, sizeof(knhx1_t
) * aux
->max
);
20 r
= aux
->node
+ (aux
->n
++);
21 r
->n
= x
; r
->parent
= -1;
22 for (p
= (char*)s
, nbeg
= p
, r
->d
= -1.0; *p
&& *p
!= ',' && *p
!= ')'; ++p
) {
24 if (nend
== 0) nend
= p
;
25 do ++p
; while (*p
&& *p
!= ']');
27 aux
->error
|= KNERR_BRACKET
;
30 } else if (*p
== ':') {
31 if (nend
== 0) nend
= p
;
32 r
->d
= strtod(p
+ 1, &p
);
34 } else if (!isgraph(*p
)) if (nend
== 0) nend
= p
;
36 if (nend
== 0) nend
= p
;
38 r
->name
= (char*)calloc(nend
- nbeg
+ 1, 1);
39 strncpy(r
->name
, nbeg
, nend
- nbeg
);
40 } else r
->name
= strdup("");
44 knhx1_t
*kn_parse(const char *nhx
, int *_n
, int *_error
)
51 #define __push_back(y) do { \
53 max = max? max<<1 : 16; \
54 stack = (int*)realloc(stack, sizeof(int) * max); \
59 stack = 0; top = max = 0;
61 aux
= (knaux_t
*)calloc(1, sizeof(knaux_t
));
63 while (*p
&& !isgraph(*p
)) ++p
;
69 } else if (*p
== ')') {
71 for (i
= top
- 1; i
>= 0; --i
)
72 if (stack
[i
] < 0) break;
74 p
= add_node(p
+ 1, aux
, m
);
75 aux
->node
[x
].child
= (int*)calloc(m
, sizeof(int));
76 for (i
= top
- 1, m
= m
- 1; m
>= 0; --m
, --i
) {
77 aux
->node
[x
].child
[m
] = stack
[i
];
78 aux
->node
[stack
[i
]].parent
= x
;
84 p
= add_node(p
, aux
, 0);
90 free(aux
); free(stack
);
95 #define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
98 static inline int kputsn(const char *p
, int l
, kstring_t
*s
)
100 if (s
->l
+ l
+ 1 >= s
->m
) {
103 s
->s
= (char*)realloc(s
->s
, s
->m
);
105 memcpy(s
->s
+ s
->l
, p
, l
);
106 s
->l
+= l
; s
->s
[s
->l
] = 0;
110 static inline int kputc(int c
, kstring_t
*s
)
112 if (s
->l
+ 1 >= s
->m
) {
115 s
->s
= (char*)realloc(s
->s
, s
->m
);
117 s
->s
[s
->l
++] = c
; s
->s
[s
->l
] = 0;
121 static void format_node_recur(const knhx1_t
*node
, const knhx1_t
*p
, kstring_t
*s
, char *numbuf
)
126 for (i
= 0; i
< p
->n
; ++i
) {
127 if (i
) kputc(',', s
);
128 format_node_recur(node
, &node
[p
->child
[i
]], s
, numbuf
);
131 if (p
->name
) kputsn(p
->name
, strlen(p
->name
), s
);
133 sprintf(numbuf
, ":%g", p
->d
);
134 kputsn(numbuf
, strlen(numbuf
), s
);
137 kputsn(p
->name
, strlen(p
->name
), s
);
139 sprintf(numbuf
, ":%g", p
->d
);
140 kputsn(numbuf
, strlen(numbuf
), s
);
145 void kn_format(const knhx1_t
*node
, int root
, kstring_t
*s
) // TODO: get rid of recursion
148 format_node_recur(node
, &node
[root
], s
, numbuf
);
152 int main(int argc
, char *argv
[])
154 char *s
= "((a[abc],d1)x:0.5,((b[&&NHX:S=MOUSE],h2)[&&NHX:S=HUMAN:B=99][blabla][&&NHX:K=foo],c))";
158 node
= kn_parse(s
, &n
, &error
);
159 for (i
= 0; i
< n
; ++i
) {
160 knhx1_t
*p
= node
+ i
;
161 printf("[%d] %s\t%d\t%d\t%g", i
, p
->name
, p
->parent
, p
->n
, p
->d
);
162 for (j
= 0; j
< p
->n
; ++j
)
163 printf("\t%d", p
->child
[j
]);
166 str
.l
= str
.m
= 0; str
.s
= 0;
167 kn_format(node
, n
-1, &str
);