static int check_and_set_terms(struct bisect_terms *terms, const char *cmd) { int has_term_file = !is_empty_or_missing_file(git_path_bisect_terms()); if (one_of(cmd, "skip", "start", "terms", NULL)) return 0; if (has_term_file && strcmp(cmd, terms->term_bad) && strcmp(cmd, terms->term_good)) return error(_("Invalid command: you're currently in a " "%s/%s bisect"), terms->term_bad, terms->term_good); if (!has_term_file) { if (one_of(cmd, "bad", "good", NULL)) { set_terms(terms, "bad", "good"); return write_terms(terms->term_bad, terms->term_good); } if (one_of(cmd, "new", "old", NULL)) { set_terms(terms, "new", "old"); return write_terms(terms->term_bad, terms->term_good); } } return 0; }
int cmd_bisect__helper(int argc, const char **argv, const char *prefix) { enum { NEXT_ALL = 1, WRITE_TERMS, BISECT_CLEAN_STATE, CHECK_EXPECTED_REVS, BISECT_RESET, BISECT_WRITE, CHECK_AND_SET_TERMS, BISECT_NEXT_CHECK, BISECT_TERMS, BISECT_START } cmdmode = 0; int no_checkout = 0, res = 0, nolog = 0; struct option options[] = { OPT_CMDMODE(0, "next-all", &cmdmode, N_("perform 'git bisect next'"), NEXT_ALL), OPT_CMDMODE(0, "write-terms", &cmdmode, N_("write the terms to .git/BISECT_TERMS"), WRITE_TERMS), OPT_CMDMODE(0, "bisect-clean-state", &cmdmode, N_("cleanup the bisection state"), BISECT_CLEAN_STATE), OPT_CMDMODE(0, "check-expected-revs", &cmdmode, N_("check for expected revs"), CHECK_EXPECTED_REVS), OPT_CMDMODE(0, "bisect-reset", &cmdmode, N_("reset the bisection state"), BISECT_RESET), OPT_CMDMODE(0, "bisect-write", &cmdmode, N_("write out the bisection state in BISECT_LOG"), BISECT_WRITE), OPT_CMDMODE(0, "check-and-set-terms", &cmdmode, N_("check and set terms in a bisection state"), CHECK_AND_SET_TERMS), OPT_CMDMODE(0, "bisect-next-check", &cmdmode, N_("check whether bad or good terms exist"), BISECT_NEXT_CHECK), OPT_CMDMODE(0, "bisect-terms", &cmdmode, N_("print out the bisect terms"), BISECT_TERMS), OPT_CMDMODE(0, "bisect-start", &cmdmode, N_("start the bisect session"), BISECT_START), OPT_BOOL(0, "no-checkout", &no_checkout, N_("update BISECT_HEAD instead of checking out the current commit")), OPT_BOOL(0, "no-log", &nolog, N_("no log for BISECT_WRITE ")), OPT_END() }; struct bisect_terms terms = { .term_good = NULL, .term_bad = NULL }; argc = parse_options(argc, argv, prefix, options, git_bisect_helper_usage, PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_UNKNOWN); if (!cmdmode) usage_with_options(git_bisect_helper_usage, options); switch (cmdmode) { case NEXT_ALL: return bisect_next_all(the_repository, prefix, no_checkout); case WRITE_TERMS: if (argc != 2) return error(_("--write-terms requires two arguments")); return write_terms(argv[0], argv[1]); case BISECT_CLEAN_STATE: if (argc != 0) return error(_("--bisect-clean-state requires no arguments")); return bisect_clean_state(); case CHECK_EXPECTED_REVS: check_expected_revs(argv, argc); return 0; case BISECT_RESET: if (argc > 1) return error(_("--bisect-reset requires either no argument or a commit")); return !!bisect_reset(argc ? argv[0] : NULL); case BISECT_WRITE: if (argc != 4 && argc != 5) return error(_("--bisect-write requires either 4 or 5 arguments")); set_terms(&terms, argv[3], argv[2]); res = bisect_write(argv[0], argv[1], &terms, nolog); break; case CHECK_AND_SET_TERMS: if (argc != 3) return error(_("--check-and-set-terms requires 3 arguments")); set_terms(&terms, argv[2], argv[1]); res = check_and_set_terms(&terms, argv[0]); break; case BISECT_NEXT_CHECK: if (argc != 2 && argc != 3) return error(_("--bisect-next-check requires 2 or 3 arguments")); set_terms(&terms, argv[1], argv[0]); res = bisect_next_check(&terms, argc == 3 ? argv[2] : NULL); break; case BISECT_TERMS: if (argc > 1) return error(_("--bisect-terms requires 0 or 1 argument")); res = bisect_terms(&terms, argc == 1 ? argv[0] : NULL); break; case BISECT_START: set_terms(&terms, "bad", "good"); res = bisect_start(&terms, no_checkout, argv, argc); break; default: return error("BUG: unknown subcommand '%d'", cmdmode); } free_terms(&terms); return !!res; }
static int bisect_start(struct bisect_terms *terms, int no_checkout, const char **argv, int argc) { int i, has_double_dash = 0, must_write_terms = 0, bad_seen = 0; int flags, pathspec_pos, retval = 0; struct string_list revs = STRING_LIST_INIT_DUP; struct string_list states = STRING_LIST_INIT_DUP; struct strbuf start_head = STRBUF_INIT; struct strbuf bisect_names = STRBUF_INIT; struct object_id head_oid; struct object_id oid; const char *head; if (is_bare_repository()) no_checkout = 1; /* * Check for one bad and then some good revisions */ for (i = 0; i < argc; i++) { if (!strcmp(argv[i], "--")) { has_double_dash = 1; break; } } for (i = 0; i < argc; i++) { const char *arg = argv[i]; if (!strcmp(argv[i], "--")) { break; } else if (!strcmp(arg, "--no-checkout")) { no_checkout = 1; } else if (!strcmp(arg, "--term-good") || !strcmp(arg, "--term-old")) { must_write_terms = 1; free((void *) terms->term_good); terms->term_good = xstrdup(argv[++i]); } else if (skip_prefix(arg, "--term-good=", &arg) || skip_prefix(arg, "--term-old=", &arg)) { must_write_terms = 1; free((void *) terms->term_good); terms->term_good = xstrdup(arg); } else if (!strcmp(arg, "--term-bad") || !strcmp(arg, "--term-new")) { must_write_terms = 1; free((void *) terms->term_bad); terms->term_bad = xstrdup(argv[++i]); } else if (skip_prefix(arg, "--term-bad=", &arg) || skip_prefix(arg, "--term-new=", &arg)) { must_write_terms = 1; free((void *) terms->term_bad); terms->term_bad = xstrdup(arg); } else if (starts_with(arg, "--") && !one_of(arg, "--term-good", "--term-bad", NULL)) { return error(_("unrecognized option: '%s'"), arg); } else { char *commit_id = xstrfmt("%s^{commit}", arg); if (get_oid(commit_id, &oid) && has_double_dash) die(_("'%s' does not appear to be a valid " "revision"), arg); string_list_append(&revs, oid_to_hex(&oid)); free(commit_id); } } pathspec_pos = i; /* * The user ran "git bisect start <sha1> <sha1>", hence did not * explicitly specify the terms, but we are already starting to * set references named with the default terms, and won't be able * to change afterwards. */ if (revs.nr) must_write_terms = 1; for (i = 0; i < revs.nr; i++) { if (bad_seen) { string_list_append(&states, terms->term_good); } else { bad_seen = 1; string_list_append(&states, terms->term_bad); } } /* * Verify HEAD */ head = resolve_ref_unsafe("HEAD", 0, &head_oid, &flags); if (!head) if (get_oid("HEAD", &head_oid)) return error(_("bad HEAD - I need a HEAD")); /* * Check if we are bisecting */ if (!is_empty_or_missing_file(git_path_bisect_start())) { /* Reset to the rev from where we started */ strbuf_read_file(&start_head, git_path_bisect_start(), 0); strbuf_trim(&start_head); if (!no_checkout) { struct argv_array argv = ARGV_ARRAY_INIT; argv_array_pushl(&argv, "checkout", start_head.buf, "--", NULL); if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) { retval = error(_("checking out '%s' failed." " Try 'git bisect start " "<valid-branch>'."), start_head.buf); goto finish; } } } else { /* Get the rev from where we start. */ if (!get_oid(head, &head_oid) && !starts_with(head, "refs/heads/")) { strbuf_reset(&start_head); strbuf_addstr(&start_head, oid_to_hex(&head_oid)); } else if (!get_oid(head, &head_oid) && skip_prefix(head, "refs/heads/", &head)) { /* * This error message should only be triggered by * cogito usage, and cogito users should understand * it relates to cg-seek. */ if (!is_empty_or_missing_file(git_path_head_name())) return error(_("won't bisect on cg-seek'ed tree")); strbuf_addstr(&start_head, head); } else { return error(_("bad HEAD - strange symbolic ref")); } } /* * Get rid of any old bisect state. */ if (bisect_clean_state()) return -1; /* * In case of mistaken revs or checkout error, or signals received, * "bisect_auto_next" below may exit or misbehave. * We have to trap this to be able to clean up using * "bisect_clean_state". */ /* * Write new start state */ write_file(git_path_bisect_start(), "%s\n", start_head.buf); if (no_checkout) { get_oid(start_head.buf, &oid); if (update_ref(NULL, "BISECT_HEAD", &oid, NULL, 0, UPDATE_REFS_MSG_ON_ERR)) { retval = -1; goto finish; } } if (pathspec_pos < argc - 1) sq_quote_argv(&bisect_names, argv + pathspec_pos); write_file(git_path_bisect_names(), "%s\n", bisect_names.buf); for (i = 0; i < states.nr; i++) if (bisect_write(states.items[i].string, revs.items[i].string, terms, 1)) { retval = -1; goto finish; } if (must_write_terms && write_terms(terms->term_bad, terms->term_good)) { retval = -1; goto finish; } retval = bisect_append_log_quoted(argv); if (retval) retval = -1; finish: string_list_clear(&revs, 0); string_list_clear(&states, 0); strbuf_release(&start_head); strbuf_release(&bisect_names); return retval; }
/** * Given a program struct, will process the (already opened) input file and * begin compilation line by line. */ void process_input_program(struct program *program){ print_asterisk(GRN_C, stdout); printf("Processing File...\n"); char *tok; char buf[MAX_LINE_LEN+1]; buf[MAX_LINE_LEN] = 0; // parse input file do{ program->line_count++; #ifdef DEBUG fprintf(stderr, "*** Reading Line %d...\n", program->line_count); #endif fgetpos(program->in, &program->str_line); tok = read_next_token(buf, program->in, MAX_LINE_LEN); #ifdef DEBUG fprintf(stderr, "Read Token '%s'\n", tok); #endif if(!tok){ continue; // just a whitespace line, move on } else{ process_token(tok, program); } // the instruction processor should have consumed all relevant tokens, // check if there is garbage at the end of the line if(!program->error_code) check_garbage(program); }while(!check_EOF(program->in) && !program->error_code); if(program->error_code) return; // resolve constants/labels #ifdef DEBUG fprintf(stderr, "LAST TERM: '%s' TRANS: %d\n", program->end_term->term, program->end_term->trans); #endif translate_terms(program->terms, program); // write terms to out file struct Term *t = program->terms; write_terms(t, program); // process warnings if(warnings){ check_warnings(program); } #ifdef DEBUG // why did we quit? if(program->error_code){ fprintf(stderr, "Stopped processing because of an error.\n"); } else if(check_EOF(program->in)){ fprintf(stderr, "Stopped processing because EOF reached.\n"); } #endif }