nsgenbind
Loading...
Searching...
No Matches
nsgenbind-ast.c
Go to the documentation of this file.
1/* binding generator AST implementation for parser
2 *
3 * This file is part of nsgenbind.
4 * Licensed under the MIT License,
5 * http://www.opensource.org/licenses/mit-license.php
6 * Copyright 2012 Vincent Sanders <vince@netsurf-browser.org>
7 */
8
12#include <stdio.h>
13#include <stdbool.h>
14#include <stdlib.h>
15#include <errno.h>
16#include <string.h>
17#include <stdarg.h>
18
19#include "utils.h"
20#include "nsgenbind-ast.h"
21#include "options.h"
22
26static FILE *genbind_parsetracef;
27
28/* parser and lexer interface */
29extern int nsgenbind_debug;
30extern int nsgenbind__flex_debug;
31extern void nsgenbind_restart(FILE*);
32extern int nsgenbind_parse(char *filename, struct genbind_node **genbind_ast);
33
34/* terminal nodes have a value only */
37 struct genbind_node *l;
38 union {
39 void *value;
41 char *text;
42 int number; /* node data is an integer */
43 } r;
44};
45
46/* insert node(s) at beginning of a list */
47struct genbind_node *
49{
50 struct genbind_node *end = inst;
51
52 if (inst == NULL) {
53 return list; /* no node to prepend - return existing list */
54 }
55
56 /* find end of inserted node list */
57 while (end->l != NULL) {
58 end = end->l;
59 }
60
61 end->l = list;
62
63 return inst;
64}
65
66/* prepend list to a nodes list
67 *
68 * inserts a list into the beginning of a nodes r list
69 *
70 * CAUTION: if the \a node element is not a node type the node will not be added
71 */
72struct genbind_node *
74{
75 if (node == NULL) {
76 return list;
77 }
78
79 /* this does not use genbind_node_getnode() as it cannot
80 * determine between an empty node and a node which is not a
81 * list type
82 */
83 switch (node->type) {
92 break;
93
94 default:
95 /* not a node type */
96 return list;
97 }
98
100
101 return node;
102}
103
104char *genbind_strapp(char *a, char *b)
105{
106 char *fullstr;
107 int fulllen;
108 fulllen = strlen(a) + strlen(b) + 1;
109 fullstr = malloc(fulllen);
110 snprintf(fullstr, fulllen, "%s%s", a, b);
111 free(a);
112 free(b);
113 return fullstr;
114}
115
116struct genbind_node *
118{
119 tgt->l = src;
120 return tgt;
121}
122
123
124struct genbind_node *
126{
127 struct genbind_node *nn;
128 nn = calloc(1, sizeof(struct genbind_node));
129 nn->type = type;
130 nn->l = l;
131 nn->r.value = r;
132 return nn;
133}
134
135struct genbind_node *
137 struct genbind_node *l,
138 int number)
139{
140 struct genbind_node *nn;
141 nn = calloc(1, sizeof(struct genbind_node));
142 nn->type = type;
143 nn->l = l;
144 nn->r.number = number;
145 return nn;
146}
147
148
149/* exported interface defined in nsgenbind-ast.h */
150int
154 void *ctx)
155{
156 int ret;
157
158 if (node == NULL) {
159 return -1;
160 }
161 if (node->l != NULL) {
162 ret = genbind_node_foreach_type(node->l, type, cb, ctx);
163 if (ret != 0) {
164 return ret;
165 }
166 }
167 if (node->type == type) {
168 return cb(node, ctx);
169 }
170
171 return 0;
172}
173
174static int genbind_enumerate_node(struct genbind_node *node, void *ctx)
175{
176 UNUSED(node);
177 (*((int *)ctx))++;
178 return 0;
179}
180
181/* exported interface defined in nsgenbind-ast.h */
182int
185{
186 int count = 0;
188 type,
189 genbind_enumerate_node,
190 &count);
191 return count;
192}
193
194/* exported interface defined in nsgenbind-ast.h */
195struct genbind_node *
197 struct genbind_node *prev,
199 void *ctx)
200{
201 struct genbind_node *ret;
202
203 if ((node == NULL) || (node == prev)) {
204 return NULL;
205 }
206
207 if (node->l != prev) {
208 ret = genbind_node_find(node->l, prev, cb, ctx);
209 if (ret != NULL) {
210 return ret;
211 }
212 }
213
214 if (cb(node, ctx) != 0) {
215 return node;
216 }
217
218 return NULL;
219}
220
221/* exported interface documented in nsgenbind-ast.h */
222struct genbind_node *
224 struct genbind_node *prev,
226{
227 return genbind_node_find(node,
228 prev,
230 (void *)type);
231}
232
233/* exported interface documented in nsgenbind-ast.h */
234struct genbind_node *
236 struct genbind_node *prev,
238 const char *ident)
239{
240 struct genbind_node *found_node;
241 struct genbind_node *ident_node;
242
243 if (ident == NULL) {
244 return NULL;
245 }
246
247 found_node = genbind_node_find_type(node, prev, type);
248
249 while (found_node != NULL) {
250 /* look for an ident node */
251 ident_node = genbind_node_find_type(
252 genbind_node_getnode(found_node),
253 NULL,
255
256 while (ident_node != NULL) {
257 /* check for matching text */
258 if (strcmp(ident_node->r.text, ident) == 0) {
259 return found_node;
260 }
261
262 ident_node = genbind_node_find_type(
263 genbind_node_getnode(found_node),
264 ident_node,
266 }
267
268
269 /* look for next matching node */
270 found_node = genbind_node_find_type(node, found_node, type);
271 }
272 return found_node;
273}
274
275
276
277/* exported interface documented in nsgenbind-ast.h */
278struct genbind_node *
280 struct genbind_node *prev,
281 enum genbind_method_type methodtype)
282{
283 struct genbind_node *res_node;
284
285 res_node = genbind_node_find_type(
288 while (res_node != NULL) {
289 struct genbind_node *type_node;
291
292 type_node = genbind_node_find_type(
293 genbind_node_getnode(res_node),
295
296 type = (enum genbind_method_type *)genbind_node_getint(type_node);
297 if (*type == methodtype) {
298 break;
299 }
300
301 res_node = genbind_node_find_type(
303 res_node, GENBIND_NODE_TYPE_METHOD);
304 }
305
306 return res_node;
307}
308
309
310/* exported interface documented in nsgenbind-ast.h */
311struct genbind_node *
313 struct genbind_node *prev,
314 enum genbind_method_type nodetype,
315 const char *ident)
316{
317 struct genbind_node *res_node;
318 char *method_ident;
319
320 res_node = genbind_node_find_method(node, prev, nodetype);
321 while (res_node != NULL) {
322 method_ident = genbind_node_gettext(
324 genbind_node_getnode(res_node),
325 NULL,
327
328 if ((ident != NULL) &&
329 (method_ident != NULL) &&
330 strcmp(ident, method_ident) == 0) {
331 break;
332 }
333
334 res_node = genbind_node_find_method(node, res_node, nodetype);
335 }
336 return res_node;
337}
338
339
340/* exported interface documented in nsgenbind-ast.h */
342{
343 if (node->type == (enum genbind_node_type)ctx)
344 return 1;
345 return 0;
346}
347
349{
350 if (node != NULL) {
351 switch(node->type) {
358 return node->r.text;
359
360 default:
361 break;
362 }
363 }
364 return NULL;
365}
366
368{
369 if (node != NULL) {
370 switch(node->type) {
379 return node->r.node;
380
381 default:
382 break;
383 }
384 }
385 return NULL;
386
387}
388
390{
391 if (node != NULL) {
392 switch(node->type) {
396 return &node->r.number;
397
398 default:
399 break;
400 }
401 }
402 return NULL;
403}
404
405static const char *genbind_node_type_to_str(enum genbind_node_type type)
406{
407 switch(type) {
409 return "Ident";
410
412 return "Root";
413
415 return "webidl";
416
418 return "String";
419
421 return "Binding";
422
424 return "TypeName";
425
427 return "Linenumber";
428
430 return "Filename";
431
433 return "Private";
434
436 return "Internal";
437
439 return "Class";
440
442 return "Flags";
443
445 return "Property";
446
448 return "Method";
449
451 return "Type";
452
454 return "Parameter";
455
457 return "CBlock";
458
459 default:
460 return "Unknown";
461 }
462}
463
465static int genbind_ast_dump(FILE *dfile, struct genbind_node *node, int indent)
466{
467 const char *SPACES=" ";
468 char *txt;
469 int *val;
470
471 while (node != NULL) {
472 fprintf(dfile, "%.*s%s", indent, SPACES,
473 genbind_node_type_to_str(node->type));
474
476 if (txt == NULL) {
478 if (val == NULL) {
479 fprintf(dfile, "\n");
480 genbind_ast_dump(dfile,
482 indent + 2);
483 } else {
484 fprintf(dfile, ": %d\n", *val);
485 }
486 } else {
487 fprintf(dfile, ": \"%.*s\"\n", 75 - indent, txt);
488 }
489 node = node->l;
490 }
491 return 0;
492}
493
494
495/* exported interface documented in nsgenbind-ast.h */
497{
498 FILE *dumpf;
499
500 /* only dump AST to file if required */
501 if (!options->debug) {
502 return 0;
503 }
504
505 dumpf = genb_fopen("binding-ast", "w");
506 if (dumpf == NULL) {
507 return 2;
508 }
509
510 genbind_ast_dump(dumpf, node, 0);
511
512 fclose(dumpf);
513
514 return 0;
515}
516
517FILE *genbindopen(const char *filename)
518{
519 FILE *genfile;
520 char *fullname;
521 int fulllen;
522 static char *prevfilepath = NULL;
523
524 /* try filename raw */
525 genfile = fopen(filename, "r");
526 if (genfile != NULL) {
527 if (options->verbose) {
528 printf("Opened Genbind file %s\n", filename);
529 }
530 if (prevfilepath == NULL) {
531 fullname = strrchr(filename, '/');
532 if (fullname == NULL) {
533 fulllen = strlen(filename);
534 } else {
535 fulllen = fullname - filename;
536 }
537 prevfilepath = strndup(filename,fulllen);
538 }
539 return genfile;
540 }
541
542 /* try based on previous filename */
543 if (prevfilepath != NULL) {
544 fulllen = strlen(prevfilepath) + strlen(filename) + 2;
545 fullname = malloc(fulllen);
546 snprintf(fullname, fulllen, "%s/%s", prevfilepath, filename);
547 if (options->verbose) {
548 printf("Attempting to open Genbind file %s\n", fullname);
549 }
550 genfile = fopen(fullname, "r");
551 if (genfile != NULL) {
552 if (options->verbose) {
553 printf("Opened Genbind file %s\n", fullname);
554 }
555 free(fullname);
556 return genfile;
557 }
558 free(fullname);
559 }
560
561 /* try on idl path */
562 if (options->idlpath != NULL) {
563 fulllen = strlen(options->idlpath) + strlen(filename) + 2;
564 fullname = malloc(fulllen);
565 snprintf(fullname, fulllen, "%s/%s", options->idlpath, filename);
566 genfile = fopen(fullname, "r");
567 if ((genfile != NULL) && options->verbose) {
568 printf("Opend Genbind file %s\n", fullname);
569#if 0
570 if (options->depfilehandle != NULL) {
571 fprintf(options->depfilehandle, " \\\n\t%s",
572 fullname);
573 }
574#endif
575 }
576
577 free(fullname);
578 }
579
580 return genfile;
581}
582
583
584int genbind_parsefile(char *infilename, struct genbind_node **ast)
585{
586 FILE *infile;
587 int ret;
588
589 /* open input file */
590 infile = genbindopen(infilename);
591 if (!infile) {
592 fprintf(stderr, "Error opening %s: %s\n",
593 infilename,
594 strerror(errno));
595 return 3;
596 }
597
598 /* if debugging enabled enable parser tracing and send to file */
599 if (options->debug) {
600 nsgenbind_debug = 1;
602 genbind_parsetracef = genb_fopen("binding-trace", "w");
603 } else {
604 genbind_parsetracef = NULL;
605 }
606
607 /* set flex to read from file */
608 nsgenbind_restart(infile);
609
610 /* process binding */
611 ret = nsgenbind_parse(infilename, ast);
612
613 /* close tracefile if open */
614 if (genbind_parsetracef != NULL) {
615 fclose(genbind_parsetracef);
616 }
617
618 return ret;
619}
620
621int genbind_fprintf(FILE *stream, const char *format, ...)
622{
623 va_list ap;
624 int ret;
625
626 va_start(ap, format);
627
628 if (genbind_parsetracef == NULL) {
629 ret = vfprintf(stream, format, ap);
630 } else {
631 ret = vfprintf(genbind_parsetracef, format, ap);
632 }
633 va_end(ap);
634
635 return ret;
636}
@ end
Definition html.idl:1035
DOMString filename
Definition html.idl:1561
struct genbind_node * genbind_node_prepend(struct genbind_node *list, struct genbind_node *inst)
int nsgenbind__flex_debug
struct genbind_node * genbind_node_find(struct genbind_node *node, struct genbind_node *prev, genbind_callback_t *cb, void *ctx)
int genbind_parsefile(char *infilename, struct genbind_node **ast)
void nsgenbind_restart(FILE *)
struct genbind_node * genbind_node_find_type(struct genbind_node *node, struct genbind_node *prev, enum genbind_node_type type)
int genbind_dump_ast(struct genbind_node *node)
struct genbind_node * genbind_node_find_method_ident(struct genbind_node *node, struct genbind_node *prev, enum genbind_method_type nodetype, const char *ident)
int * genbind_node_getint(struct genbind_node *node)
struct genbind_node * genbind_node_find_type_ident(struct genbind_node *node, struct genbind_node *prev, enum genbind_node_type type, const char *ident)
struct genbind_node * genbind_node_find_method(struct genbind_node *node, struct genbind_node *prev, enum genbind_method_type methodtype)
struct genbind_node * genbind_new_node(enum genbind_node_type type, struct genbind_node *l, void *r)
struct genbind_node * genbind_new_number_node(enum genbind_node_type type, struct genbind_node *l, int number)
struct genbind_node * genbind_node_getnode(struct genbind_node *node)
FILE * genbindopen(const char *filename)
char * genbind_node_gettext(struct genbind_node *node)
struct genbind_node * genbind_node_link(struct genbind_node *tgt, struct genbind_node *src)
int genbind_cmp_node_type(struct genbind_node *node, void *ctx)
int nsgenbind_debug
struct genbind_node * genbind_node_add(struct genbind_node *node, struct genbind_node *list)
int genbind_node_enumerate_type(struct genbind_node *node, enum genbind_node_type type)
int genbind_node_foreach_type(struct genbind_node *node, enum genbind_node_type type, genbind_callback_t *cb, void *ctx)
int genbind_fprintf(FILE *stream, const char *format,...)
char * genbind_strapp(char *a, char *b)
int nsgenbind_parse(char *filename, struct genbind_node **genbind_ast)
genbind_method_type
genbind_node_type
@ GENBIND_NODE_TYPE_PARAMETER
@ GENBIND_NODE_TYPE_BINDING
@ GENBIND_NODE_TYPE_INTERNAL
@ GENBIND_NODE_TYPE_ROOT
@ GENBIND_NODE_TYPE_MODIFIER
@ GENBIND_NODE_TYPE_WEBIDL
@ GENBIND_NODE_TYPE_METHOD_TYPE
@ GENBIND_NODE_TYPE_NAME
@ GENBIND_NODE_TYPE_STRING
@ GENBIND_NODE_TYPE_FLAGS
@ GENBIND_NODE_TYPE_CLASS
@ GENBIND_NODE_TYPE_METHOD
@ GENBIND_NODE_TYPE_PROPERTY
@ GENBIND_NODE_TYPE_IDENT
@ GENBIND_NODE_TYPE_PRIVATE
@ GENBIND_NODE_TYPE_CDATA
@ GENBIND_NODE_TYPE_LINE
@ GENBIND_NODE_TYPE_FILE
int() genbind_callback_t(struct genbind_node *node, void *ctx)
void * malloc(YYSIZE_T)
void free(void *)
struct genbind_node * node
struct genbind_node * l
enum genbind_node_type type
union genbind_node::@3 r
bool debug
Definition options.h:19
char * idlpath
Definition options.h:16
bool verbose
Definition options.h:18
FILE * genb_fopen(const char *fname, const char *mode)
Definition utils.c:46
#define UNUSED(x)
Definition utils.h:50