Example #1
0
/// Append one byte to a growarray which contains bytes.
///
/// @param gap
/// @param c
void ga_append(garray_T *gap, int c)
{
    if (ga_grow(gap, 1) == OK) {
        *((char *) gap->ga_data + gap->ga_len) = c;
        ++gap->ga_len;
    }
}
Example #2
0
// Initialize users garray and fill it with os usernames.
// Return Ok for success, FAIL for failure.
int os_get_usernames(garray_T *users)
{
  if (users == NULL) {
    return FAIL;
  }
  ga_init(users, sizeof(char *), 20);

# if defined(HAVE_GETPWENT) && defined(HAVE_PWD_H)
  char *user;
  struct passwd *pw;

  setpwent();
  while ((pw = getpwent()) != NULL) {
    // pw->pw_name shouldn't be NULL but just in case...
    if (pw->pw_name != NULL) {
      ga_grow(users, 1);
      user = xstrdup(pw->pw_name);
      ((char **)(users->ga_data))[users->ga_len++] = user;
    }
  }
  endpwent();
# endif

  return OK;
}
Example #3
0
/// Concatenate a string to a growarray which contains characters.
/// Note: Does NOT copy the NUL at the end!
///
/// @param gap
/// @param s
void ga_concat(garray_T *gap, char_u *s)
{
    int len = (int)STRLEN(s);
    if (ga_grow(gap, len) == OK) {
        mch_memmove((char *)gap->ga_data + gap->ga_len, s, (size_t)len);
        gap->ga_len += len;
    }
}
Example #4
0
/// Add the digraphs in the argument to the digraph table.
/// format: {c1}{c2} char {c1}{c2} char ...
///
/// @param str
void putdigraph(char_u *str)
{
  int char1, char2, n;
  int i;
  digr_T *dp;

  while (*str != NUL) {
    str = skipwhite(str);

    if (*str == NUL) {
      return;
    }
    char1 = *str++;
    char2 = *str++;

    if (char2 == 0) {
      EMSG(_(e_invarg));
      return;
    }

    if ((char1 == ESC) || (char2 == ESC)) {
      EMSG(_("E104: Escape not allowed in digraph"));
      return;
    }
    str = skipwhite(str);

    if (!VIM_ISDIGIT(*str)) {
      EMSG(_(e_number_exp));
      return;
    }
    n = getdigits(&str);

    // If the digraph already exists, replace the result.
    dp = (digr_T *)user_digraphs.ga_data;

    for (i = 0; i < user_digraphs.ga_len; ++i) {
      if (((int)dp->char1 == char1) && ((int)dp->char2 == char2)) {
        dp->result = n;
        break;
      }
      ++dp;
    }

    // Add a new digraph to the table.
    if (i == user_digraphs.ga_len) {
      ga_grow(&user_digraphs, 1);
      dp = (digr_T *)user_digraphs.ga_data + user_digraphs.ga_len;
      dp->char1 = char1;
      dp->char2 = char2;
      dp->result = n;
      ++user_digraphs.ga_len;
    }
  }
}
Example #5
0
/*
 * ":menutrans".
 * This function is also defined without the +multi_lang feature, in which
 * case the commands are ignored.
 */
void ex_menutranslate(exarg_T *eap)
{
  char_u              *arg = eap->arg;
  menutrans_T         *tp;
  char_u              *from, *from_noamp, *to;

  if (menutrans_ga.ga_itemsize == 0)
    ga_init(&menutrans_ga, (int)sizeof(menutrans_T), 5);

  /*
   * ":menutrans clear": clear all translations.
   */
  if (STRNCMP(arg, "clear", 5) == 0 && ends_excmd(*skipwhite(arg + 5))) {
    tp = (menutrans_T *)menutrans_ga.ga_data;
    for (int i = 0; i < menutrans_ga.ga_len; ++i) {
      free(tp[i].from);
      free(tp[i].from_noamp);
      free(tp[i].to);
    }
    ga_clear(&menutrans_ga);
    /* Delete all "menutrans_" global variables. */
    del_menutrans_vars();
  } else {
    /* ":menutrans from to": add translation */
    from = arg;
    arg = menu_skip_part(arg);
    to = skipwhite(arg);
    *arg = NUL;
    arg = menu_skip_part(to);
    if (arg == to)
      EMSG(_(e_invarg));
    else {
      ga_grow(&menutrans_ga, 1);
      tp = (menutrans_T *)menutrans_ga.ga_data;
      from = vim_strsave(from);
      from_noamp = menu_text(from, NULL, NULL);
      to = vim_strnsave(to, (int)(arg - to));
      if (from_noamp != NULL) {
        menu_translate_tab_and_shift(from);
        menu_translate_tab_and_shift(to);
        menu_unescape_name(from);
        menu_unescape_name(to);
        tp[menutrans_ga.ga_len].from = from;
        tp[menutrans_ga.ga_len].from_noamp = from_noamp;
        tp[menutrans_ga.ga_len].to = to;
        ++menutrans_ga.ga_len;
      } else {
        free(from);
        free(from_noamp);
        free(to);
      }
    }
  }
}
Example #6
0
/*
 * Read "blob" from file "fd".
 * Return OK or FAIL.
 */
    int
