示例#1
0
static int _call_cb(const char *arg, const opts *opt, opt_error *error)
{
    int nb_arg_used = 1;

    switch (opt->has_arg)
    {
        case NO_ARG:
            if (!opt->cb(opt->long_opt, NULL, opt->user_data))
                return set_parse_error(error, -1, 0, CALLBACK_ERROR, -1);
            break;
        case OPTIONAL_ARG:
            if (!opt->cb(opt->long_opt, arg, opt->user_data))
                return set_parse_error(error, -1, 0, CALLBACK_ERROR, -1);
            nb_arg_used += arg != NULL ? 1 : 0;
            break;
        case REQUIRED_ARG:
            if (arg == NULL)
                return set_parse_error(error, -1, 0, ARG_NOT_PROVIDE, -1);
            if (!opt->cb(opt->long_opt, arg, opt->user_data))
                return set_parse_error(error, -1, 0, CALLBACK_ERROR, -1);
            ++nb_arg_used;
            break;
    }

    return nb_arg_used;
}
示例#2
0
static int parse_name(
	char **name, const char **value, git_config_parser *reader, const char *line)
{
	const char *name_end = line, *value_start;

	*name = NULL;
	*value = NULL;

	while (*name_end && is_namechar(*name_end))
		name_end++;

	if (line == name_end) {
		set_parse_error(reader, 0, "Invalid configuration key");
		return -1;
	}

	value_start = name_end;

	while (*value_start && git__isspace(*value_start))
		value_start++;

	if (*value_start == '=') {
		*value = value_start + 1;
	} else if (*value_start) {
		set_parse_error(reader, 0, "Invalid configuration key");
		return -1;
	}

	if ((*name = git__strndup(line, name_end - line)) == NULL)
		return -1;

	return 0;
}
示例#3
0
int parse_long_opt(const char *long_opt, const char *next_opt[], const opts options[], opt_error *error)
{
    const char *real_opt;
    const char *real_arg;
    int nb_arg_parsed;

    nb_arg_parsed = _split_opt_and_arg(long_opt, next_opt, &real_opt, &real_arg);
    if (nb_arg_parsed == -1)
        return -1;

    int idx = _get_opts_idx_for_opt(real_opt, options);
    if (idx == -1)
        nb_arg_parsed = set_parse_error(error, -1, 0, UNKNOWN_OPT, -1);
    else if (_call_cb(real_arg, &options[idx], error) != -1)
    {
        if (options[idx].has_arg == NO_ARG && nb_arg_parsed > 1)
            --nb_arg_parsed;
    }
    else
        nb_arg_parsed = -1;

    free((void*)real_opt);

    return nb_arg_parsed;
}
示例#4
0
static void
advance_pos (TextgenTemplate *tpl,
             const gchar *text, 
             gint length,
             gint *pos,
             gint *line,
             gint *column,
             GError **error)
{
  const gchar *next_char = g_utf8_find_next_char (text + *pos, text + length + 1);
  
  if (!next_char)
    {
      emit_message (tpl, TEXTGEN_MESSAGE_ERROR, *line, *column,
                    _("Invalid UTF-8 character"));
      set_parse_error (error);
      return;
    }
  
  if (text[*pos] == '\n')
    {
      (*line)++;
      *column = 1;
    }
  else
    (*column)++;

  *pos = next_char - text;
}
示例#5
0
static Node *
parse_list (TextgenTemplate *tpl,
            GList *tokens,
            CheckEndFunc check_end,
            GList **end, 
            GError **error)
{
  gboolean success = TRUE;
  GList *list = NULL;
  GList *l;

  l = tokens;
  while (l && !(check_end  && check_end (l)))
    {
      Token *token = l->data;
      
      if (token->type == TOKEN_TEXT)
        {
          Node *node;
          node = g_slice_new (Node);
          node->type = NODE_TEXT;
          node->value.text.text = token->content;
          node->value.text.length = token->content_length;
          token->owns_content = FALSE;

          list = g_list_prepend (list, node);
          l = l->next;
        }
      else if (token->type == TOKEN_VARIABLE)
        {
          Node *node;
          node = g_slice_new (Node);
          node->type = NODE_VARIABLE;
          node->value.variable.name = token->content;
          node->value.variable.line = token->line;
          node->value.variable.column = token->column;
          token->owns_content = FALSE;

          list = g_list_prepend (list, node);
          l = l->next;
        }
      else if (token->type == TOKEN_EXPRESSION
               || token->type == TOKEN_SCRIPT)
        {
          Node *node;
          node = g_slice_new (Node);
          node->type = token->type == TOKEN_EXPRESSION ? NODE_EXPRESSION 
                                                       : NODE_SCRIPT;
          node->value.script.code = token->content;
          node->value.script.length = token->content_length;
          node->value.script.code_line = token->line;
          node->value.script.code_column = token->content_column;
          token->owns_content = FALSE;

          list = g_list_prepend (list, node);
          l = l->next;
        }
      else if (token->type == TOKEN_COMMAND)
        {
          if (g_ascii_strcasecmp (token->command, "IF") == 0)
            {
              Node *node;
              GList *end;
              GError *tmp_error = NULL;
              
              node = parse_condition (tpl, l, &end, &tmp_error);
              if (tmp_error)
                {
                  g_propagate_error (error, tmp_error);
                  success = FALSE;
                  goto finish;
                }

              list = g_list_prepend (list, node);
              l = end->next;
            }
          else if (g_ascii_strcasecmp (token->command, "INCLUDE") == 0)
            {
              Node *node;
              node = g_slice_new (Node);
              node->type = NODE_INCLUDE;
              node->value.script.code = token->content;
              node->value.script.length = token->content_length;
              node->value.script.code_line = token->line;
              node->value.script.code_column = token->content_column;
              token->owns_content = FALSE;

              list = g_list_prepend (list, node);
              l = l->next;
            }
          else
            {
              emit_message (tpl, TEXTGEN_MESSAGE_ERROR, 
                             token->line, token->column,
                            _("Unknown command %s"), token->command);
              set_parse_error (error);
              success = FALSE;
              goto finish;
            }
        }
    }

  if (end)
    *end = l;

finish:
  if (success)
    {
      Node *node = g_slice_new (Node);
      node->type = NODE_LIST;
      node->value.list = g_list_reverse (list);
      return node;
    }
  else
    {
      g_list_free_full (list, free_node);
      return NULL;
    }
}
示例#6
0
static Node *
parse_condition (TextgenTemplate *tpl,
                 GList *tokens,
                 GList **end, 
                 GError **error)
{
  Token *start_token = tokens->data;
  Token *end_token;
  gboolean success = TRUE;
  Node *if_true = NULL;
  Node *if_false = NULL;
  GList *tmp_end = NULL;
  GError *tmp_error = NULL;
  
  if_true = parse_list (tpl, tokens->next, check_condition_if_true_end, &tmp_end, &tmp_error);
  if (tmp_error != NULL)
    {
      success = FALSE;
      g_propagate_error (error, tmp_error);
      goto finish;
    }

  if (tmp_end == NULL)
    {
      emit_message (tpl, TEXTGEN_MESSAGE_ERROR, 
                    start_token->line, start_token->column,
                    _("Could not find ENDIF of the condition"));
      set_parse_error (error);
      success = FALSE;
      goto finish;
    }

  end_token = tmp_end->data;

  if (g_ascii_strcasecmp (end_token->command, "ELSEIF") == 0)
    {
      if_false = parse_condition (tpl, tmp_end, &tmp_end, &tmp_error);
      if (tmp_error)
        {
          g_propagate_error (error, tmp_error);
          success = FALSE;
          goto finish;
        }
    }
  else if (g_ascii_strcasecmp (end_token->command, "ELSE") == 0)
    {
      if_false = parse_list (tpl, tmp_end->next, check_condition_if_false_end, &tmp_end, &tmp_error);
      if (tmp_error)
        {
          g_propagate_error (error, tmp_error);
          success = FALSE;
          goto finish;
        }

      if (tmp_end == NULL)
        {
          emit_message (tpl, TEXTGEN_MESSAGE_ERROR, 
                        start_token->line, start_token->column,
                        _("Could not find ENDIF of the condition"));
          set_parse_error (error);
          success = FALSE;
          goto finish;
        }
    }

finish:
  if (success)
    {
      Node *node;
      node = g_slice_new (Node);
      node->type = NODE_CONDITION;
      node->value.cond.code = start_token->content;
      node->value.cond.length = start_token->content_length;
      node->value.cond.if_true = if_true;
      node->value.cond.if_false = if_false;
      node->value.cond.code_line = start_token->line;
      node->value.cond.code_column = start_token->column;
      start_token->owns_content = FALSE;
      *end = tmp_end;
      return node;
    }
  else
    {
      if (if_true) free_node (if_true);
      if (if_false) free_node (if_false);
      return FALSE;
    }
}
示例#7
0
static Token *
maybe_parse_instruction (TextgenTemplate *tpl,
                         const gchar *text, 
                         gint length,
                         gint start,
                         gint start_line,
                         gint start_column,
                         gboolean *ignore_empty_line,
                         gint *after_end,
                         gint *after_end_line,
                         gint *after_end_column,
                         GError **error)
{
  gboolean success = TRUE;
  gboolean found_end = FALSE;
  gchar instr;
  gint content_offset;
  gchar *command = NULL;
  gchar *content = NULL;
  gint content_length;
  gint pos = start;
  gint cur_line = start_line;
  gint cur_column = start_column;
  GError *tmp_error = NULL;

  if (start < length - 1 && text[start] == '[')
    {
      if (text[start + 1] == '!')
        {
          *ignore_empty_line = TRUE;
          instr = text[start + 2];
          content_offset = 3;
        }
      else
        {
          *ignore_empty_line = FALSE;
          instr = text[start + 1];
          content_offset = 2;
        }
    
      if (!IS_VALID_INSTRUCTION_CHAR (instr))
        return NULL;
    }
  else
    return NULL;

  pos += content_offset;
  cur_column += content_offset;

  while (pos < length)
    {
      if (pos < length - 1 && text[pos] == instr && text[pos + 1] == ']')
        {
          gint content_start = start + content_offset;
          content_length = pos - content_start;
          content = g_strndup (text + content_start, content_length);
          *after_end = pos + 2;
          cur_column += 2;
          found_end = TRUE;
          break;
        }

      advance_pos (tpl, text, length, &pos, &cur_line, &cur_column, &tmp_error);
      if (tmp_error)
        {
          g_propagate_error (error, tmp_error);
          success = FALSE;
          goto finish;
        }
    }

  if (!found_end)
    {
      emit_message (tpl, TEXTGEN_MESSAGE_ERROR, start_line, start_column,
                    _("Could not find the end of the instruction"), instr);
      set_parse_error (error);
      success = FALSE;
      goto finish;
    }

  if (instr == TOKEN_COMMAND)
    {
      static GRegex *regex = NULL;
      GMatchInfo *match_info;
      gchar *old_content = content;
      gint start_pos;
      gint end_pos;

      if (!regex)
        regex = g_regex_new ("^\\s*([A-Za-z]+)\\s+(.*)$", G_REGEX_MULTILINE | G_REGEX_OPTIMIZE, 0, NULL);

      if (!g_regex_match (regex, old_content, 0, &match_info))
        {
          emit_message (tpl, TEXTGEN_MESSAGE_ERROR, start_line, start_column,
                        _("A command must look like this: [# COMMAND content #]"));
          set_parse_error (error);
          success = FALSE;
          goto finish;
        }

      command = g_match_info_fetch (match_info, 1);
      content = g_match_info_fetch (match_info, 2);

      g_match_info_fetch_pos (match_info, 2, &start_pos, &end_pos);
      content_length = end_pos - start_pos;
      
      g_match_info_free (match_info);
      g_free (old_content);
    }

  *after_end_line = cur_line;
  *after_end_column = cur_column;

finish:
  if (success)
    {
      Token *token = g_slice_new (Token);
      token->type = instr;
      token->command = command;
      token->content = content;
      token->content_length = content_length;
      token->line = start_line;
      token->column = start_column;
      token->content_column = start_column + content_offset;
      token->owns_content = TRUE;
      token->owns_command = TRUE;
      return token;
    }
  else
    {
      g_free (command);
      g_free (content);
      return NULL;
    }
}
示例#8
0
static int parse_section_header_ext(git_config_parser *reader, const char *line, const char *base_name, char **section_name)
{
	int c, rpos;
	char *first_quote, *last_quote;
	git_buf buf = GIT_BUF_INIT;
	size_t quoted_len, alloc_len, base_name_len = strlen(base_name);

	/*
	 * base_name is what came before the space. We should be at the
	 * first quotation mark, except for now, line isn't being kept in
	 * sync so we only really use it to calculate the length.
	 */

	first_quote = strchr(line, '"');
	if (first_quote == NULL) {
		set_parse_error(reader, 0, "Missing quotation marks in section header");
		goto end_error;
	}

	last_quote = strrchr(line, '"');
	quoted_len = last_quote - first_quote;

	if (quoted_len == 0) {
		set_parse_error(reader, 0, "Missing closing quotation mark in section header");
		goto end_error;
	}

	GITERR_CHECK_ALLOC_ADD(&alloc_len, base_name_len, quoted_len);
	GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);

	if (git_buf_grow(&buf, alloc_len) < 0 ||
	    git_buf_printf(&buf, "%s.", base_name) < 0)
		goto end_error;

	rpos = 0;

	line = first_quote;
	c = line[++rpos];

	/*
	 * At the end of each iteration, whatever is stored in c will be
	 * added to the string. In case of error, jump to out
	 */
	do {

		switch (c) {
		case 0:
			set_parse_error(reader, 0, "Unexpected end-of-line in section header");
			goto end_error;

		case '"':
			goto end_parse;

		case '\\':
			c = line[++rpos];

			if (c == 0) {
				set_parse_error(reader, rpos, "Unexpected end-of-line in section header");
				goto end_error;
			}

		default:
			break;
		}

		git_buf_putc(&buf, (char)c);
		c = line[++rpos];
	} while (line + rpos < last_quote);

