예제 #1
0
파일: charset.c 프로젝트: Gaelan/neovim
/*
 * Translate any special characters in buf[bufsize] in-place.
 * The result is a string with only printable characters, but if there is not
 * enough room, not all characters will be translated.
 */
void trans_characters(char_u *buf, int bufsize)
{
  int len;                      /* length of string needing translation */
  int room;                     /* room in buffer after string */
  char_u      *trs;             /* translated character */
  int trs_len;                  /* length of trs[] */

  len = (int)STRLEN(buf);
  room = bufsize - len;
  while (*buf != 0) {
    /* Assume a multi-byte character doesn't need translation. */
    if (has_mbyte && (trs_len = (*mb_ptr2len)(buf)) > 1)
      len -= trs_len;
    else {
      trs = transchar_byte(*buf);
      trs_len = (int)STRLEN(trs);
      if (trs_len > 1) {
        room -= trs_len - 1;
        if (room <= 0)
          return;
        mch_memmove(buf + trs_len, buf + 1, (size_t)len);
      }
      mch_memmove(buf, trs, (size_t)trs_len);
      --len;
    }
    buf += trs_len;
  }
}
예제 #2
0
파일: channel.c 프로젝트: ZombineDev/vim
/*
 * Add a new channel slot, return the index.
 * The channel isn't actually used into ch_fd is set >= 0;
 * Returns -1 if all channels are in use.
 */
    static int
add_channel(void)
{
    int		idx;
    channel_T	*new_channels;

    if (channels != NULL)
	for (idx = 0; idx < channel_count; ++idx)
	    if (channels[idx].ch_fd < 0)
		/* re-use a closed channel slot */
		return idx;
    if (channel_count == MAX_OPEN_CHANNELS)
	return -1;
    new_channels = (channel_T *)alloc(sizeof(channel_T) * (channel_count + 1));
    if (new_channels == NULL)
	return -1;
    if (channels != NULL)
	mch_memmove(new_channels, channels, sizeof(channel_T) * channel_count);
    channels = new_channels;
    (void)vim_memset(&channels[channel_count], 0, sizeof(channel_T));

    channels[channel_count].ch_fd = (sock_T)-1;
#ifdef FEAT_GUI_X11
    channels[channel_count].ch_inputHandler = (XtInputId)NULL;
#endif
#ifdef FEAT_GUI_GTK
    channels[channel_count].ch_inputHandler = 0;
#endif
#ifdef FEAT_GUI_W32
    channels[channel_count].ch_inputHandler = -1;
#endif

    return channel_count++;
}
예제 #3
0
파일: crypt.c 프로젝트: KarstenHopp/vim
/*
 * Read the crypt method specific header data from "fp".
 * Return an allocated cryptstate_T or NULL on error.
 */
    cryptstate_T *
crypt_create_from_file(FILE *fp, char_u *key)
{
    int		method_nr;
    int		header_len;
    char	magic_buffer[CRYPT_MAGIC_LEN];
    char_u	*buffer;
    cryptstate_T *state;

    if (fread(magic_buffer, CRYPT_MAGIC_LEN, 1, fp) != 1)
	return NULL;
    method_nr = crypt_method_nr_from_magic(magic_buffer, CRYPT_MAGIC_LEN);
    if (method_nr < 0)
	return NULL;

    header_len = crypt_get_header_len(method_nr);
    if ((buffer = alloc(header_len)) == NULL)
	return NULL;
    mch_memmove(buffer, magic_buffer, CRYPT_MAGIC_LEN);
    if (header_len > CRYPT_MAGIC_LEN
	    && fread(buffer + CRYPT_MAGIC_LEN,
				    header_len - CRYPT_MAGIC_LEN, 1, fp) != 1)
    {
	vim_free(buffer);
	return NULL;
    }

    state = crypt_create_from_header(method_nr, key, buffer);
    vim_free(buffer);
    return state;
}
예제 #4
0
파일: garray.c 프로젝트: hunner/neovim
/// 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;
    }
}
예제 #5
0
파일: if_python.c 프로젝트: carozhu/macvim
    static void *
py_memsave(void *p, size_t len)
{
    void	*r;

    if (!(r = PyMem_Malloc(len)))
	return NULL;
    mch_memmove(r, p, len);
    return r;
}
예제 #6
0
파일: crypt.c 프로젝트: KarstenHopp/vim
/*
 * Allocate a cryptstate_T for writing and initialize it with "key".
 * Allocates and fills in the header and stores it in "header", setting
 * "header_len".  The header may include salt and seed, depending on
 * cryptmethod.  Caller must free header.
 * Returns the state or NULL on failure.
 */
    cryptstate_T *
