Exemple #1
0
/**
 * 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;
}
Exemple #2
0
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);
}
Exemple #3
0
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);
}
Exemple #4
0
/* ':' 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, ']')) {
        }
    }
}
Exemple #5
0
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);
}
Exemple #6
0
/*
 * 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;
}
Exemple #7
0
/* `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);
}
Exemple #8
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;
}
Exemple #9
0
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);
}
Exemple #10
0
/**
 * 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;
}