read_blob(FILE *fd, blob_T *blob)
{
    struct stat	st;

    if (fstat(fileno(fd), &st) < 0)
	return FAIL;
    if (ga_grow(&blob->bv_ga, st.st_size) == FAIL)
	return FAIL;
    blob->bv_ga.ga_len = st.st_size;
    if (fread(blob->bv_ga.ga_data, 1, blob->bv_ga.ga_len, fd)
						  < (size_t)blob->bv_ga.ga_len)
	return FAIL;
    return OK;
}
Example #7
0
static VimRemotingClient_ServerReply *findReply(VimRemotingClient *client, Window w, enum VimRemotingClient_ServerReplyOp op)
{
    VimRemotingClient_ServerReply *p;
    VimRemotingClient_ServerReply e;
    int i;

    p = (VimRemotingClient_ServerReply *) serverReply.ga_data;

    i = 0;
    while (i < serverReply.ga_len) {
        if (p->id == w)
            break;
        i++, p++;
    }

    if (i >= serverReply.ga_len)
        p = NULL;

    if (p == NULL && op == SROP_Add)
    {
        if (serverReply.ga_growsize == 0)
            ga_init2(&serverReply, sizeof(VimRemotingClient_ServerReply), 1);
        if (ga_grow(&serverReply, 1) == OK)
        {
            p = ((VimRemotingClient_ServerReply *) serverReply.ga_data)
                + serverReply.ga_len;
            e.id = w;
            ga_init2(&e.strings, 1, 100);
            memmove(p, &e, sizeof(e));
            serverReply.ga_len++;
        }
    }
    else if (p != NULL && op == SROP_Delete)
    {
        ga_clear(&p->strings);
        memmove(p, p + 1, (serverReply.ga_len - i - 1) * sizeof(*p));
        serverReply.ga_len--;
    }

    return p;
}
Example #8
0
/*
 * Split a string into parts to display in the balloon.
 * Aimed at output from gdb.  Attempts to split at white space, preserve quoted
 * strings and make a struct look good.
 * Resulting array is stored in "array" and returns the size of the array.
 */
    int
split_message(char_u *mesg, pumitem_T **array)
{
    garray_T	ga;
    char_u	*p;
    balpart_T	*item;
    int		quoted = FALSE;
    int		height;
    int		line;
    int		item_idx;
    int		indent = 0;
    int		max_cells = 0;
    int		max_height = Rows / 2 - 2;
    int		long_item_count = 0;
    int		split_long_items = FALSE;

    ga_init2(&ga, sizeof(balpart_T), 20);
    p = mesg;

    while (*p != NUL)
    {
	if (ga_grow(&ga, 1) == FAIL)
	    goto failed;
	item = ((balpart_T *)ga.ga_data) + ga.ga_len;
	item->start = p;
	item->indent = indent;
	item->cells = indent * 2;
	++ga.ga_len;
	while (*p != NUL)
	{
	    if (*p == '"')
		quoted = !quoted;
	    else if (*p == '\\' && p[1] != NUL)
		++p;
	    else if (!quoted)
	    {
		if ((*p == ',' && p[1] == ' ') || *p == '{' || *p == '}')
		{
		    /* Looks like a good point to break. */
		    if (*p == '{')
			++indent;
		    else if (*p == '}' && indent > 0)
			--indent;
		    ++item->cells;
		    p = skipwhite(p + 1);
		    break;
		}
	    }
	    item->cells += ptr2cells(p);
	    p += MB_PTR2LEN(p);
	}
	item->bytelen = p - item->start;
	if (item->cells > max_cells)
	    max_cells = item->cells;
	long_item_count += (item->cells - 1) / BALLOON_MIN_WIDTH;
    }

    height = 2 + ga.ga_len;

    /* If there are long items and the height is below the limit: split lines */
    if (long_item_count > 0 && height + long_item_count <= max_height)
    {
	split_long_items = TRUE;
	height += long_item_count;
    }

    /* Limit to half the window height, it has to fit above or below the mouse
     * position. */
    if (height > max_height)
	height = max_height;
    *array = (pumitem_T *)alloc_clear((unsigned)sizeof(pumitem_T) * height);
    if (*array == NULL)
	goto failed;

    /* Add an empty line above and below, looks better. */
    (*array)->pum_text = vim_strsave((char_u *)"");
    (*array + height - 1)->pum_text = vim_strsave((char_u *)"");

    for (line = 1, item_idx = 0; line < height - 1; ++item_idx)
    {
	int	skip;
	int	thislen;
	int	copylen;
	int	ind;
	int	cells;

	item = ((balpart_T *)ga.ga_data) + item_idx;
	for (skip = 0; skip < item->bytelen; skip += thislen)
	{
	    if (split_long_items && item->cells >= BALLOON_MIN_WIDTH)
	    {
		cells = item->indent * 2;
		for (p = item->start + skip; p < item->start + item->bytelen;
							    p += MB_PTR2LEN(p))
		    if ((cells += ptr2cells(p)) > BALLOON_MIN_WIDTH)
			break;
		thislen = p - (item->start + skip);
	    }
	    else
		thislen = item->bytelen;

	    /* put indent at the start */
	    p = alloc(thislen + item->indent * 2 + 1);
	    for (ind = 0; ind < item->indent * 2; ++ind)
		p[ind] = ' ';

	    /* exclude spaces at the end of the string */
	    for (copylen = thislen; copylen > 0; --copylen)
		if (item->start[skip + copylen - 1] != ' ')
		    break;

	    vim_strncpy(p + ind, item->start + skip, copylen);
	    (*array)[line].pum_text = p;
	    item->indent = 0;  /* wrapped line has no indent */
	    ++line;
	}
    }
    ga_clear(&ga);
    return height;

failed:
    ga_clear(&ga);
    return 0;
}
Example #9
0
/*
 * Decode one item and put it in "res".  If "res" is NULL only advance.
 * Must already have skipped white space.
 *
 * Return FAIL for a decoding error (and give an error).
 * Return MAYBE for an incomplete message.
 */
    static int
