Example #1
0
static int parse_patch_binary(
	git_patch_parsed *patch,
	git_patch_parse_ctx *ctx)
{
	int error;

	if (parse_advance_expected_s(ctx, "GIT binary patch") < 0 ||
		parse_advance_nl(ctx) < 0)
		return parse_err("corrupt git binary header at line %d", ctx->line_num);

	/* parse old->new binary diff */
	if ((error = parse_patch_binary_side(
			&patch->base.binary.new_file, ctx)) < 0)
		return error;

	if (parse_advance_nl(ctx) < 0)
		return parse_err("corrupt git binary separator at line %d",
			ctx->line_num);

	/* parse new->old binary diff */
	if ((error = parse_patch_binary_side(
			&patch->base.binary.old_file, ctx)) < 0)
		return error;

	if (parse_advance_nl(ctx) < 0)
		return parse_err("corrupt git binary patch separator at line %d",
			ctx->line_num);

	patch->base.delta->flags |= GIT_DIFF_FLAG_BINARY;
	return 0;
}
Example #2
0
static void parse_ops(int argc, char **argv, int i)
{
  enum { STATE_INIT, STATE_GOT_FILTER, STATE_GOT_OP } state = STATE_INIT;
  struct pci_filter filter;
  struct pci_dev **selected_devices = NULL;

  while (i < argc)
    {
      char *c = argv[i++];

      if (*c == '-')
	{
	  if (state != STATE_GOT_FILTER)
	    pci_filter_init(pacc, &filter);
	  i = parse_filter(argc, argv, i-1, &filter);
	  state = STATE_GOT_FILTER;
	}
      else
	{
	  if (state == STATE_INIT)
	    parse_err("Filter specification expected");
	  if (state == STATE_GOT_FILTER)
	    selected_devices = select_devices(&filter);
	  if (!selected_devices[0] && !force)
	    fprintf(stderr, "setpci: Warning: No devices selected for \"%s\".\n", c);
	  parse_op(c, selected_devices);
	  state = STATE_GOT_OP;
	}
    }
  if (state == STATE_INIT)
    parse_err("No operation specified");
}
Example #3
0
static int parse_filter(int argc, char **argv, int i, struct pci_filter *filter)
{
  char *c = argv[i++];
  char *d;

  if (!c[1] || !strchr("sd", c[1]))
    parse_err("Invalid option -%c", c[1]);
  if (c[2])
    d = (c[2] == '=') ? c+3 : c+2;
  else if (i < argc)
    d = argv[i++];
  else
    parse_err("Option -%c requires an argument", c[1]);
  switch (c[1])
    {
    case 's':
      if (d = pci_filter_parse_slot(filter, d))
	parse_err("Unable to parse filter -s %s", d);
      break;
    case 'd':
      if (d = pci_filter_parse_id(filter, d))
	parse_err("Unable to parse filter -d %s", d);
      break;
    default:
      parse_err("Unknown filter option -%c", c[1]);
    }

  return i;
}
Example #4
0
get_outputs()
{
	int	i;
	int	j;

	struct	nf	*n;

	char	buf[80];

	get_str(cfp,buf," ");
	/* next line must specify outputs */
	if (strcmp(buf, "output") != 0)
		parse_err();
	get_str(cfp,buf," ");
	if (strcmp(buf, "node") != 0){
		if (strcmp(buf, "nodes") != 0)
			parse_err();
	}
	get_str(cfp,buf," ");
	if (strcmp(buf, "are") != 0){
		if (strcmp(buf, "is") != 0)
		parse_err();
	}
	get_str(cfp,buf,"\n");
	get_nums(buf,nn+ni,ni,selects);
	if (selects[0] == 1){
		fprintf(stderr,"Node 0 cannot be an output\n");
		exit(1);
	}
	for (i = 1; i <= ni; i++){
		if (selects[i] == 1){
			fprintf(stderr,"An input cannot be an output\n");
			exit(1);
		}
	}
	n = ninfo;
	for (i = ni+1, j = -1; i <= nn+ni; i++, n++){
		if (selects[i] > 0){
			if (++j < no){
				outputs[j] = i-ni;
				n->targ = 1;
			}
		}
	}
	if (++j != no){
		fprintf(stderr,"Expecting %d outputs, found %d\n",no,j);
		exit(1);
	}

}
Example #5
0
static int check_filenames(git_patch_parsed *patch)
{
	const char *prefixed_new, *prefixed_old;
	size_t old_prefixlen = 0, new_prefixlen = 0;
	bool added = (patch->base.delta->status == GIT_DELTA_ADDED);
	bool deleted = (patch->base.delta->status == GIT_DELTA_DELETED);

	if (patch->old_path && !patch->new_path)
		return parse_err("missing new path");

	if (!patch->old_path && patch->new_path)
		return parse_err("missing old path");

	/* Ensure (non-renamed) paths match */
	if (check_header_names(
			patch->header_old_path, patch->old_path, "old", added) < 0 ||
		check_header_names(
			patch->header_new_path, patch->new_path, "new", deleted) < 0)
		return -1;

	prefixed_old = (!added && patch->old_path) ? patch->old_path :
		patch->header_old_path;
	prefixed_new = (!deleted && patch->new_path) ? patch->new_path :
		patch->header_new_path;

	if (check_prefix(
			&patch->old_prefix, &old_prefixlen, patch, prefixed_old) < 0 ||
		check_prefix(
			&patch->new_prefix, &new_prefixlen, patch, prefixed_new) < 0)
		return -1;

	/* Prefer the rename filenames as they are unambiguous and unprefixed */
	if (patch->rename_old_path)
		patch->base.delta->old_file.path = patch->rename_old_path;
	else
		patch->base.delta->old_file.path = prefixed_old + old_prefixlen;

	if (patch->rename_new_path)
		patch->base.delta->new_file.path = patch->rename_new_path;
	else
		patch->base.delta->new_file.path = prefixed_new + new_prefixlen;

	if (!patch->base.delta->old_file.path &&
		!patch->base.delta->new_file.path)
		return parse_err("git diff header lacks old / new paths");

	return 0;
}
Example #6
0
/*
 * parse_line - Parse the current line and process the found token.
 */
