/** * get the main worktree */ static struct worktree *get_main_worktree(void) { struct worktree *worktree = NULL; struct strbuf path = STRBUF_INIT; struct strbuf worktree_path = STRBUF_INIT; struct strbuf head_ref = STRBUF_INIT; int is_bare = 0; int is_detached = 0; strbuf_add_absolute_path(&worktree_path, get_git_common_dir()); is_bare = !strbuf_strip_suffix(&worktree_path, "/.git"); if (is_bare) strbuf_strip_suffix(&worktree_path, "/."); strbuf_addf(&path, "%s/HEAD", get_git_common_dir()); worktree = xcalloc(1, sizeof(*worktree)); worktree->path = strbuf_detach(&worktree_path, NULL); worktree->is_bare = is_bare; worktree->is_detached = is_detached; if (!parse_ref(path.buf, &head_ref, &is_detached)) add_head_info(&head_ref, worktree); strbuf_release(&path); strbuf_release(&worktree_path); strbuf_release(&head_ref); return worktree; }
static void parse_value(fb_parser_t *P, fb_value_t *v, int flags, const char *error_msg) { fb_token_t *t; fb_token_t *sign; sign = optional(P, '-'); t = P->token; switch (t->id) { case LEX_TOK_INT: read_integer_value(P, t, v, sign != 0); break; case LEX_TOK_FLOAT: read_float_value(P, t, v, sign != 0); break; case tok_kw_true: v->b = 1; v->type = vt_bool; break; case tok_kw_false: v->b = 0; v->type = vt_bool; break; case LEX_TOK_STRING_BEGIN: next(P); parse_string_literal(P, v); if (!(flags & allow_string_value)) { v->type = vt_invalid; error_tok(P, t, error_msg); return; } if (sign) { v->type = vt_invalid; error_tok(P, t, "string constants cannot be signed"); return; } return; case LEX_TOK_ID: parse_ref(P, &v->ref); v->type = vt_name_ref; if (sign) { v->type = vt_invalid; /* Technically they could, but we do not allow it. */ error_tok(P, t, "named values cannot be signed"); } return; default: /* We might have consumed a sign, but never mind that. */ error_tok(P, t, error_msg); return; } if (sign && v->type == vt_bool) { v->type = vt_invalid; error_tok(P, t, "boolean constants cannot be signed"); } next(P); }
static void parse_namespace(fb_parser_t *P) { fb_ref_t *ref = 0; fb_token_t *t = P->token; parse_ref(P, &ref); advance(P, ';', "missing ';' expected by namespace at", t); P->current_scope = fb_add_scope(P, ref); }
/* ':' must already be matched */ static void parse_type(fb_parser_t *P, fb_value_t *v) { fb_token_t *t = 0; fb_token_t *t0 = P->token; int vector = 0; v->type = vt_invalid; while ((t = optional(P, '['))) { ++vector; } if (vector > 1) { error_tok(P, t0, "vector type can only be one-dimensional"); } switch (P->token->id) { case tok_kw_int: case tok_kw_bool: case tok_kw_byte: case tok_kw_long: case tok_kw_uint: case tok_kw_float: case tok_kw_short: case tok_kw_ubyte: case tok_kw_ulong: case tok_kw_ushort: case tok_kw_double: v->t = P->token; v->type = vector ? vt_vector_type : vt_scalar_type; next(P); break; case tok_kw_string: v->t = P->token; v->type = vector ? vt_vector_string_type : vt_string_type; next(P); break; case LEX_TOK_ID: parse_ref(P, &v->ref); v->type = vector ? vt_vector_type_ref : vt_type_ref; break; case ']': error_tok(P, t, "vector type cannot be empty"); break; default: error_tok(P, t, "invalid type specifier"); break; } while (optional(P, ']') && vector--) { } if (vector) { error_tok_2(P, t, "vector type missing ']' to match", t0); } if ((t = optional(P, ']'))) { error_tok_2(P, t, "extra ']' not matching", t0); while (optional(P, ']')) { } } }
static void parse_root_type(fb_parser_t *P, fb_root_type_t *rt) { fb_token_t *t = P->token; if (rt->name) { error_tok(P, P->token, "root_type already set"); } parse_ref(P, &rt->name); rt->scope = P->current_scope; advance(P, ';', "missing ';' expected by root_type at", t); }
/* * note: this function should be able to detect shared symref even if * HEAD is temporarily detached (e.g. in the middle of rebase or * bisect). New commands that do similar things should update this * function as well. */ const struct worktree *find_shared_symref(const char *symref, const char *target) { const struct worktree *existing = NULL; struct strbuf path = STRBUF_INIT; struct strbuf sb = STRBUF_INIT; static struct worktree **worktrees; int i = 0; if (worktrees) free_worktrees(worktrees); worktrees = get_worktrees(); for (i = 0; worktrees[i]; i++) { struct worktree *wt = worktrees[i]; if (wt->is_bare) continue; if (wt->is_detached && !strcmp(symref, "HEAD")) { if (is_worktree_being_rebased(wt, target)) { existing = wt; break; } if (is_worktree_being_bisected(wt, target)) { existing = wt; break; } } strbuf_reset(&path); strbuf_reset(&sb); strbuf_addf(&path, "%s/%s", get_worktree_git_dir(wt), symref); if (parse_ref(path.buf, &sb, NULL)) { continue; } if (!strcmp(sb.buf, target)) { existing = wt; break; } } strbuf_release(&path); strbuf_release(&sb); return existing; }
/* `union` must already be matched. */ static void parse_union_decl(fb_parser_t *P, fb_compound_type_t *ct) { fb_token_t *t0; fb_member_t *member; fb_ref_t *ref; if (!(ct->symbol.ident = match(P, LEX_TOK_ID, "union declaration expected identifier"))) { goto fail; } ct->metadata = parse_metadata(P); if (!((t0 = match(P, '{', "union declaration expected '{'")))) { goto fail; } for (;;) { if (P->token->id != LEX_TOK_ID) { error_tok(P, P->token, "union expects an identifier"); goto fail; } if (P->failed >= FLATCC_MAX_ERRORS) { goto fail; } member = fb_add_member(P, &ct->members); parse_ref(P, &ref); member->type.ref = ref; member->type.type = vt_type_ref; while (ref->link) { ref = ref->link; } /* The union member is the unqualified reference. */ member->symbol.ident = ref->ident; if (optional(P, '=')) { parse_value(P, &member->value, 0, "integral constant expected"); /* Leave detailed type (e.g. no floats) and range checking to a later stage. */ } if (!optional(P, ',') || P->token->id == '}') { break; } P->doc = 0; } advance(P, '}', "union missing closing '}' to match", t0); revert_symbols(&ct->members); /* Add implicit `NONE` member first in the list. */ member = fb_add_member(P, &ct->members); member->symbol.ident = &P->t_none; return; fail: recover2(P, ';', 1, '}', 0); }
static struct worktree *get_linked_worktree(const char *id) { struct worktree *worktree = NULL; struct strbuf path = STRBUF_INIT; struct strbuf worktree_path = STRBUF_INIT; struct strbuf head_ref = STRBUF_INIT; int is_detached = 0; if (!id) die("Missing linked worktree name"); strbuf_git_common_path(&path, "worktrees/%s/gitdir", id); if (strbuf_read_file(&worktree_path, path.buf, 0) <= 0) /* invalid gitdir file */ goto done; strbuf_rtrim(&worktree_path); if (!strbuf_strip_suffix(&worktree_path, "/.git")) { strbuf_reset(&worktree_path); strbuf_add_absolute_path(&worktree_path, "."); strbuf_strip_suffix(&worktree_path, "/."); } strbuf_reset(&path); strbuf_addf(&path, "%s/worktrees/%s/HEAD", get_git_common_dir(), id); if (parse_ref(path.buf, &head_ref, &is_detached) < 0) goto done; worktree = xmalloc(sizeof(struct worktree)); worktree->path = strbuf_detach(&worktree_path, NULL); worktree->id = xstrdup(id); worktree->is_bare = 0; worktree->head_ref = NULL; worktree->is_detached = is_detached; worktree->is_current = 0; add_head_info(&head_ref, worktree); worktree->lock_reason = NULL; worktree->lock_reason_valid = 0; done: strbuf_release(&path); strbuf_release(&worktree_path); strbuf_release(&head_ref); return worktree; }
static void parse_namespace(fb_parser_t *P) { fb_ref_t *ref = 0; fb_token_t *t = P->token; if (optional(P, ';') && t) { /* Revert to global namespace. */ P->current_scope = 0; return; } if (P->token->id != LEX_TOK_ID) { error_tok(P, P->token, "namespace expects an identifier"); recover(P, ';', 1); return; } parse_ref(P, &ref); advance(P, ';', "missing ';' expected by namespace at", t); P->current_scope = fb_add_scope(P, ref); }
/** * get the main worktree */ static struct worktree *get_main_worktree(void) { struct worktree *worktree = NULL; struct strbuf path = STRBUF_INIT; struct strbuf worktree_path = STRBUF_INIT; struct strbuf head_ref = STRBUF_INIT; int is_bare = 0; int is_detached = 0; strbuf_add_absolute_path(&worktree_path, get_git_common_dir()); is_bare = !strbuf_strip_suffix(&worktree_path, "/.git"); if (is_bare) strbuf_strip_suffix(&worktree_path, "/."); strbuf_addf(&path, "%s/HEAD", get_git_common_dir()); if (parse_ref(path.buf, &head_ref, &is_detached) < 0) goto done; worktree = xmalloc(sizeof(struct worktree)); worktree->path = strbuf_detach(&worktree_path, NULL); worktree->id = NULL; worktree->is_bare = is_bare; worktree->head_ref = NULL; worktree->is_detached = is_detached; worktree->is_current = 0; add_head_info(&head_ref, worktree); worktree->lock_reason = NULL; worktree->lock_reason_valid = 0; done: strbuf_release(&path); strbuf_release(&worktree_path); strbuf_release(&head_ref); return worktree; }