end_parse:
	if (git_buf_oom(&buf))
		goto end_error;

	if (line[rpos] != '"' || line[rpos + 1] != ']') {
		set_parse_error(reader, rpos, "Unexpected text after closing quotes");
		git_buf_free(&buf);
		return -1;
	}

	*section_name = git_buf_detach(&buf);
	return 0;

end_error:
	git_buf_free(&buf);

	return -1;
}
示例#9
0
static int parse_section_header(git_config_parser *reader, char **section_out)
{
	char *name, *name_end;
	int name_length, c, pos;
	int result;
	char *line;
	size_t line_len;

	git_parse_advance_ws(&reader->ctx);
	line = git__strndup(reader->ctx.line, reader->ctx.line_len);
	if (line == NULL)
		return -1;

	/* find the end of the variable's name */
	name_end = strrchr(line, ']');
	if (name_end == NULL) {
		git__free(line);
		set_parse_error(reader, 0, "Missing ']' in section header");
		return -1;
	}

	GITERR_CHECK_ALLOC_ADD(&line_len, (size_t)(name_end - line), 1);
	name = git__malloc(line_len);
	GITERR_CHECK_ALLOC(name);

	name_length = 0;
	pos = 0;

	/* Make sure we were given a section header */
	c = line[pos++];
	assert(c == '[');

	c = line[pos++];

	do {
		if (git__isspace(c)){
			name[name_length] = '\0';
			result = parse_section_header_ext(reader, line, name, section_out);
			git__free(line);
			git__free(name);
			return result;
		}

		if (!config_keychar(c) && c != '.') {
			set_parse_error(reader, pos, "Unexpected character in header");
			goto fail_parse;
		}

		name[name_length++] = (char)git__tolower(c);

	} while ((c = line[pos++]) != ']');

	if (line[pos - 1] != ']') {
		set_parse_error(reader, pos, "Unexpected end of file");
		goto fail_parse;
	}

	git__free(line);

	name[name_length] = 0;
	*section_out = name;

	return 0;

fail_parse:
	git__free(line);
	git__free(name);
	return -1;
}