static int parse_line(const char *line, int nl, parser_ctx_t *ctx, gamelist_t *list)
{
	int tok = get_token(line, ctx->top);
	D_PRINTF("%4i  %i  %s\n", nl, tok, line);

	/*
	 * Check if current token is expected - makes sure that the list
	 * operations succeed.
	 */
	if (!(ctx->next & tok)) {
		parse_err(nl, "parse error: %s invalid here", tok2str(tok));
		return -1;
	}

	/* Process actual token and add it to the list it belongs to. */
	switch (tok) {
	case TOK_GAME_TITLE:
		ctx->game = __make_game(line);
		if (ctx->game == NULL) {
			parse_err(nl, "make_game() failed");
			return -1;
		}
		GAMES_INSERT_TAIL(list, ctx->game);
		break;

	case TOK_CHEAT_DESC:
		ctx->cheat = __make_cheat(line);
		if (ctx->cheat == NULL) {
			parse_err(nl, "make_cheat() failed");
			return -1;
		}
		CHEATS_INSERT_TAIL(&ctx->game->cheats, ctx->cheat);
		break;

	case TOK_CHEAT_CODE:
		ctx->code = __make_code(line);
		if (ctx->code == NULL) {
			parse_err(nl, "make_code() failed");
			return -1;
		}
		CODES_INSERT_TAIL(&ctx->cheat->codes, ctx->code);
		break;
	}

	ctx->next = next_token(tok);

	return 0;
}
Example #7
0
static int check_patch(git_patch_parsed *patch)
{
	git_diff_delta *delta = patch->base.delta;

	if (check_filenames(patch) < 0)
		return -1;

	if (delta->old_file.path &&
			delta->status != GIT_DELTA_DELETED &&
			!delta->new_file.mode)
		delta->new_file.mode = delta->old_file.mode;

	if (delta->status == GIT_DELTA_MODIFIED &&
			!(delta->flags & GIT_DIFF_FLAG_BINARY) &&
			delta->new_file.mode == delta->old_file.mode &&
			git_array_size(patch->base.hunks) == 0)
		return parse_err("patch with no hunks");

	if (delta->status == GIT_DELTA_ADDED) {
		memset(&delta->old_file.id, 0x0, sizeof(git_oid));
		delta->old_file.id_abbrev = 0;
	}

	if (delta->status == GIT_DELTA_DELETED) {
		memset(&delta->new_file.id, 0x0, sizeof(git_oid));
		delta->new_file.id_abbrev = 0;
	}

	return 0;
}
Example #8
0
int set_iof_rule(const char* path, const char* prob, const char* fake_err, const char* extra_arg)
{
  int err = 0;
  iof_t* iof = NULL;
  iof_t val;
  memset(&val, 0, sizeof(val));
  if (NULL == path || NULL == prob || NULL == fake_err || NULL == extra_arg)
  {
    err = -EINVAL;
    error("set_iof_rule():EINVAL\n");
  }
  else if (NULL == (iof = get_iof_ctrl()))
  {
    err = errno;
  }
  else if (0 == strncmp(TCP_PREFIX, path, strlen(TCP_PREFIX)))
  {
    val.type = SOCK_TYPE;
    val.port = atoi(path + strlen(TCP_PREFIX));
  }
  else
  {
    val.type = REG_TYPE;
    val.dev_no = get_dev_no_by_path(path);
  }
  if (0 == err)
  {
    val.prob = atof(prob);
    val.err = parse_err(fake_err);
    val.arg = atoi(extra_arg);
    while(!set_iof(iof, &val))
      ;
  }
  return err;
}
Example #9
0
int check_header_names(
	const char *one,
	const char *two,
	const char *old_or_new,
	bool two_null)
{
	if (!one || !two)
		return 0;

	if (two_null && strcmp(two, "/dev/null") != 0)
		return parse_err("expected %s path of '/dev/null'", old_or_new);

	else if (!two_null && strcmp(one, two) != 0)
		return parse_err("mismatched %s path names", old_or_new);

	return 0;
}
Example #10
0
static int parse_header_similarity(
	git_patch_parsed *patch, git_patch_parse_ctx *ctx)
{
	if (parse_header_percent(&patch->base.delta->similarity, ctx) < 0)
		return parse_err("invalid similarity percentage at line %d",
			ctx->line_num);

	return 0;
}
Example #11
0
static int parse_patch_header(
	git_patch_parsed *patch,
	git_patch_parse_ctx *ctx)
{
	int error = 0;

	for (ctx->line = ctx->remain;
		ctx->remain_len > 0;
		parse_advance_line(ctx)) {

		/* This line is too short to be a patch header. */
		if (ctx->line_len < 6)
			continue;

		/* This might be a hunk header without a patch header, provide a
		 * sensible error message. */
		if (parse_ctx_contains_s(ctx, "@@ -")) {
			size_t line_num = ctx->line_num;
			git_patch_hunk hunk;

			/* If this cannot be parsed as a hunk header, it's just leading
			* noise, continue.
			*/
			if (parse_hunk_header(&hunk, ctx) < 0) {
				giterr_clear();
				continue;
			}

			error = parse_err("invalid hunk header outside patch at line %d",
				line_num);
			goto done;
		}

		/* This buffer is too short to contain a patch. */
		if (ctx->remain_len < ctx->line_len + 6)
			break;

		/* A proper git patch */
		if (parse_ctx_contains_s(ctx, "diff --git ")) {
			error = parse_header_git(patch, ctx);
			goto done;
		}

		error = 0;
		continue;
	}

	giterr_set(GITERR_PATCH, "no patch found");
	error = GIT_ENOTFOUND;

done:
	return error;
}
Example #12
0
static int parse_hunk_header(
	git_patch_hunk *hunk,
	git_patch_parse_ctx *ctx)
{
	const char *header_start = ctx->line;

	hunk->hunk.old_lines = 1;
	hunk->hunk.new_lines = 1;

	if (parse_advance_expected_s(ctx, "@@ -") < 0 ||
		parse_int(&hunk->hunk.old_start, ctx) < 0)
		goto fail;

	if (ctx->line_len > 0 && ctx->line[0] == ',') {
		if (parse_advance_expected_s(ctx, ",") < 0 ||
			parse_int(&hunk->hunk.old_lines, ctx) < 0)
			goto fail;
	}

	if (parse_advance_expected_s(ctx, " +") < 0 ||
		parse_int(&hunk->hunk.new_start, ctx) < 0)
		goto fail;

	if (ctx->line_len > 0 && ctx->line[0] == ',') {
		if (parse_advance_expected_s(ctx, ",") < 0 ||
			parse_int(&hunk->hunk.new_lines, ctx) < 0)
			goto fail;
	}

	if (parse_advance_expected_s(ctx, " @@") < 0)
		goto fail;

	parse_advance_line(ctx);

	if (!hunk->hunk.old_lines && !hunk->hunk.new_lines)
		goto fail;

	hunk->hunk.header_len = ctx->line - header_start;
	if (hunk->hunk.header_len > (GIT_DIFF_HUNK_HEADER_SIZE - 1))
		return parse_err("oversized patch hunk header at line %d",
			ctx->line_num);

	memcpy(hunk->hunk.header, header_start, hunk->hunk.header_len);
	hunk->hunk.header[hunk->hunk.header_len] = '\0';

	return 0;

fail:
	giterr_set(GITERR_PATCH, "invalid patch hunk header at line %d",
		ctx->line_num);
	return -1;
}
Example #13
0
static int parse_header_dissimilarity(
	git_patch_parsed *patch, git_patch_parse_ctx *ctx)
{
	uint16_t dissimilarity;

	if (parse_header_percent(&dissimilarity, ctx) < 0)
		return parse_err("invalid similarity percentage at line %d",
			ctx->line_num);

	patch->base.delta->similarity = 100 - dissimilarity;

	return 0;
}
Example #14
0
int main(int argc, char *argv[]) 
{
#if defined(_WIN32) || defined(__CYGWIN__)
	const char * port = "COM1";
#else
	const char * port = "/dev/ttyS11";
#endif
	int fcnt;
	char * fnam[64];
	extern char *optarg;	/* getopt */
	extern int optind;	/* getopt */
	int c;

	/* the program name start just after the last slash */
	if ((progname = (char *)strrchr(argv[0], '/')) == NULL)
		progname = argv[0];
	else
		progname++;

	/* parse the command line options */
	while ((c = getopt(argc, argv, "dvhp:")) > 0) {
		switch (c) {
		case 'v':
			show_version();
			return 0;
		case 'h':
			show_usage();
			return 1;
		case 'p':
			port = optarg;
			break;
		default:
			parse_err(optarg);
			return 2;
		}
	}

	if (optind < argc) {
		fcnt = 0;
		do {
			fnam[fcnt++] = argv[optind];
			optind++;
		} while (optind < argc);

		return ymodem_send(port, fcnt, fnam); 
	}

	return ymodem_recv(port); 
}
Example #15
0
get_nodes()
{
	int	i;

	char	buf[80];
	char	tmp[80];

	/* read nn, ni, no */
	nn = ni = no = -1;
	get_str(cfp,buf,"\n");
	/* first line must be "NODES:" */
	if (strcmp(buf, "NODES:") != 0){
		fprintf(stderr,".cf file must begin with NODES:\n");
		exit(1);
	}
	/* next three lines must specify nn, ni, and no in any order */
	for (i = 0; i < 3; i++){
		get_str(cfp,buf," ");
		get_str(cfp,tmp," ");
		if (tmp[0] != '=')
			parse_err();
		get_str(cfp,tmp,"\n");
		if (strcmp(buf, "nodes") == 0)
			nn = atoi(tmp);
		if (strcmp(buf, "inputs") == 0)
			ni = atoi(tmp);
		if (strcmp(buf, "outputs") == 0)
			no = atoi(tmp);
	}
	if ((nn < 1) || (ni < 0) || (no < 0) || (nn < no)){
		fprintf(stderr,"ERROR: Invalid specification\n\n");
		parse_err();
	}
	nt = 1 + ni + nn;
	np = 1 + ni;
}
Example #16
0
static int parse_patch_binary_nodata(
    git_patch_parsed *patch,
    git_patch_parse_ctx *ctx)
{
    if (parse_advance_expected_str(ctx, "Binary files ") < 0 ||
            parse_advance_expected_str(ctx, patch->header_old_path) < 0 ||
            parse_advance_expected_str(ctx, " and ") < 0 ||
            parse_advance_expected_str(ctx, patch->header_new_path) < 0 ||
            parse_advance_expected_str(ctx, " differ") < 0 ||
            parse_advance_nl(ctx) < 0)
        return parse_err("corrupt git binary header at line %"PRIuZ, ctx->line_num);

    patch->base.binary.contains_data = 0;
    patch->base.delta->flags |= GIT_DIFF_FLAG_BINARY;
    return 0;
}
Example #17
0
static void parse_register(struct op *op, char *base)
{
  const struct reg_name *r;
  unsigned int cap;

  op->cap_type = op->cap_id = 0;
  if (parse_x32(base, NULL, &op->addr) > 0)
    return;
  else if (r = parse_reg_name(base))
    {
      switch (r->cap & 0xff0000)
	{
	case 0x10000:
	  op->cap_type = PCI_CAP_NORMAL;
	  break;
	case 0x20000:
	  op->cap_type = PCI_CAP_EXTENDED;
	  break;
	}
      op->cap_id = r->cap & 0xffff;
      op->addr = r->offset;
      if (r->width && !op->width)
	op->width = r->width;
      return;
    }
  else if (!strncasecmp(base, "CAP", 3))
    {
      if (parse_x32(base+3, NULL, &cap) > 0 && cap < 0x100)
	{
	  op->cap_type = PCI_CAP_NORMAL;
	  op->cap_id = cap;
	  op->addr = 0;
	  return;
	}
    }
  else if (!strncasecmp(base, "ECAP", 4))
    {
      if (parse_x32(base+4, NULL, &cap) > 0 && cap < 0x1000)
	{
	  op->cap_type = PCI_CAP_EXTENDED;
	  op->cap_id = cap;
	  op->addr = 0;
	  return;
	}
    }
  parse_err("Unknown register \"%s\"", base);
}
Example #18
0
static int parse_header_mode(uint16_t *mode, git_patch_parse_ctx *ctx)
{
	const char *end;
	int32_t m;
	int ret;

	if (ctx->line_len < 1 || !git__isdigit(ctx->line[0]))
		return parse_err("invalid file mode at line %d", ctx->line_num);

	if ((ret = git__strntol32(&m, ctx->line, ctx->line_len, &end, 8)) < 0)
		return ret;

	if (m > UINT16_MAX)
		return -1;

	*mode = (uint16_t)m;

	parse_advance_chars(ctx, (end - ctx->line));

	return ret;
}
Example #19
0
static int check_prefix(
	char **out,
	size_t *out_len,
	git_patch_parsed *patch,
	const char *path_start)
{
	const char *path = path_start;
	size_t prefix_len = patch->ctx->opts.prefix_len;
	size_t remain_len = prefix_len;

	*out = NULL;
	*out_len = 0;

	if (prefix_len == 0)
		goto done;

	/* leading slashes do not count as part of the prefix in git apply */
	while (*path == '/')
		path++;

	while (*path && remain_len) {
		if (*path == '/')
			remain_len--;

		path++;
	}

	if (remain_len || !*path)
		return parse_err(
			"header filename does not contain %d path components",
			prefix_len);

done:
	*out_len = (path - path_start);
	*out = git__strndup(path_start, *out_len);

	return (out == NULL) ? -1 : 0;
}
Example #20
0
static int parse_header_oid(
	git_oid *oid,
	int *oid_len,
	git_patch_parse_ctx *ctx)
{
	size_t len;

	for (len = 0; len < ctx->line_len && len < GIT_OID_HEXSZ; len++) {
		if (!git__isxdigit(ctx->line[len]))
			break;
	}

	if (len < GIT_OID_MINPREFIXLEN ||
		git_oid_fromstrn(oid, ctx->line, len) < 0)
		return parse_err("invalid hex formatted object id at line %d",
			ctx->line_num);

	parse_advance_chars(ctx, len);

	*oid_len = (int)len;

	return 0;
}
Example #21
0
/* Returns 1 if argument consumed, 0 if all done, -1 on error. */
int parse_one(int *argc, char *argv[], unsigned *offset,
	      void (*errlog)(const char *fmt, ...))
{
	unsigned i, arg, len;
	const char *o, *optarg = NULL;
	char *problem;

	if (getenv("POSIXLY_CORRECT")) {
		/* Don't find options after non-options. */
		arg = 1;
	} else {
		for (arg = 1; argv[arg]; arg++) {
			if (argv[arg][0] == '-')
				break;
		}
	}

	if (!argv[arg] || argv[arg][0] != '-')
		return 0;

	/* Special arg terminator option. */
	if (strcmp(argv[arg], "--") == 0) {
		consume_option(argc, argv, arg);
		return 0;
	}

	/* Long options start with -- */
	if (argv[arg][1] == '-') {
		assert(*offset == 0);
		for (o = first_lopt(&i, &len); o; o = next_lopt(o, &i, &len)) {
			if (strncmp(argv[arg] + 2, o, len) != 0)
				continue;
			if (argv[arg][2 + len] == '=')
				optarg = argv[arg] + 2 + len + 1;
			else if (argv[arg][2 + len] != '\0')
				continue;
			break;
		}
		if (!o)
			return parse_err(errlog, argv[0],
					 argv[arg], strlen(argv[arg]),
					 "unrecognized option");
		/* For error messages, we include the leading '--' */
		o -= 2;
		len += 2;
	} else {
		/* offset allows us to handle -abc */
		for (o = first_sopt(&i); o; o = next_sopt(o, &i)) {
			if (argv[arg][*offset + 1] != *o)
				continue;
			(*offset)++;
			break;
		}
		if (!o)
			return parse_err(errlog, argv[0],
					 argv[arg], strlen(argv[arg]),
					 "unrecognized option");
		/* For error messages, we include the leading '-' */
		o--;
		len = 2;
	}

	if (opt_table[i].type == OPT_NOARG) {
		if (optarg)
			return parse_err(errlog, argv[0], o, len,
					 "doesn't allow an argument");
		problem = opt_table[i].cb(opt_table[i].u.arg);
	} else {
		if (!optarg) {
			/* Swallow any short options as optarg, eg -afile */
			if (*offset && argv[arg][*offset + 1]) {
				optarg = argv[arg] + *offset + 1;
				*offset = 0;
			} else
				optarg = argv[arg+1];
		}
		if (!optarg)
			return parse_err(errlog, argv[0], o, len,
					 "requires an argument");
		problem = opt_table[i].cb_arg(optarg, opt_table[i].u.arg);
	}

	if (problem) {
		parse_err(errlog, argv[0], o, len, problem);
		free(problem);
		return -1;
	}

	/* If no more letters in that short opt, reset offset. */
	if (*offset && !argv[arg][*offset + 1])
		*offset = 0;

	/* All finished with that option? */
	if (*offset == 0) {
		consume_option(argc, argv, arg);
		if (optarg && optarg == argv[arg])
			consume_option(argc, argv, arg);
	}
	return 1;
}
Example #22
0
get_connections()
{
	int	i;
	int	j;
	int	k;

	struct	cf	*ci;

	int	gn;

	float	min;
	float	max;

	char	buf[80];

	int	*tmp;
	int	*iselects;

	/* malloc space for iselects */
	iselects = (int *) malloc(nt * sizeof(int));
	if (iselects == NULL){
		perror("iselects malloc failed");
		exit(1);
	}

	get_str(cfp,buf,"\n");
	/* next line must be "CONNECTIONS:" */
	if (strcmp(buf, "CONNECTIONS:") != 0)
		parse_err();

	get_str(cfp,buf," ");

	/* next line must be "groups = #" */
	if (strcmp(buf, "groups") != 0)
		parse_err();
	get_str(cfp,buf," ");
	if (buf[0] != '=')
		parse_err();
	get_str(cfp,buf,"\n");
	ngroups = atoi(buf);

	/* malloc space for tmp */
	tmp = (int *) malloc((ngroups+1) * sizeof(int));
	if (tmp == NULL){
		perror("tmp malloc failed");
		exit(1);
	}

	get_str(cfp,buf," ");
	while (strcmp(buf, "SPECIAL:") != 0){
		/* a group is identified */
		if (strcmp(buf,"group") == 0){
			get_str(cfp,buf," ");
			get_nums(buf,ngroups,0,tmp);
			get_str(cfp,buf," ");
			if (buf[0] != '=')
				parse_err();
			get_str(cfp,buf," ");
			/* group * = fixed */
			if (strcmp(buf,"fixed") == 0){
				for (i = 0; i < nn; i++){
					ci = *(cinfo + i);
					for (j = 0; j < nt; j++, ci++){
						if (tmp[ci->num])
							ci->fix = 1;
					}
				}
			}
			/* group * = wmin & wmax */
			else {
				min = (float) atof(buf);
				get_str(cfp,buf," ");
				if (buf[0] != '&')
					parse_err();
				get_str(cfp,buf," ");
				max = (float) atof(buf);
				if (max < min){
					fprintf(stderr,"ERROR: %g < %g\n\n",max,min);
					parse_err();
				}
				for (i = 0; i < nn; i++){
					ci = *(cinfo + i);
					for (j = 0; j < nt; j++, ci++){
						if (tmp[ci->num]){
							limits = 1;
							ci->lim = 1;
							ci->min = min;
							ci->max = max;
						}
					}
				}
			}
			strcat(pbuf,"\n");
			get_str(cfp,buf," ");
		}
		/* a connection is specified */
		else {
			get_nums(buf,nn+ni,ni,selects);
			if (selects[0]){
				fprintf(stderr,"Connecting TO a bias\n\n");
				parse_err();
			}
			for (i = 1; i <= ni; i++){
				if (selects[i]){
					fprintf(stderr,"Connecting TO an input\n\n");
					parse_err();
				}
			}
			get_str(cfp,buf," ");
			if (strcmp(buf,"from") != 0)
				parse_err();
			get_str(cfp,buf," ");
			get_nums(buf,nn+ni,ni,iselects);
			for (i = 0; i < nn; i++){
				ci = *(cinfo + i);
				for (j = 0; j < nt; j++, ci++){
					if ((selects[i+ni+1]) && (iselects[j]))
						ci->con += 1;
				}
			}
			strcat(pbuf,"\t");
			get_str(cfp,buf," ");
			if (buf[0] == '='){
				get_str(cfp,buf," ");
				/* connection  = fixed */
				if (strcmp(buf,"fixed") == 0){
					for (i = 0; i < nn; i++){
						ci = *(cinfo + i);
						for (j = 0; j < nt; j++, ci++){
							if ((selects[i+ni+1]) &&
								(iselects[j]))
								ci->fix = 1;
						}
					}
				}
				else {
				    /* connection  = group # */
				    if (strcmp(buf,"group") == 0){
					get_str(cfp,buf," ");
					gn = atoi(buf);
					for (i = 0; i < nn; i++){
					    ci = *(cinfo + i);
					    for (j = 0; j < nt; j++, ci++){
						if ((selects[i+ni+1]) &&
							(iselects[j]))
							ci->num = gn;
					    }
					}
				    }
				    /* connection  = min & max */
				    else {
					min = (float) atof(buf);
					get_str(cfp,buf," ");
					if (buf[0] != '&')
						parse_err();
					get_str(cfp,buf," ");
					max = (float) atof(buf);
					if (max < min){
						fprintf(stderr,"ERROR: %g < %g\n\n",max,min);
						parse_err();
					}
					for (i = 0; i < nn; i++){
						ci = *(cinfo + i);
						for (j = 0; j < nt; j++, ci++){
							if ((selects[i+ni+1]) &&
								(iselects[j])){
								limits = 1;
								ci->lim = 1;
								ci->min = min;
								ci->max = max;
							}
						}
					}
				    }
				}
				get_str(cfp,buf,"\t");
				if (strcmp(buf,"fixed") == 0){
					for (i = 0; i < nn; i++){
						ci = *(cinfo + i);
						for (j = 0; j < nt; j++, ci++){
							if ((selects[i+ni+1]) &&
								(iselects[j]))
								ci->fix = 1;
						}
					}
					get_str(cfp,buf,"\t");
				}
				if (strcmp(buf,"one-to-one") == 0){
					for (k = 0; k < nt; k++){
						if (iselects[k])
							break;
					}
					for (i = 0; i < nn; i++){
						ci = *(cinfo + i);
						for (j = 0; j < nt; j++, ci++){
							if ((selects[i+ni+1]) &&
								(iselects[j])){
								if (ci->con == 1){
									ci->con = 0;
									ci->fix = 0;
									ci->lim = 0;
								}
								else
									ci->con -= 1;
							}
						}
						if (selects[i+np]){
							ci = *(cinfo + i) + k++;
							ci->con = 1;
							ci->fix = 1;
							ci->lim = 1;
						}
					}
					get_str(cfp,buf,"\n");
				}
			}
		}
	}
/*
	for (i = 0; i < nn; i++){
		ci = *(cinfo + i);
		for (j = 0; j < nt; j++, ci++){
			fprintf(stderr,"i: %d  j: %d  c: %d  f: %d  g: %d\n",
					i,j,ci->con,ci->fix,ci->num);
		}
	}
*/

}
Example #23
0
get_special()
{
	char	buf[80];
	char	tmp[80];

	int	i;

	int	*iselects;

	struct	nf	*n;

	/* malloc space for iselects */
	iselects = (int *) malloc(nt * sizeof(int));
	if (iselects == NULL){
		perror("iselects malloc failed");
		exit(1);
	}


	while (fscanf(cfp,"%s",buf) != EOF){
	if (strlen(pbuf) > MAX_PARSE_BUF -512) strcpy(pbuf, pbuf +512);
		strcat(pbuf,buf);
		strcat(pbuf," ");
		get_str(cfp,tmp," ");
		if (tmp[0] != '=')
			parse_err();
		get_str(cfp,tmp,"\n");
		if (strcmp(buf,"weight_limit") == 0)
			weight_limit = (float) atof(tmp);
		if (strcmp(buf,"selected") == 0){
			get_nums(tmp,nn,0,selects);
		}
		if (strcmp(buf,"linear") == 0){
			get_nums(tmp,nn,0,iselects);
			n = ninfo;
			for (i = 1; i <= nn; i++, n++){
				if (iselects[i])
					n->func = 2;
			}
		}
		if (strcmp(buf,"bipolar") == 0){
			get_nums(tmp,nn,0,iselects);
			n = ninfo;
			for (i = 1; i <= nn; i++, n++){
				if (iselects[i])
					n->func = 1;
			}
		}
		if (strcmp(buf,"binary") == 0){
			get_nums(tmp,nn,0,iselects);
			n = ninfo;
			for (i = 1; i <= nn; i++, n++){
				if (iselects[i])
					n->func = 3;
			}
		}
		if (strcmp(buf,"delayed") == 0){
			get_nums(tmp,nn,0,iselects);
			n = ninfo;
			for (i = 1; i <= nn; i++, n++){
				if (iselects[i])
					n->dela = 1;
			}
		}
	}

}
Example #24
0
asm86_t *ack_get_instruction(void)
{
	asm86_t *a= nil;
	expression_t *e;
	token_t *t;

	while ((t= get_token(0))->symbol == ';')
		skip_token(1);

	if (t->type == T_EOF) return nil;

	if (t->symbol == '#') {
		/* Preprocessor line and file change. */

		if ((t= get_token(1))->type != T_WORD || !isanumber(t->name)
			|| get_token(2)->type != T_STRING
		) {
			parse_err(1, t, "file not preprocessed?\n");
			zap();
		} else {
			set_file(get_token(2)->name,
				strtol(get_token(1)->name, nil, 0) - 1);

			/* GNU CPP adds extra cruft, simply zap the line. */
			zap();
		}
		a= ack_get_instruction();
	} else
	if (t->type == T_WORD && get_token(1)->symbol == ':') {
		/* A label definition. */
		a= new_asm86();
		a->line= t->line;
		a->opcode= DOT_LABEL;
		a->optype= PSEUDO;
		a->args= e= new_expr();
		e->operator= ':';
		e->name= copystr(t->name);
		skip_token(2);
	} else
	if (t->type == T_WORD && get_token(1)->symbol == '=') {
		int n= 2;

		if ((e= ack_get_C_expression(&n)) == nil) {
			zap();
			a= ack_get_instruction();
		} else
		if (get_token(n)->symbol != ';') {
			parse_err(1, t, "garbage after assignment\n");
			zap();
			a= ack_get_instruction();
		} else {
			a= new_asm86();
			a->line= t->line;
			a->opcode= DOT_EQU;
			a->optype= PSEUDO;
			a->args= new_expr();
			a->args->operator= '=';
			a->args->name= copystr(t->name);
			a->args->middle= e;
			skip_token(n+1);
		}
	} else
	if (t->type == T_WORD) {
		if ((a= ack_get_statement()) == nil) {
			zap();
			a= ack_get_instruction();
		}
	} else {
		parse_err(1, t, "syntax error\n");
		zap();
		a= ack_get_instruction();
	}
	return a;
}
Example #25
0
static int parse_header_git(
	git_patch_parsed *patch,
	git_patch_parse_ctx *ctx)
{
	size_t i;
	int error = 0;

	/* Parse the diff --git line */
	if (parse_advance_expected_s(ctx, "diff --git ") < 0)
		return parse_err("corrupt git diff header at line %d", ctx->line_num);

	if (parse_header_path(&patch->header_old_path, ctx) < 0)
		return parse_err("corrupt old path in git diff header at line %d",
			ctx->line_num);

	if (parse_advance_ws(ctx) < 0 ||
		parse_header_path(&patch->header_new_path, ctx) < 0)
		return parse_err("corrupt new path in git diff header at line %d",
			ctx->line_num);

	/* Parse remaining header lines */
	for (parse_advance_line(ctx);
		ctx->remain_len > 0;
		parse_advance_line(ctx)) {

		bool found = false;

		if (ctx->line_len == 0 || ctx->line[ctx->line_len - 1] != '\n')
			break;

		for (i = 0; i < ARRAY_SIZE(header_git_ops); i++) {
			const header_git_op *op = &header_git_ops[i];
			size_t op_len = strlen(op->str);

			if (memcmp(ctx->line, op->str, min(op_len, ctx->line_len)) != 0)
				continue;

			/* Do not advance if this is the patch separator */
			if (op->fn == NULL)
				goto done;

			parse_advance_chars(ctx, op_len);

			if ((error = op->fn(patch, ctx)) < 0)
				goto done;

			parse_advance_ws(ctx);
			parse_advance_expected_s(ctx, "\n");

			if (ctx->line_len > 0) {
				error = parse_err("trailing data at line %d", ctx->line_num);
				goto done;
			}

			found = true;
			break;
		}
		
		if (!found) {
			error = parse_err("invalid patch header at line %d",
				ctx->line_num);
			goto done;
		}
	}

done:
	return error;
}
Example #26
0
static asm86_t *ack_get_statement(void)
/* Get a pseudo op or machine instruction with arguments. */
{
	token_t *t= get_token(0);
	asm86_t *a;
	mnemonic_t *m;
	int n;
	int prefix_seen;
	int oaz_prefix;
	int deref;

	assert(t->type == T_WORD);

	if (strcmp(t->name, ".sect") == 0) {
		/* .sect .text etc.  Accept only four segment names. */
		skip_token(1);
		t= get_token(0);
		if (t->type != T_WORD || (
			strcmp(t->name, ".text") != 0
			&& strcmp(t->name, ".rom") != 0
			&& strcmp(t->name, ".data") != 0
			&& strcmp(t->name, ".bss") != 0
			&& strcmp(t->name, ".end") != 0
		)) {
			parse_err(1, t, "weird section name to .sect\n");
			return nil;
		}
	}
	a= new_asm86();

	/* Process instruction prefixes. */
	oaz_prefix= 0;
	for (prefix_seen= 0;; prefix_seen= 1) {
		if (strcmp(t->name, "o16") == 0) {
			if (use16()) {
				parse_err(1, t, "o16 in an 8086 section\n");
			}
			oaz_prefix|= OPZ;
		} else
		if (strcmp(t->name, "o32") == 0) {
			if (use32()) {
				parse_err(1, t, "o32 in an 80386 section\n");
			}
			oaz_prefix|= OPZ;
		} else
		if (strcmp(t->name, "a16") == 0) {
			if (use16()) {
				parse_err(1, t, "a16 in an 8086 section\n");
			}
			oaz_prefix|= ADZ;
		} else
		if (strcmp(t->name, "a32") == 0) {
			if (use32()) {
				parse_err(1, t, "a32 in an 80386 section\n");
			}
			oaz_prefix|= ADZ;
		} else
		if (strcmp(t->name, "rep") == 0
			|| strcmp(t->name, "repe") == 0
			|| strcmp(t->name, "repne") == 0
			|| strcmp(t->name, "repz") == 0
			|| strcmp(t->name, "repnz") == 0
		) {
			if (a->rep != ONCE) {
				parse_err(1, t,
					"can't have more than one rep\n");
			}
			switch (t->name[3]) {
			case 0:		a->rep= REP;	break;
			case 'e':
			case 'z':	a->rep= REPE;	break;
			case 'n':	a->rep= REPNE;	break;
			}
		} else
		if (strchr("cdefgs", t->name[0]) != nil
					&& strcmp(t->name+1, "seg") == 0) {
			if (a->seg != DEFSEG) {
				parse_err(1, t,
				"can't have more than one segment prefix\n");
			}
			switch (t->name[0]) {
			case 'c':	a->seg= CSEG;	break;
			case 'd':	a->seg= DSEG;	break;
			case 'e':	a->seg= ESEG;	break;
			case 'f':	a->seg= FSEG;	break;
			case 'g':	a->seg= GSEG;	break;
			case 's':	a->seg= SSEG;	break;
			}
		} else
		if (!prefix_seen) {
			/* No prefix here, get out! */
			break;
		} else {
			/* No more prefixes, next must be an instruction. */
			if (t->type != T_WORD
				|| (m= search_mnem(t->name)) == nil
				|| m->optype == PSEUDO
			) {
				parse_err(1, t,
		"machine instruction expected after instruction prefix\n");
				del_asm86(a);
				return nil;
			}
			if (oaz_prefix != 0 && m->optype != JUMP
						&& m->optype != WORD) {
				parse_err(1, t,
			"'%s' can't have an operand size prefix\n", m->name);
			}
			break;
		}

		/* Skip the prefix and extra newlines. */
		do {
			skip_token(1);
		} while ((t= get_token(0))->symbol == ';');
	}

	/* All the readahead being done upsets the line counter. */
	a->line= t->line;

	/* Read a machine instruction or pseudo op. */
	if ((m= search_mnem(t->name)) == nil) {
		parse_err(1, t, "unknown instruction '%s'\n", t->name);
		del_asm86(a);
		return nil;
	}
	a->opcode= m->opcode;
	a->optype= m->optype;
	a->oaz= oaz_prefix;

	switch (a->opcode) {
	case IN:
	case OUT:
	case INT:
		deref= 0;
		break;
	default:
		deref= (a->optype >= BYTE);
	}
	n= 1;
	if (get_token(1)->symbol != ';'
			&& (a->args= ack_get_oplist(&n, deref)) == nil) {
		del_asm86(a);
		return nil;
	}
	if (get_token(n)->symbol != ';') {
		parse_err(1, t, "garbage at end of instruction\n");
		del_asm86(a);
		return nil;
	}
	switch (a->opcode) {
	case DOT_ALIGN:
		/* Restrict .align to have a single numeric argument, some
		 * assemblers think of the argument as a power of two, so
		 * we need to be able to change the value.
		 */
		if (a->args == nil || a->args->operator != 'W'
					|| !isanumber(a->args->name)) {
			parse_err(1, t,
			  ".align is restricted to one numeric argument\n");
			del_asm86(a);
			return nil;
		}
		break;
	case JMPF:
	case CALLF:
		/* NCC jmpf off,seg  ->  ACK jmpf seg:off */
		if (dialect == NCC && a->args != nil
						&& a->args->operator == ',') {
			expression_t *t;

			t= a->args->left;
			a->args->left= a->args->right;
			a->args->right= t;
			break;
		}
		/*FALL THROUGH*/
	case JMP:
	case CALL:
		/* NCC jmp @(reg)  ->  ACK jmp (reg) */
		if (dialect == NCC && a->args != nil && (
			(a->args->operator == '('
				&& a->args->middle != nil
				&& a->args->middle->operator == 'O')
			|| (a->args->operator == 'O'
				&& a->args->left == nil
				&& a->args->middle != nil
				&& a->args->right == nil)
		)) {
			expression_t *t;

			t= a->args;
			a->args= a->args->middle;
			t->middle= nil;
			del_expr(t);
			if (a->args->operator == 'B') a->args->operator= 'W';
		}
		break;
	default:;
	}
	skip_token(n+1);
	return a;
}
Example #27
0
static expression_t *ack_get_operand(int *pn, int deref)
/* Get something like: (memory), offset(base)(index*scale), or simpler. */
{
	expression_t *e, *offset, *base, *index;
	token_t *t;
	int c;

	/* Is it (memory)? */
	if (get_token(*pn)->symbol == '('
		&& ((t= get_token(*pn + 1))->type != T_WORD
			|| !isregister(t->name))
	) {
		/* A memory dereference. */
		(*pn)++;
		if ((offset= ack_get_C_expression(pn)) == nil) return nil;
		if (get_token(*pn)->symbol != ')') {
			parse_err(1, t, "operand syntax error\n");
			del_expr(offset);
			return nil;
		}
		(*pn)++;
		e= new_expr();
		e->operator= '(';
		e->middle= offset;
		return e;
	}

	/* #constant? */
	if (dialect == NCC && deref
			&& ((c= get_token(*pn)->symbol) == '#' || c == '*')) {
		/* NCC: mov ax,#constant  ->  ACK: mov ax,constant */
		(*pn)++;
		return ack_get_C_expression(pn);
	}

	/* @address? */
	if (dialect == NCC && get_token(*pn)->symbol == '@') {
		/* NCC: jmp @address  ->  ACK: jmp (address) */
		(*pn)++;
		if ((offset= ack_get_operand(pn, deref)) == nil) return nil;
		e= new_expr();
		e->operator= '(';
		e->middle= offset;
		return e;
	}

	/* Offset? */
	if (get_token(*pn)->symbol != '(') {
		/* There is an offset. */
		if ((offset= ack_get_C_expression(pn)) == nil) return nil;
	} else {
		/* No offset. */
		offset= nil;
	}

	/* (base)? */
	if (get_token(*pn)->symbol == '('
		&& (t= get_token(*pn + 1))->type == T_WORD
		&& isregister(t->name)
		&& get_token(*pn + 2)->symbol == ')'
	) {
		/* A base register expression. */
		base= new_expr();
		base->operator= 'B';
		base->name= copystr(t->name);
		(*pn)+= 3;
	} else {
		/* No base register expression. */
		base= nil;
	}

	/* (index*scale)? */
	if (get_token(*pn)->symbol == '(') {
		/* An index most likely. */
		token_t *m= nil;

		if (!(		/* This must be true: */
			(t= get_token(*pn + 1))->type == T_WORD
			&& isregister(t->name)
			&& (get_token(*pn + 2)->symbol == ')' || (
				get_token(*pn + 2)->symbol == '*'
				&& (m= get_token(*pn + 3))->type == T_WORD
				&& strchr("1248", m->name[0]) != nil
				&& m->name[1] == 0
				&& get_token(*pn + 4)->symbol == ')'
			))
		)) {
			/* Alas it isn't */
			parse_err(1, t, "operand syntax error\n");
			del_expr(offset);
			del_expr(base);
			return nil;
		}
		/* Found an index. */
		index= new_expr();
		index->operator= m == nil ? '1' : m->name[0];
		index->name= copystr(t->name);
		(*pn)+= (m == nil ? 3 : 5);
	} else {
		/* No index. */
		index= nil;
	}

	if (dialect == NCC && deref && base == nil && index == nil
		&& !(offset != nil && offset->operator == 'W'
					&& isregister(offset->name))
	) {
		/* NCC: mov ax,thing  ->  ACK mov ax,(thing) */
		e= new_expr();
		e->operator= '(';
		e->middle= offset;
		return e;
	}

	if (base == nil && index == nil) {
		/* Return a lone offset as is. */
		e= offset;
	} else {
		e= new_expr();
		e->operator= 'O';
		e->left= offset;
		e->middle= base;
		e->right= index;
	}
	return e;
}
Example #28
0
static expression_t *ack_get_C_expression(int *pn)
/* Read a "C-like" expression.  Note that we don't worry about precedence,
 * the expression is printed later like it is read.  If the target language
 * does not have all the operators (like ~) then this has to be repaired by
 * changing the source file.  (No problem, you still have one source file
 * to maintain, not two.)
 */
{
	expression_t *e, *a1, *a2;
	token_t *t;

	if ((t= get_token(*pn))->symbol == '[') {
		/* [ expr ]: grouping. */
		(*pn)++;
		if ((a1= ack_get_C_expression(pn)) == nil) return nil;
		if (get_token(*pn)->symbol != ']') {
			parse_err(1, t, "missing ]\n");
			del_expr(a1);
			return nil;
		}
		(*pn)++;
		e= new_expr();
		e->operator= '[';
		e->middle= a1;
	} else
	if (t->type == T_WORD || t->type == T_STRING) {
		/* Label, number, or string. */
		e= new_expr();
		e->operator= t->type == T_WORD ? 'W' : 'S';
		e->name= allocate(nil, (t->len+1) * sizeof(e->name[0]));
		memcpy(e->name, t->name, t->len+1);
		e->len= t->len;
		(*pn)++;
	} else
	if (t->symbol == '+' || t->symbol == '-' || t->symbol == '~') {
		/* Unary operator. */
		(*pn)++;
		if ((a1= ack_get_C_expression(pn)) == nil) return nil;
		e= new_expr();
		e->operator= t->symbol;
		e->middle= a1;
	} else {
		parse_err(1, t, "expression syntax error\n");
		return nil;
	}

	switch ((t= get_token(*pn))->symbol) {
	case '+':
	case '-':
	case '*':
	case '/':
	case '%':
	case '&':
	case '|':
	case '^':
	case S_LEFTSHIFT:
	case S_RIGHTSHIFT:
		(*pn)++;
		a1= e;
		if ((a2= ack_get_C_expression(pn)) == nil) {
			del_expr(a1);
			return nil;
		}
		e= new_expr();
		e->operator= t->symbol;
		e->left= a1;
		e->right= a2;
	}
	return e;
}
Example #29
0
static int parse_hunk_body(
	git_patch_parsed *patch,
	git_patch_hunk *hunk,
	git_patch_parse_ctx *ctx)
{
	git_diff_line *line;
	int error = 0;

	int oldlines = hunk->hunk.old_lines;
	int newlines = hunk->hunk.new_lines;

	for (;
		ctx->remain_len > 4 && (oldlines || newlines) &&
		memcmp(ctx->line, "@@ -", 4) != 0;
		parse_advance_line(ctx)) {

		int origin;
		int prefix = 1;

		if (ctx->line_len == 0 || ctx->line[ctx->line_len - 1] != '\n') {
			error = parse_err("invalid patch instruction at line %d",
				ctx->line_num);
			goto done;
		}

		switch (ctx->line[0]) {
		case '\n':
			prefix = 0;

		case ' ':
			origin = GIT_DIFF_LINE_CONTEXT;
			oldlines--;
			newlines--;
			break;

		case '-':
			origin = GIT_DIFF_LINE_DELETION;
			oldlines--;
			break;

		case '+':
			origin = GIT_DIFF_LINE_ADDITION;
			newlines--;
			break;

		default:
			error = parse_err("invalid patch hunk at line %d", ctx->line_num);
			goto done;
		}

		line = git_array_alloc(patch->base.lines);
		GITERR_CHECK_ALLOC(line);

		memset(line, 0x0, sizeof(git_diff_line));

		line->content = ctx->line + prefix;
		line->content_len = ctx->line_len - prefix;
		line->content_offset = ctx->content_len - ctx->remain_len;
		line->origin = origin;

		hunk->line_count++;
	}

	if (oldlines || newlines) {
		error = parse_err(
			"invalid patch hunk, expected %d old lines and %d new lines",
			hunk->hunk.old_lines, hunk->hunk.new_lines);
		goto done;
	}

	/* Handle "\ No newline at end of file".  Only expect the leading
	 * backslash, though, because the rest of the string could be
	 * localized.  Because `diff` optimizes for the case where you
	 * want to apply the patch by hand.
	 */
	if (parse_ctx_contains_s(ctx, "\\ ") &&
		git_array_size(patch->base.lines) > 0) {

		line = git_array_get(patch->base.lines, git_array_size(patch->base.lines) - 1);

		if (line->content_len < 1) {
			error = parse_err("cannot trim trailing newline of empty line");
			goto done;
		}

		line->content_len--;

		parse_advance_line(ctx);
	}

done:
	return error;
}
Example #30
0
static int parse_patch_binary_side(
	git_diff_binary_file *binary,
	git_patch_parse_ctx *ctx)
{
	git_diff_binary_t type = GIT_DIFF_BINARY_NONE;
	git_buf base85 = GIT_BUF_INIT, decoded = GIT_BUF_INIT;
	git_off_t len;
	int error = 0;

	if (parse_ctx_contains_s(ctx, "literal ")) {
		type = GIT_DIFF_BINARY_LITERAL;
		parse_advance_chars(ctx, 8);
	} else if (parse_ctx_contains_s(ctx, "delta ")) {
		type = GIT_DIFF_BINARY_DELTA;
		parse_advance_chars(ctx, 6);
	} else {
		error = parse_err(
			"unknown binary delta type at line %d", ctx->line_num);
		goto done;
	}

	if (parse_number(&len, ctx) < 0 || parse_advance_nl(ctx) < 0 || len < 0) {
		error = parse_err("invalid binary size at line %d", ctx->line_num);
		goto done;
	}

	while (ctx->line_len) {
		char c = ctx->line[0];
		size_t encoded_len, decoded_len = 0, decoded_orig = decoded.size;

		if (c == '\n')
			break;
		else if (c >= 'A' && c <= 'Z')
			decoded_len = c - 'A' + 1;
		else if (c >= 'a' && c <= 'z')
			decoded_len = c - 'a' + (('z' - 'a') + 1) + 1;

		if (!decoded_len) {
			error = parse_err("invalid binary length at line %d", ctx->line_num);
			goto done;
		}

		parse_advance_chars(ctx, 1);

		encoded_len = ((decoded_len / 4) + !!(decoded_len % 4)) * 5;

		if (encoded_len > ctx->line_len - 1) {
			error = parse_err("truncated binary data at line %d", ctx->line_num);
			goto done;
		}

		if ((error = git_buf_decode_base85(
			&decoded, ctx->line, encoded_len, decoded_len)) < 0)
			goto done;

		if (decoded.size - decoded_orig != decoded_len) {
			error = parse_err("truncated binary data at line %d", ctx->line_num);
			goto done;
		}

		parse_advance_chars(ctx, encoded_len);

		if (parse_advance_nl(ctx) < 0) {
			error = parse_err("trailing data at line %d", ctx->line_num);
			goto done;
		}
	}

	binary->type = type;
	binary->inflatedlen = (size_t)len;
	binary->datalen = decoded.size;
	binary->data = git_buf_detach(&decoded);

done:
	git_buf_free(&base85);
	git_buf_free(&decoded);
	return error;
}