json_decode_item(js_read_T *reader, typval_T *res, int options)
{
    char_u	*p;
    int		len;
    int		retval;
    garray_T	stack;
    typval_T	item;
    typval_T	*cur_item;
    json_dec_item_T *top_item;
    char_u	key_buf[NUMBUFLEN];

    ga_init2(&stack, sizeof(json_dec_item_T), 100);
    cur_item = res;
    init_tv(&item);
    if (res != NULL)
    init_tv(res);

    fill_numbuflen(reader);
    p = reader->js_buf + reader->js_used;
    for (;;)
    {
	top_item = NULL;
	if (stack.ga_len > 0)
	{
	    top_item = ((json_dec_item_T *)stack.ga_data) + stack.ga_len - 1;
	    json_skip_white(reader);
	    p = reader->js_buf + reader->js_used;
	    if (*p == NUL)
	    {
		retval = MAYBE;
		if (top_item->jd_type == JSON_OBJECT)
		    /* did get the key, clear it */
		    clear_tv(&top_item->jd_key_tv);
		goto theend;
	    }
	    if (top_item->jd_type == JSON_OBJECT_KEY
					    || top_item->jd_type == JSON_ARRAY)
	    {
		/* Check for end of object or array. */
		if (*p == (top_item->jd_type == JSON_ARRAY ? ']' : '}'))
		{
		    ++reader->js_used; /* consume the ']' or '}' */
		    --stack.ga_len;
		    if (stack.ga_len == 0)
		    {
			retval = OK;
			goto theend;
		    }
		    if (cur_item != NULL)
			cur_item = &top_item->jd_tv;
		    goto item_end;
		}
	    }
	}

	if (top_item != NULL && top_item->jd_type == JSON_OBJECT_KEY
		&& (options & JSON_JS)
		&& reader->js_buf[reader->js_used] != '"'
		&& reader->js_buf[reader->js_used] != '\''
		&& reader->js_buf[reader->js_used] != '['
		&& reader->js_buf[reader->js_used] != '{')
	{
	    char_u *key;

	    /* accept an object key that is not in quotes */
	    key = p = reader->js_buf + reader->js_used;
	    while (*p != NUL && *p != ':' && *p > ' ')
		++p;
	    if (cur_item != NULL)
	    {
		cur_item->v_type = VAR_STRING;
		cur_item->vval.v_string = vim_strnsave(key, (int)(p - key));
		top_item->jd_key = cur_item->vval.v_string;
	    }
	    reader->js_used += (int)(p - key);
	}
	else
	{
	    switch (*p)
	    {
		case '[': /* start of array */
		    if (top_item && top_item->jd_type == JSON_OBJECT_KEY)
		    {
			retval = FAIL;
			break;
		    }
		    if (ga_grow(&stack, 1) == FAIL)
		    {
			retval = FAIL;
			break;
		    }
		    if (cur_item != NULL && rettv_list_alloc(cur_item) == FAIL)
		    {
			cur_item->v_type = VAR_SPECIAL;
			cur_item->vval.v_number = VVAL_NONE;
			retval = FAIL;
			break;
		    }

		    ++reader->js_used; /* consume the '[' */
		    top_item = ((json_dec_item_T *)stack.ga_data)
								+ stack.ga_len;
		    top_item->jd_type = JSON_ARRAY;
		    ++stack.ga_len;
		    if (cur_item != NULL)
		    {
			top_item->jd_tv = *cur_item;
			cur_item = &item;
		    }
		    continue;

		case '{': /* start of object */
		    if (top_item && top_item->jd_type == JSON_OBJECT_KEY)
		    {
			retval = FAIL;
			break;
		    }
		    if (ga_grow(&stack, 1) == FAIL)
		    {
			retval = FAIL;
			break;
		    }
		    if (cur_item != NULL && rettv_dict_alloc(cur_item) == FAIL)
		    {
			cur_item->v_type = VAR_SPECIAL;
			cur_item->vval.v_number = VVAL_NONE;
			retval = FAIL;
			break;
		    }

		    ++reader->js_used; /* consume the '{' */
		    top_item = ((json_dec_item_T *)stack.ga_data)
								+ stack.ga_len;
		    top_item->jd_type = JSON_OBJECT_KEY;
		    ++stack.ga_len;
		    if (cur_item != NULL)
		    {
			top_item->jd_tv = *cur_item;
			cur_item = &top_item->jd_key_tv;
		    }
		    continue;

		case '"': /* string */
		    retval = json_decode_string(reader, cur_item, *p);
		    break;

		case '\'':
		    if (options & JSON_JS)
			retval = json_decode_string(reader, cur_item, *p);
		    else
		    {
			EMSG(_(e_invarg));
			retval = FAIL;
		    }
		    break;

		case ',': /* comma: empty item */
		    if ((options & JSON_JS) == 0)
		    {
			EMSG(_(e_invarg));
			retval = FAIL;
			break;
		    }
		    /* FALLTHROUGH */
		case NUL: /* empty */
		    if (cur_item != NULL)
		    {
			cur_item->v_type = VAR_SPECIAL;
			cur_item->vval.v_number = VVAL_NONE;
		    }
		    retval = OK;
		    break;

		default:
		    if (VIM_ISDIGIT(*p) || *p == '-')
		    {
#ifdef FEAT_FLOAT
			char_u  *sp = p;

			if (*sp == '-')
			{
			    ++sp;
			    if (*sp == NUL)
			    {
				retval = MAYBE;
				break;
			    }
			    if (!VIM_ISDIGIT(*sp))
			    {
				EMSG(_(e_invarg));
				retval = FAIL;
				break;
			    }
			}
			sp = skipdigits(sp);
			if (*sp == '.' || *sp == 'e' || *sp == 'E')
			{
			    if (cur_item == NULL)
			    {
				float_T f;

				len = string2float(p, &f);
			    }
			    else
			    {
				cur_item->v_type = VAR_FLOAT;
				len = string2float(p, &cur_item->vval.v_float);
			    }
			}
			else
#endif
			{
			    varnumber_T nr;

			    vim_str2nr(reader->js_buf + reader->js_used,
				    NULL, &len, 0, /* what */
				    &nr, NULL, 0);
			    if (cur_item != NULL)
			    {
				cur_item->v_type = VAR_NUMBER;
				cur_item->vval.v_number = nr;
			    }
			}
			reader->js_used += len;
			retval = OK;
			break;
		    }
		    if (STRNICMP((char *)p, "false", 5) == 0)
		    {
			reader->js_used += 5;
			if (cur_item != NULL)
			{
			    cur_item->v_type = VAR_SPECIAL;
			    cur_item->vval.v_number = VVAL_FALSE;
			}
			retval = OK;
			break;
		    }
		    if (STRNICMP((char *)p, "true", 4) == 0)
		    {
			reader->js_used += 4;
			if (cur_item != NULL)
			{
			    cur_item->v_type = VAR_SPECIAL;
			    cur_item->vval.v_number = VVAL_TRUE;
			}
			retval = OK;
			break;
		    }
		    if (STRNICMP((char *)p, "null", 4) == 0)
		    {
			reader->js_used += 4;
			if (cur_item != NULL)
			{
			    cur_item->v_type = VAR_SPECIAL;
			    cur_item->vval.v_number = VVAL_NULL;
			}
			retval = OK;
			break;
		    }
#ifdef FEAT_FLOAT
		    if (STRNICMP((char *)p, "NaN", 3) == 0)
		    {
			reader->js_used += 3;
			if (cur_item != NULL)
			{
			    cur_item->v_type = VAR_FLOAT;
			    cur_item->vval.v_float = NAN;
			}
			retval = OK;
			break;
		    }
		    if (STRNICMP((char *)p, "Infinity", 8) == 0)
		    {
			reader->js_used += 8;
			if (cur_item != NULL)
			{
			    cur_item->v_type = VAR_FLOAT;
			    cur_item->vval.v_float = INFINITY;
			}
			retval = OK;
			break;
		    }
#endif
		    /* check for truncated name */
		    len = (int)(reader->js_end - (reader->js_buf + reader->js_used));
		    if (
			    (len < 5 && STRNICMP((char *)p, "false", len) == 0)
#ifdef FEAT_FLOAT
			    || (len < 8 && STRNICMP((char *)p, "Infinity", len) == 0)
			    || (len < 3 && STRNICMP((char *)p, "NaN", len) == 0)
#endif
			    || (len < 4 && (STRNICMP((char *)p, "true", len) == 0
				       ||  STRNICMP((char *)p, "null", len) == 0)))

			retval = MAYBE;
		    else
			retval = FAIL;
		    break;
	    }

	    /* We are finished when retval is FAIL or MAYBE and when at the
	     * toplevel. */
	    if (retval == FAIL)
		break;
	    if (retval == MAYBE || stack.ga_len == 0)
		goto theend;

	    if (top_item != NULL && top_item->jd_type == JSON_OBJECT_KEY
		    && cur_item != NULL)
	    {
		top_item->jd_key = get_tv_string_buf_chk(cur_item, key_buf);
		if (top_item->jd_key == NULL)
		{
		    clear_tv(cur_item);
		    EMSG(_(e_invarg));
		    retval = FAIL;
		    goto theend;
		}
	    }
	}

item_end:
	top_item = ((json_dec_item_T *)stack.ga_data) + stack.ga_len - 1;
	switch (top_item->jd_type)
	{
	    case JSON_ARRAY:
		if (res != NULL)
		{
		    listitem_T	*li = listitem_alloc();

		    if (li == NULL)
		    {
			clear_tv(cur_item);
			retval = FAIL;
			goto theend;
		    }
		    li->li_tv = *cur_item;
		    list_append(top_item->jd_tv.vval.v_list, li);
		}
		if (cur_item != NULL)
		    cur_item = &item;

		json_skip_white(reader);
		p = reader->js_buf + reader->js_used;
		if (*p == ',')
		    ++reader->js_used;
		else if (*p != ']')
		{
		    if (*p == NUL)
			retval = MAYBE;
		    else
		    {
			EMSG(_(e_invarg));
			retval = FAIL;
		    }
		    goto theend;
		}
		break;

	    case JSON_OBJECT_KEY:
		json_skip_white(reader);
		p = reader->js_buf + reader->js_used;
		if (*p != ':')
		{
		    if (cur_item != NULL)
			clear_tv(cur_item);
		    if (*p == NUL)
			retval = MAYBE;
		    else
		    {
			EMSG(_(e_invarg));
			retval = FAIL;
		    }
		    goto theend;
		}
		++reader->js_used;
		json_skip_white(reader);
		top_item->jd_type = JSON_OBJECT;
		if (cur_item != NULL)
		    cur_item = &item;
		break;

	    case JSON_OBJECT:
		if (cur_item != NULL
			&& dict_find(top_item->jd_tv.vval.v_dict,
						 top_item->jd_key, -1) != NULL)
		{
		    EMSG2(_("E938: Duplicate key in JSON: \"%s\""),
							     top_item->jd_key);
		    clear_tv(&top_item->jd_key_tv);
		    clear_tv(cur_item);
		    retval = FAIL;
		    goto theend;
		}

		if (cur_item != NULL)
		{
		    dictitem_T *di = dictitem_alloc(top_item->jd_key);

		    clear_tv(&top_item->jd_key_tv);
		    if (di == NULL)
		    {
			clear_tv(cur_item);
			retval = FAIL;
			goto theend;
		    }
		    di->di_tv = *cur_item;
		    di->di_tv.v_lock = 0;
		    if (dict_add(top_item->jd_tv.vval.v_dict, di) == FAIL)
		    {
			dictitem_free(di);
			retval = FAIL;
			goto theend;
		    }
		}

		json_skip_white(reader);
		p = reader->js_buf + reader->js_used;
		if (*p == ',')
		    ++reader->js_used;
		else if (*p != '}')
		{
		    if (*p == NUL)
			retval = MAYBE;
		    else
		    {
			EMSG(_(e_invarg));
			retval = FAIL;
		    }
		    goto theend;
		}
		top_item->jd_type = JSON_OBJECT_KEY;
		if (cur_item != NULL)
		    cur_item = &top_item->jd_key_tv;
		break;
	}
    }

    /* Get here when parsing failed. */
    if (res != NULL)
    {
	clear_tv(res);
	res->v_type = VAR_SPECIAL;
	res->vval.v_number = VVAL_NONE;
    }
    EMSG(_(e_invarg));

theend:
    ga_clear(&stack);
    return retval;
}
Example #10
0
    static int