crypt_create_for_writing(
    int	    method_nr,
    char_u  *key,
    char_u  **header,
    int	    *header_len)
{
    int	    len = crypt_get_header_len(method_nr);
    char_u  *salt = NULL;
    char_u  *seed = NULL;
    int	    salt_len = cryptmethods[method_nr].salt_len;
    int	    seed_len = cryptmethods[method_nr].seed_len;
    cryptstate_T *state;

    *header_len = len;
    *header = alloc(len);
    if (*header == NULL)
	return NULL;

    mch_memmove(*header, cryptmethods[method_nr].magic, CRYPT_MAGIC_LEN);
    if (salt_len > 0 || seed_len > 0)
    {
	if (salt_len > 0)
	    salt = *header + CRYPT_MAGIC_LEN;
	if (seed_len > 0)
	    seed = *header + CRYPT_MAGIC_LEN + salt_len;

	/* TODO: Should this be crypt method specific? (Probably not worth
	 * it).  sha2_seed is pretty bad for large amounts of entropy, so make
	 * that into something which is suitable for anything. */
	sha2_seed(salt, salt_len, seed, seed_len);
    }

    state = crypt_create(method_nr, key, salt, salt_len, seed, seed_len);
    if (state == NULL)
    {
	vim_free(*header);
	*header = NULL;
    }
    return state;
}
예제 #7
0
/*
 * Add a new channel slot, return the index.
 * The channel isn't actually used into ch_fd is set >= 0;
 * Returns -1 if all channels are in use.
 */
    static int
add_channel(void)
{
    int		idx;
    channel_T	*new_channels;
    channel_T	*ch;

    if (channels != NULL)
	for (idx = 0; idx < channel_count; ++idx)
	    if (channels[idx].ch_fd < 0)
		/* re-use a closed channel slot */
		return idx;
    if (channel_count == MAX_OPEN_CHANNELS)
	return -1;
    new_channels = (channel_T *)alloc(sizeof(channel_T) * (channel_count + 1));
    if (new_channels == NULL)
	return -1;
    if (channels != NULL)
	mch_memmove(new_channels, channels, sizeof(channel_T) * channel_count);
    channels = new_channels;
    ch = &channels[channel_count];
    (void)vim_memset(ch, 0, sizeof(channel_T));

    ch->ch_fd = (sock_T)-1;
#ifdef FEAT_GUI_X11
    ch->ch_inputHandler = (XtInputId)NULL;
#endif
#ifdef FEAT_GUI_GTK
    ch->ch_inputHandler = 0;
#endif
#ifdef FEAT_GUI_W32
    ch->ch_inputHandler = -1;
#endif
    /* initialize circular queues */
    ch->ch_head.next = &ch->ch_head;
    ch->ch_head.prev = &ch->ch_head;
    ch->ch_json_head.next = &ch->ch_json_head;
    ch->ch_json_head.prev = &ch->ch_json_head;

    return channel_count++;
}
예제 #8
0
파일: channel.c 프로젝트: koron/vim
/*
 * Add a new channel slot, return the index.
 * Returns -1 if out of space.
 */
    static int
add_channel(void)
{
    int		idx;
    channel_T	*new_channels;

    if (channels != NULL)
	for (idx = 0; idx < channel_count; ++idx)
	    if (channels[idx].ch_fd < 0)
		/* re-use a closed channel slot */
		return idx;
    if (channel_count == MAX_OPEN_CHANNELS)
	return -1;
    new_channels = (channel_T *)alloc(sizeof(channel_T) * channel_count + 1);
    if (new_channels == NULL)
	return -1;
    if (channels != NULL)
	mch_memmove(new_channels, channels, sizeof(channel_T) * channel_count);
    channels = new_channels;
    channels[channel_count].ch_fd = (sock_T)-1;

    return channel_count++;
}
예제 #9
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;
}
예제 #10
0
파일: charset.c 프로젝트: Gaelan/neovim
/*
 * 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) {
    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;
}
예제 #11
0
파일: hashtab.c 프로젝트: Bapexboz/vim
/*
 * Shrink a hashtable when there is too much empty space.
 * Grow a hashtable when there is not enough empty space.
 * Returns OK or FAIL (out of memory).
 */
    static int
