/* Root schema `rs` is null for top level parser. */ int fb_init_parser(fb_parser_t *P, fb_options_t *opts, const char *name, fb_error_fun error_out, void *error_ctx, fb_root_schema_t *rs) { int i, n, name_len; char *s; memset(P, 0, sizeof(*P)); if (error_out) { P->error_out = error_out; P->error_ctx = error_ctx; } else { P->error_out = fb_default_error_out; } if (opts) { memcpy(&P->opts, opts, sizeof(*opts)); } else { flatcc_init_options(&P->opts); } P->schema.root_schema = rs ? rs : &P->schema.root_schema_instance; switch (P->opts.offset_size) { case 2: case 4: case 8: break; default: error(P, "invalid offset configured, must be 2, 4 (default), or 8"); return -1; } switch (P->opts.voffset_size) { case 2: case 4: case 8: break; default: error(P, "invalid voffset configured, must be 2 (default), 4, or 8"); return -1; } if (!name) { /* Mostly for testing, just so we always have a name. */ name = FLATCC_DEFAULT_FILENAME; } if (name == 0) { name = ""; } name_len = strlen(name); checkmem((P->schema.basename = fb_create_basename(name, name_len, opts->default_schema_ext))); n = strlen(P->schema.basename); checkmem(s = fb_copy_path(P->schema.basename, n)); for (i = 0; i < n; ++i) { s[i] = toupper(s[i]); } P->schema.basenameup = s; P->schema.name.name.s.s = s; P->schema.name.name.s.len = n; checkmem((P->schema.errorname = fb_create_basename(name, name_len, ""))); if (opts->ns) { P->schema.prefix.s = (char *)opts->ns; P->schema.prefix.len = strlen(opts->ns); } P->current_scope = fb_add_scope(P, 0); assert(P->current_scope == fb_scope_table_find(&P->schema.root_schema->scope_index, 0, 0)); return 0; }
int main() { const char *name = "../xyzzy.fbs"; char input[] = "// buffers do not support include statements\n" "//include \"foobar.fbs\";\n" "// in flatc, only one field can have a key, but we have no issues\n" "// as long as the vector is sorted accordingly. The first key gets\n" "// gets a shorter find alias method.\n" "// (all scalar vectors can also be searched - they have find defined)\n" "table point { x : float (key); y: float; z: float (key); }\n" "namespace mystic;\n" "table island { lattitude : int; longitude : int; }\n" " /// There are two different point tables\n" "// we test multi line doc comments here - this line should be ignored.\n" " /// - one in each name space.\n" "table point { interest: agent; blank: string; geo: mystic.island; }\n" "enum agent:int { lot, pirate, vessel, navy, parrot }\n" "namespace the;\n" "//root_type point;\n" "attribute \"foo\";\n" "//attribute \"\"; // ensure empty strings are accepted.\n" "/// shade is for CG applications\n" "struct shade (force_align:2) { x: byte; y: byte; z: byte;\n" "/// alpha is unsigned!\n" "alpha: ubyte (key); }\n" "/// the.ui is a union\n" "///\n" "/// We got one blank comment line above.\n" "union u1 { /// Note that the.point is different from mystic.point in other namespace.\n" "point\n" "= /// meaningless doc comment that should be stripped\n" "2, foo = 4, mystic.island = 17, } enum e1:short { z = -2, one , two , three = 3, }\n" "// key on enum not supported by flatc\n" "table foo { m: u1; e: e1 = z (key); x : int = mystic.agent.vessel; interest: mystic.agent = pirate; strange: mystic.agent = flags2.zulu; }\n" "// Unknown attributes can be repeated with varying types since behavior is unspecified.\n" "enum flags : short (bit_flags, \n" "/// foos are plentiful - here it is an enum of value 42\n" "foo: 42, foo, foo: \"hello\") { f1 = 1, f2 = 13, f3 }\n" "enum flags2 : uint (bit_flags) { zulu, alpha, bravo, charlie, delta, echo, foxtrot }\n" "/// A boolean enum - all enums must be type.\n" "enum confirm : bool { no, yes }\n" "// enums are not formally permitted in structs, but can be enabled.\n" "// This is advanced: boolean enum binary search on struct vector ...\n" "struct notify { primary_recipient: confirm (key); secondary_recipient: confirm; flags : flags; }\n" "// duplicates are disallowed by default, but can be enabled\n" "// enum dupes : byte { large = 2, great = 2, small = 0, other }\n" "table goo { hello: string (key, required); confirmations: [confirm];\n" " never_mind: double = 3.1415 (deprecated);\n" " embedded_t: [ubyte] (nested_flatbuffer: \"foo\");\n" " embedded_s: [ubyte] (nested_flatbuffer: \"little.whale.c2\");\n" " shady: shade;\n" "}\n" "struct s1 (force_align:4) { index: int (key); }\n" "struct c1 { a: ubyte; x1 : little.whale.c2; x2:uint; x3: short; light: shade (deprecated); }\n" "/// not all constructs support doc comments - this one doesn't\n" "namespace little.whale;\n" "struct c2 { y : c3; }\n" "//struct c3 { z : c1; }\n" "struct c3 { z : the.s1; }\n" "file_identifier \"fbuz\";\n" "file_extension \"cgen_test\";\n" "root_type little.whale.c2;\n" "//root_type c2;\n" "//root_type the.goo;\n" "table hop { einhorn: c3 (required); jupiter: c2; names: [string] (required); ehlist: [c3]; k2: the.goo; k2vec: [the.goo]; lunar: the.flags2 = bravo; }\n" "table TestOrder { x0 : byte; x1: bool = true; x2: short; x3: the.shade; x4: string; x5 : the.u1; x6 : [string]; x7: double; }\n" "table TestOrder2 (original_order) { x0 : byte; x1: bool = true; x1a : bool = 1; x2: short; x3: the.shade; x4: string; x5: the.u1; x6 : [string]; x7: double; }\n"; flatcc_options_t opts; flatcc_context_t ctx = 0; int ret = -1; flatcc_init_options(&opts); opts.cgen_common_reader = 1; opts.cgen_reader = 1; opts.cgen_common_builder = 1; opts.cgen_builder = 1; opts.gen_stdout = 1; /* The basename xyzzy is derived from path. */ if (!(ctx = flatcc_create_context(&opts, name, 0, 0))) { fprintf(stderr, "unexpected: could not initialize context\n"); return -1; } if ((ret = flatcc_parse_buffer(ctx, input, sizeof(input)))) { fprintf(stderr, "sorry, parse failed\n"); goto done; } else { fprintf(stderr, "schema is valid!\n"); fprintf(stderr, "now generating code for C ...\n\n"); if (flatcc_generate_files(ctx)) { fprintf(stderr, "failed to generate output for C\n"); goto done; }; fprintf(stdout, "\n#if 0 /* FlatBuffers Schema Source */\n" "%s\n" "#endif /* FlatBuffers Schema Source */\n", input); } ret = 0; done: flatcc_destroy_context(ctx); return ret; }