json_decode_string(js_read_T *reader, typval_T *res, int quote)
{
    garray_T    ga;
    int		len;
    char_u	*p;
    int		c;
    varnumber_T	nr;

    if (res != NULL)
	ga_init2(&ga, 1, 200);

    p = reader->js_buf + reader->js_used + 1; /* skip over " or ' */
    while (*p != quote)
    {
	/* The JSON is always expected to be utf-8, thus use utf functions
	 * here. The string is converted below if needed. */
	if (*p == NUL || p[1] == NUL
#ifdef FEAT_MBYTE
		|| utf_ptr2len(p) < utf_byte2len(*p)
#endif
		)
	{
	    /* Not enough bytes to make a character or end of the string. Get
	     * more if possible. */
	    if (reader->js_fill == NULL)
		break;
	    len = (int)(reader->js_end - p);
	    reader->js_used = (int)(p - reader->js_buf);
	    if (!reader->js_fill(reader))
		break; /* didn't get more */
	    p = reader->js_buf + reader->js_used;
	    reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
	    continue;
	}

	if (*p == '\\')
	{
	    c = -1;
	    switch (p[1])
	    {
		case '\\': c = '\\'; break;
		case '"': c = '"'; break;
		case 'b': c = BS; break;
		case 't': c = TAB; break;
		case 'n': c = NL; break;
		case 'f': c = FF; break;
		case 'r': c = CAR; break;
		case 'u':
		    if (reader->js_fill != NULL
				     && (int)(reader->js_end - p) < NUMBUFLEN)
		    {
			reader->js_used = (int)(p - reader->js_buf);
			if (reader->js_fill(reader))
			{
			    p = reader->js_buf + reader->js_used;
			    reader->js_end = reader->js_buf
						     + STRLEN(reader->js_buf);
			}
		    }
		    nr = 0;
		    len = 0;
		    vim_str2nr(p + 2, NULL, &len,
				     STR2NR_HEX + STR2NR_FORCE, &nr, NULL, 4);
		    p += len + 2;
		    if (0xd800 <= nr && nr <= 0xdfff
			    && (int)(reader->js_end - p) >= 6
			    && *p == '\\' && *(p+1) == 'u')
		    {
			varnumber_T	nr2 = 0;

			/* decode surrogate pair: \ud812\u3456 */
			len = 0;
			vim_str2nr(p + 2, NULL, &len,
				     STR2NR_HEX + STR2NR_FORCE, &nr2, NULL, 4);
			if (0xdc00 <= nr2 && nr2 <= 0xdfff)
			{
			    p += len + 2;
			    nr = (((nr - 0xd800) << 10) |
				((nr2 - 0xdc00) & 0x3ff)) + 0x10000;
			}
		    }
		    if (res != NULL)
		    {
#ifdef FEAT_MBYTE
			char_u	buf[NUMBUFLEN];
			buf[utf_char2bytes((int)nr, buf)] = NUL;
			ga_concat(&ga, buf);
#else
			ga_append(&ga, (int)nr);
#endif
		    }
		    break;
		default:
		    /* not a special char, skip over \ */
		    ++p;
		    continue;
	    }
	    if (c > 0)
	    {
		p += 2;
		if (res != NULL)
		    ga_append(&ga, c);
	    }
	}
	else
	{
#ifdef FEAT_MBYTE
	    len = utf_ptr2len(p);
#else
	    len = 1;
#endif
	    if (res != NULL)
	    {
		if (ga_grow(&ga, len) == FAIL)
		{
		    ga_clear(&ga);
		    return FAIL;
		}
		mch_memmove((char *)ga.ga_data + ga.ga_len, p, (size_t)len);
		ga.ga_len += len;
	    }
	    p += len;
	}
    }

    reader->js_used = (int)(p - reader->js_buf);
    if (*p == quote)
    {
	++reader->js_used;
	if (res != NULL)
	{
	    ga_append(&ga, NUL);
	    res->v_type = VAR_STRING;
#if defined(FEAT_MBYTE) && defined(USE_ICONV)
	    if (!enc_utf8)
	    {
		vimconv_T   conv;

		/* Convert the utf-8 string to 'encoding'. */
		conv.vc_type = CONV_NONE;
		convert_setup(&conv, (char_u*)"utf-8", p_enc);
		if (conv.vc_type != CONV_NONE)
		{
		    res->vval.v_string =
				      string_convert(&conv, ga.ga_data, NULL);
		    vim_free(ga.ga_data);
		}
		convert_setup(&conv, NULL, NULL);
	    }
	    else
#endif
		res->vval.v_string = ga.ga_data;
	}
	return OK;
    }
    if (res != NULL)
    {
	res->v_type = VAR_SPECIAL;
	res->vval.v_number = VVAL_NONE;
	ga_clear(&ga);
    }
    return MAYBE;
}
Example #11
0
/// ":loadkeymap" command: load the following lines as the keymap.
///
/// @param eap
void ex_loadkeymap(exarg_T *eap)
{
  char_u *line;
  char_u *p;
  char_u *s;
  kmap_T *kp;

#define KMAP_LLEN 200  // max length of "to" and "from" together
  char_u buf[KMAP_LLEN + 11];
  int i;
  char_u *save_cpo = p_cpo;

  if (!getline_equal(eap->getline, eap->cookie, getsourceline)) {
    EMSG(_("E105: Using :loadkeymap not in a sourced file"));
    return;
  }

  // Stop any active keymap and clear the table.
  keymap_unload();

  curbuf->b_kmap_state = 0;
  ga_init(&curbuf->b_kmap_ga, (int)sizeof(kmap_T), 20);

  // Set 'cpoptions' to "C" to avoid line continuation.
  p_cpo = (char_u *)"C";

  // Get each line of the sourced file, break at the end.
  for (;;) {
    line = eap->getline(0, eap->cookie, 0);

    if (line == NULL) {
      break;
    }

    p = skipwhite(line);

    if ((*p != '"') && (*p != NUL)) {
      ga_grow(&curbuf->b_kmap_ga, 1);
      kp = (kmap_T *)curbuf->b_kmap_ga.ga_data + curbuf->b_kmap_ga.ga_len;
      s = skiptowhite(p);
      kp->from = vim_strnsave(p, (int)(s - p));
      p = skipwhite(s);
      s = skiptowhite(p);
      kp->to = vim_strnsave(p, (int)(s - p));

      if ((STRLEN(kp->from) + STRLEN(kp->to) >= KMAP_LLEN)
          || (*kp->from == NUL)
          || (*kp->to == NUL)) {
        if (*kp->to == NUL) {
          EMSG(_("E791: Empty keymap entry"));
        }
        free(kp->from);
        free(kp->to);
      } else {
        ++curbuf->b_kmap_ga.ga_len;
      }
    }
    free(line);
  }

  // setup ":lnoremap" to map the keys
  for (i = 0; i < curbuf->b_kmap_ga.ga_len; ++i) {
    vim_snprintf((char *)buf, sizeof(buf), "<buffer> %s %s",
                 ((kmap_T *)curbuf->b_kmap_ga.ga_data)[i].from,
                 ((kmap_T *)curbuf->b_kmap_ga.ga_data)[i].to);
    (void)do_map(2, buf, LANGMAP, FALSE);
  }

  p_cpo = save_cpo;

  curbuf->b_kmap_state |= KEYMAP_LOADED;
  status_redraw_curbuf();
}
Example #12
0
/// Convert the string "str[orglen]" to do ignore-case comparing.  Uses the
/// current locale.
///
/// When "buf" is NULL returns an allocated string (NULL for out-of-memory).
/// Otherwise puts the result in "buf[buflen]".
///
/// @param str
/// @param orglen
/// @param buf
/// @param buflen
///
/// @return converted string.
char_u* str_foldcase(char_u *str, int orglen, char_u *buf, int buflen)
{
  garray_T ga;
  int i;
  int len = orglen;

#define GA_CHAR(i) ((char_u *)ga.ga_data)[i]
#define GA_PTR(i) ((char_u *)ga.ga_data + i)
#define STR_CHAR(i) (buf == NULL ? GA_CHAR(i) : buf[i])
#define STR_PTR(i) (buf == NULL ? GA_PTR(i) : buf + i)

  // Copy "str" into "buf" or allocated memory, unmodified.
  if (buf == NULL) {
    ga_init(&ga, 1, 10);

    if (ga_grow(&ga, len + 1) == FAIL) {
      return NULL;
    }
    memmove(ga.ga_data, str, (size_t)len);
    ga.ga_len = len;
  } else {
    if (len >= buflen) {
      // Ugly!
      len = buflen - 1;
    }
    memmove(buf, str, (size_t)len);
  }

  if (buf == NULL) {
    GA_CHAR(len) = NUL;
  } else {
    buf[len] = NUL;
  }

  // Make each character lower case.
  i = 0;
  while (STR_CHAR(i) != NUL) {
    if (enc_utf8 || (has_mbyte && (MB_BYTE2LEN(STR_CHAR(i)) > 1))) {
      if (enc_utf8) {
        int c = utf_ptr2char(STR_PTR(i));
        int olen = utf_ptr2len(STR_PTR(i));
        int lc = utf_tolower(c);

        // Only replace the character when it is not an invalid
        // sequence (ASCII character or more than one byte) and
        // utf_tolower() doesn't return the original character.
        if (((c < 0x80) || (olen > 1)) && (c != lc)) {
          int nlen = utf_char2len(lc);

          // If the byte length changes need to shift the following
          // characters forward or backward.
          if (olen != nlen) {
            if (nlen > olen) {
              if ((buf == NULL)
                  ? (ga_grow(&ga, nlen - olen + 1) == FAIL)
                  : (len + nlen - olen >= buflen)) {
                // out of memory, keep old char
                lc = c;
                nlen = olen;
              }
            }

            if (olen != nlen) {
              if (buf == NULL) {
                STRMOVE(GA_PTR(i) + nlen, GA_PTR(i) + olen);
                ga.ga_len += nlen - olen;
              } else {
                STRMOVE(buf + i + nlen, buf + i + olen);
                len += nlen - olen;
              }
            }
          }
          (void)utf_char2bytes(lc, STR_PTR(i));
        }
      }

      // skip to next multi-byte char
      i += (*mb_ptr2len)(STR_PTR(i));
    } else {
      if (buf == NULL) {
        GA_CHAR(i) = TOLOWER_LOC(GA_CHAR(i));
      } else {
        buf[i] = TOLOWER_LOC(buf[i]);
      }
      ++i;
    }
  }

  if (buf == NULL) {
    return (char_u *)ga.ga_data;
  }
  return buf;
}
Example #13
0
    static int