hash_may_resize(
    hashtab_T	*ht,
    int		minitems)		/* minimal number of items */
{
    hashitem_T	temparray[HT_INIT_SIZE];
    hashitem_T	*oldarray, *newarray;
    hashitem_T	*olditem, *newitem;
    unsigned	newi;
    int		todo;
    long_u	oldsize, newsize;
    long_u	minsize;
    long_u	newmask;
    hash_T	perturb;

    /* Don't resize a locked table. */
    if (ht->ht_locked > 0)
	return OK;

#ifdef HT_DEBUG
    if (ht->ht_used > ht->ht_filled)
	EMSG("hash_may_resize(): more used than filled");
    if (ht->ht_filled >= ht->ht_mask + 1)
	EMSG("hash_may_resize(): table completely filled");
#endif

    if (minitems == 0)
    {
	/* Return quickly for small tables with at least two NULL items.  NULL
	 * items are required for the lookup to decide a key isn't there. */
	if (ht->ht_filled < HT_INIT_SIZE - 1
					 && ht->ht_array == ht->ht_smallarray)
	    return OK;

	/*
	 * Grow or refill the array when it's more than 2/3 full (including
	 * removed items, so that they get cleaned up).
	 * Shrink the array when it's less than 1/5 full.  When growing it is
	 * at least 1/4 full (avoids repeated grow-shrink operations)
	 */
	oldsize = ht->ht_mask + 1;
	if (ht->ht_filled * 3 < oldsize * 2 && ht->ht_used > oldsize / 5)
	    return OK;

	if (ht->ht_used > 1000)
	    minsize = ht->ht_used * 2;  /* it's big, don't make too much room */
	else
	    minsize = ht->ht_used * 4;  /* make plenty of room */
    }
    else
    {
	/* Use specified size. */
	if ((long_u)minitems < ht->ht_used)	/* just in case... */
	    minitems = (int)ht->ht_used;
	minsize = minitems * 3 / 2;	/* array is up to 2/3 full */
    }

    newsize = HT_INIT_SIZE;
    while (newsize < minsize)
    {
	newsize <<= 1;		/* make sure it's always a power of 2 */
	if (newsize == 0)
	    return FAIL;	/* overflow */
    }

    if (newsize == HT_INIT_SIZE)
    {
	/* Use the small array inside the hashdict structure. */
	newarray = ht->ht_smallarray;
	if (ht->ht_array == newarray)
	{
	    /* Moving from ht_smallarray to ht_smallarray!  Happens when there
	     * are many removed items.  Copy the items to be able to clean up
	     * removed items. */
	    mch_memmove(temparray, newarray, sizeof(temparray));
	    oldarray = temparray;
	}
	else
	    oldarray = ht->ht_array;
    }
    else
    {
	/* Allocate an array. */
	newarray = (hashitem_T *)alloc((unsigned)
					      (sizeof(hashitem_T) * newsize));
	if (newarray == NULL)
	{
	    /* Out of memory.  When there are NULL items still return OK.
	     * Otherwise set ht_error, because lookup may result in a hang if
	     * we add another item. */
	    if (ht->ht_filled < ht->ht_mask)
		return OK;
	    ht->ht_error = TRUE;
	    return FAIL;
	}
	oldarray = ht->ht_array;
    }
    vim_memset(newarray, 0, (size_t)(sizeof(hashitem_T) * newsize));

    /*
     * Move all the items from the old array to the new one, placing them in
     * the right spot.  The new array won't have any removed items, thus this
     * is also a cleanup action.
     */
    newmask = newsize - 1;
    todo = (int)ht->ht_used;
    for (olditem = oldarray; todo > 0; ++olditem)
	if (!HASHITEM_EMPTY(olditem))
	{
	    /*
	     * The algorithm to find the spot to add the item is identical to
	     * the algorithm to find an item in hash_lookup().  But we only
	     * need to search for a NULL key, thus it's simpler.
	     */
	    newi = (unsigned)(olditem->hi_hash & newmask);
	    newitem = &newarray[newi];

	    if (newitem->hi_key != NULL)
		for (perturb = olditem->hi_hash; ; perturb >>= PERTURB_SHIFT)
		{
		    newi = (unsigned)((newi << 2U) + newi + perturb + 1U);
		    newitem = &newarray[newi & newmask];
		    if (newitem->hi_key == NULL)
			break;
		}
	    *newitem = *olditem;
	    --todo;
	}
예제 #12
0
파일: mark.c 프로젝트: Davie013/neovim
/*
 * Handle marks in the viminfo file:
 * fp_out != NULL: copy marks for buffers not in buffer list
 * fp_out == NULL && (flags & VIF_WANT_MARKS): read marks for curbuf only
 * fp_out == NULL && (flags & VIF_GET_OLDFILES | VIF_FORCEIT): fill v:oldfiles
 */
void copy_viminfo_marks(vir_T *virp, FILE *fp_out, int count, int eof, int flags)
{
  char_u      *line = virp->vir_line;
  buf_T       *buf;
  int num_marked_files;
  int load_marks;
  int copy_marks_out;
  char_u      *str;
  int i;
  char_u      *p;
  char_u      *name_buf;
  pos_T pos;
  list_T      *list = NULL;

  if ((name_buf = alloc(LSIZE)) == NULL)
    return;
  *name_buf = NUL;

  if (fp_out == NULL && (flags & (VIF_GET_OLDFILES | VIF_FORCEIT))) {
    list = list_alloc();
    if (list != NULL)
      set_vim_var_list(VV_OLDFILES, list);
  }

  num_marked_files = get_viminfo_parameter('\'');
  while (!eof && (count < num_marked_files || fp_out == NULL)) {
    if (line[0] != '>') {
      if (line[0] != '\n' && line[0] != '\r' && line[0] != '#') {
        if (viminfo_error("E576: ", _("Missing '>'"), line))
          break;                /* too many errors, return now */
      }
      eof = vim_fgets(line, LSIZE, virp->vir_fd);
      continue;                 /* Skip this dud line */
    }

    /*
     * Handle long line and translate escaped characters.
     * Find file name, set str to start.
     * Ignore leading and trailing white space.
     */
    str = skipwhite(line + 1);
    str = viminfo_readstring(virp, (int)(str - virp->vir_line), FALSE);
    if (str == NULL)
      continue;
    p = str + STRLEN(str);
    while (p != str && (*p == NUL || vim_isspace(*p)))
      p--;
    if (*p)
      p++;
    *p = NUL;

    if (list != NULL)
      list_append_string(list, str, -1);

    /*
     * If fp_out == NULL, load marks for current buffer.
     * If fp_out != NULL, copy marks for buffers not in buflist.
     */
    load_marks = copy_marks_out = FALSE;
    if (fp_out == NULL) {
      if ((flags & VIF_WANT_MARKS) && curbuf->b_ffname != NULL) {
        if (*name_buf == NUL)               /* only need to do this once */
          home_replace(NULL, curbuf->b_ffname, name_buf, LSIZE, TRUE);
        if (fnamecmp(str, name_buf) == 0)
          load_marks = TRUE;
      }
    } else   { /* fp_out != NULL */
             /* This is slow if there are many buffers!! */
      for (buf = firstbuf; buf != NULL; buf = buf->b_next)
        if (buf->b_ffname != NULL) {
          home_replace(NULL, buf->b_ffname, name_buf, LSIZE, TRUE);
          if (fnamecmp(str, name_buf) == 0)
            break;
        }

      /*
       * copy marks if the buffer has not been loaded
       */
      if (buf == NULL || !buf->b_marks_read) {
        copy_marks_out = TRUE;
        fputs("\n> ", fp_out);
        viminfo_writestring(fp_out, str);
        count++;
      }
    }
    vim_free(str);

    pos.coladd = 0;
    while (!(eof = viminfo_readline(virp)) && line[0] == TAB) {
      if (load_marks) {
        if (line[1] != NUL) {
          unsigned u;

          sscanf((char *)line + 2, "%ld %u", &pos.lnum, &u);
          pos.col = u;
          switch (line[1]) {
          case '"': curbuf->b_last_cursor = pos; break;
          case '^': curbuf->b_last_insert = pos; break;
          case '.': curbuf->b_last_change = pos; break;
          case '+':
            /* changelist positions are stored oldest
             * first */
            if (curbuf->b_changelistlen == JUMPLISTSIZE)
              /* list is full, remove oldest entry */
              mch_memmove(curbuf->b_changelist,
                  curbuf->b_changelist + 1,
                  sizeof(pos_T) * (JUMPLISTSIZE - 1));
            else
              ++curbuf->b_changelistlen;
            curbuf->b_changelist[
              curbuf->b_changelistlen - 1] = pos;
            break;
          default:  if ((i = line[1] - 'a') >= 0 && i < NMARKS)
              curbuf->b_namedm[i] = pos;
          }
        }
      } else if (copy_marks_out)
        fputs((char *)line, fp_out);
    }
    if (load_marks) {
      win_T       *wp;

      FOR_ALL_WINDOWS(wp)
      {
        if (wp->w_buffer == curbuf)
          wp->w_changelistidx = curbuf->b_changelistlen;
      }
      break;
    }
  }
  vim_free(name_buf);
}
예제 #13
0
파일: json.c 프로젝트: 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;
}
예제 #14
0
파일: hashtab.c 프로젝트: jpssff/neovim
/// Shrink a hashtable when there is too much empty space.
/// Grow a hashtable when there is not enough empty space.
///
/// @param ht
/// @param minitems minimal number of items
///
/// @returns OK or FAIL (out of memory).
static int hash_may_resize(hashtab_T *ht, int minitems)
{
  hashitem_T temparray[HT_INIT_SIZE];
  hashitem_T *oldarray, *newarray;
  hashitem_T *olditem, *newitem;
  unsigned newi;
  int todo;
  long_u oldsize, newsize;
  long_u minsize;
  long_u newmask;
  hash_T perturb;

  // Don't resize a locked table.
  if (ht->ht_locked > 0) {
    return OK;
  }

#ifdef HT_DEBUG
  if (ht->ht_used > ht->ht_filled) {
    EMSG("hash_may_resize(): more used than filled");
  }

  if (ht->ht_filled >= ht->ht_mask + 1) {
    EMSG("hash_may_resize(): table completely filled");
  }
#endif  // ifdef HT_DEBUG

  if (minitems == 0) {
    // Return quickly for small tables with at least two NULL items.  NULL
    // items are required for the lookup to decide a key isn't there.
    if ((ht->ht_filled < HT_INIT_SIZE - 1)
        && (ht->ht_array == ht->ht_smallarray)) {
      return OK;
    }

    // Grow or refill the array when it's more than 2/3 full (including
    // removed items, so that they get cleaned up).
    // Shrink the array when it's less than 1/5 full.  When growing it is
    // at least 1/4 full (avoids repeated grow-shrink operations)
    oldsize = ht->ht_mask + 1;
    if ((ht->ht_filled * 3 < oldsize * 2) && (ht->ht_used > oldsize / 5)) {
      return OK;
    }

    if (ht->ht_used > 1000) {
      // it's big, don't make too much room
      minsize = ht->ht_used * 2;
    } else {
      // make plenty of room
      minsize = ht->ht_used * 4;
    }
  } else {
    // Use specified size.
    if ((long_u)minitems < ht->ht_used) {
      // just in case...
      minitems = (int)ht->ht_used;
    }
    // array is up to 2/3 full
    minsize = minitems * 3 / 2;
  }

  newsize = HT_INIT_SIZE;

  while (newsize < minsize) {
    // make sure it's always a power of 2
    newsize <<= 1;
    if (newsize == 0) {
      // overflow
      return FAIL;
    }
  }

  if (newsize == HT_INIT_SIZE) {
    // Use the small array inside the hashdict structure.
    newarray = ht->ht_smallarray;
    if (ht->ht_array == newarray) {
      // Moving from ht_smallarray to ht_smallarray!  Happens when there
      // are many removed items.  Copy the items to be able to clean up
      // removed items.
      mch_memmove(temparray, newarray, sizeof(temparray));
      oldarray = temparray;
    } else {
      oldarray = ht->ht_array;
    }
  } else {
    // Allocate an array.
    newarray = (hashitem_T *)alloc((unsigned)(sizeof(hashitem_T) * newsize));

    if (newarray == NULL) {
      // Out of memory.  When there are NULL items still return OK.
      // Otherwise set ht_error, because lookup may result in a hang if
      // we add another item.
      if (ht->ht_filled < ht->ht_mask) {
        return OK;
      }
      ht->ht_error = TRUE;
      return FAIL;
    }
    oldarray = ht->ht_array;
  }
  memset(newarray, 0, (size_t)(sizeof(hashitem_T) * newsize));

  // Move all the items from the old array to the new one, placing them in
  // the right spot.  The new array won't have any removed items, thus this
  // is also a cleanup action.
  newmask = newsize - 1;
  todo = (int)ht->ht_used;

  for (olditem = oldarray; todo > 0; ++olditem) {
    if (!HASHITEM_EMPTY(olditem)) {
      // The algorithm to find the spot to add the item is identical to
      // the algorithm to find an item in hash_lookup().  But we only
      // need to search for a NULL key, thus it's simpler.
      newi = (unsigned)(olditem->hi_hash & newmask);
      newitem = &newarray[newi];
      if (newitem->hi_key != NULL) {
        for (perturb = olditem->hi_hash;; perturb >>= PERTURB_SHIFT) {
          newi = (unsigned)((newi << 2U) + newi + perturb + 1U);
          newitem = &newarray[newi & newmask];
          if (newitem->hi_key == NULL) {
            break;
          }
        }
      }
      *newitem = *olditem;
      todo--;
    }
  }