list_join_inner(
    garray_T	*gap,		/* to store the result in */
    list_T	*l,
    char_u	*sep,
    int		echo_style,
    int		restore_copyID,
    int		copyID,
    garray_T	*join_gap)	/* to keep each list item string */
{
    int		i;
    join_T	*p;
    int		len;
    int		sumlen = 0;
    int		first = TRUE;
    char_u	*tofree;
    char_u	numbuf[NUMBUFLEN];
    listitem_T	*item;
    char_u	*s;

    /* Stringify each item in the list. */
    for (item = l->lv_first; item != NULL && !got_int; item = item->li_next)
    {
	s = echo_string_core(&item->li_tv, &tofree, numbuf, copyID,
				      echo_style, restore_copyID, !echo_style);
	if (s == NULL)
	    return FAIL;

	len = (int)STRLEN(s);
	sumlen += len;

	(void)ga_grow(join_gap, 1);
	p = ((join_T *)join_gap->ga_data) + (join_gap->ga_len++);
	if (tofree != NULL || s != numbuf)
	{
	    p->s = s;
	    p->tofree = tofree;
	}
	else
	{
	    p->s = vim_strnsave(s, len);
	    p->tofree = p->s;
	}

	line_breakcheck();
	if (did_echo_string_emsg)  /* recursion error, bail out */
	    break;
    }

    /* Allocate result buffer with its total size, avoid re-allocation and
     * multiple copy operations.  Add 2 for a tailing ']' and NUL. */
    if (join_gap->ga_len >= 2)
	sumlen += (int)STRLEN(sep) * (join_gap->ga_len - 1);
    if (ga_grow(gap, sumlen + 2) == FAIL)
	return FAIL;

    for (i = 0; i < join_gap->ga_len && !got_int; ++i)
    {
	if (first)
	    first = FALSE;
	else
	    ga_concat(gap, sep);
	p = ((join_T *)join_gap->ga_data) + i;

	if (p->s != NULL)
	    ga_concat(gap, p->s);
	line_breakcheck();
    }

    return OK;
}
Example #14
0
File: json.c Project: Qubit0-1/vim
    static int
json_decode_string(js_read_T *reader, typval_T *res)
{
    garray_T    ga;
    int		len;
    char_u	*p;
    int		c;
    long	nr;
    char_u	buf[NUMBUFLEN];

    if (res != NULL)
	ga_init2(&ga, 1, 200);

    p = reader->js_buf + reader->js_used + 1; /* skip over " */
    while (*p != '"')
    {
	if (*p == NUL || p[1] == NUL
#ifdef FEAT_MBYTE
		|| utf_ptr2len(p) < utf_byte2len(*p)
#endif
		)
	{
	    if (reader->js_fill == NULL)
		break;
	    len = (int)(reader->js_end - p);
	    reader->js_used = (int)(p - reader->js_buf);
	    if (!reader->js_fill(reader))
		break; /* didn't get more */
	    p = reader->js_buf + reader->js_used;
	    reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
	    continue;
	}

	if (*p == '\\')
	{
	    c = -1;
	    switch (p[1])
	    {
		case '\\': c = '\\'; break;
		case '"': c = '"'; break;
		case 'b': c = BS; break;
		case 't': c = TAB; break;
		case 'n': c = NL; break;
		case 'f': c = FF; break;
		case 'r': c = CAR; break;
		case 'u':
		    if (reader->js_fill != NULL
				     && (int)(reader->js_end - p) < NUMBUFLEN)
		    {
			reader->js_used = (int)(p - reader->js_buf);
			if (reader->js_fill(reader))
			{
			    p = reader->js_buf + reader->js_used;
			    reader->js_end = reader->js_buf
						     + STRLEN(reader->js_buf);
			}
		    }
		    vim_str2nr(p + 2, NULL, &len,
				     STR2NR_HEX + STR2NR_FORCE, &nr, NULL, 4);
		    p += len + 2;
		    if (res != NULL)
		    {
#ifdef FEAT_MBYTE
			buf[(*mb_char2bytes)((int)nr, buf)] = NUL;
			ga_concat(&ga, buf);
#else
			ga_append(&ga, nr);
#endif
		    }
		    break;
		default:
		    /* not a special char, skip over \ */
		    ++p;
		    continue;
	    }
	    if (c > 0)
	    {
		p += 2;
		if (res != NULL)
		    ga_append(&ga, c);
	    }
	}
	else
	{
	    len = MB_PTR2LEN(p);
	    if (res != NULL)
	    {
		if (ga_grow(&ga, len) == FAIL)
		{
		    ga_clear(&ga);
		    return FAIL;
		}
		mch_memmove((char *)ga.ga_data + ga.ga_len, p, (size_t)len);
		ga.ga_len += len;
	    }
	    p += len;
	}
    }

    reader->js_used = (int)(p - reader->js_buf);
    if (*p == '"')
    {
	++reader->js_used;
	if (res != NULL)
	{
	    res->v_type = VAR_STRING;
	    res->vval.v_string = ga.ga_data;
	}
	return OK;
    }
    if (res != NULL)
    {
	res->v_type = VAR_SPECIAL;
	res->vval.v_number = VVAL_NONE;
	ga_clear(&ga);
    }
    return MAYBE;
}
Example #15
0
/*
 * Convert the string "str[orglen]" to do ignore-case comparing.  Uses the
 * current locale.
 * When "buf" is NULL returns an allocated string (NULL for out-of-memory).
 * Otherwise puts the result in "buf[buflen]".
 */
    char_u *
str_foldcase(
    char_u	*str,
    int		orglen,
    char_u	*buf,
    int		buflen)
{
    garray_T	ga;
    int		i;
    int		len = orglen;

#define GA_CHAR(i)  ((char_u *)ga.ga_data)[i]
#define GA_PTR(i)   ((char_u *)ga.ga_data + i)
#define STR_CHAR(i)  (buf == NULL ? GA_CHAR(i) : buf[i])
#define STR_PTR(i)   (buf == NULL ? GA_PTR(i) : buf + i)

    /* Copy "str" into "buf" or allocated memory, unmodified. */
    if (buf == NULL)
    {
	ga_init2(&ga, 1, 10);
	if (ga_grow(&ga, len + 1) == FAIL)
	    return NULL;
	mch_memmove(ga.ga_data, str, (size_t)len);
	ga.ga_len = len;
    }
    else
    {
	if (len >= buflen)	    /* Ugly! */
	    len = buflen - 1;
	mch_memmove(buf, str, (size_t)len);
    }
    if (buf == NULL)
	GA_CHAR(len) = NUL;
    else
	buf[len] = NUL;

    /* Make each character lower case. */
    i = 0;
    while (STR_CHAR(i) != NUL)
    {
#ifdef FEAT_MBYTE
	if (enc_utf8 || (has_mbyte && MB_BYTE2LEN(STR_CHAR(i)) > 1))
	{
	    if (enc_utf8)
	    {
		int	c = utf_ptr2char(STR_PTR(i));
		int	olen = utf_ptr2len(STR_PTR(i));
		int	lc = utf_tolower(c);

		/* Only replace the character when it is not an invalid
		 * sequence (ASCII character or more than one byte) and
		 * utf_tolower() doesn't return the original character. */
		if ((c < 0x80 || olen > 1) && c != lc)
		{
		    int	    nlen = utf_char2len(lc);

		    /* If the byte length changes need to shift the following
		     * characters forward or backward. */
		    if (olen != nlen)
		    {
			if (nlen > olen)
			{
			    if (buf == NULL
				    ? ga_grow(&ga, nlen - olen + 1) == FAIL
				    : len + nlen - olen >= buflen)
			    {
				/* out of memory, keep old char */
				lc = c;
				nlen = olen;
			    }
			}
			if (olen != nlen)
			{
			    if (buf == NULL)
			    {
				STRMOVE(GA_PTR(i) + nlen, GA_PTR(i) + olen);
				ga.ga_len += nlen - olen;
			    }
			    else
			    {
				STRMOVE(buf + i + nlen, buf + i + olen);
				len += nlen - olen;
			    }
			}
		    }
		    (void)utf_char2bytes(lc, STR_PTR(i));
		}
	    }
	    /* skip to next multi-byte char */
	    i += (*mb_ptr2len)(STR_PTR(i));
	}
	else
#endif
	{
	    if (buf == NULL)
		GA_CHAR(i) = TOLOWER_LOC(GA_CHAR(i));
	    else
		buf[i] = TOLOWER_LOC(buf[i]);
	    ++i;
	}
    }

    if (buf == NULL)
	return (char_u *)ga.ga_data;
    return buf;
}