/// @file charset.c
///
/// Code related to character sets.
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <uv.h>
#include "auto/config.h"
#include "klib/kvec.h"
#include "nvim/ascii_defs.h"
#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/cursor.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/garray.h"
#include "nvim/garray_defs.h"
#include "nvim/globals.h"
#include "nvim/keycodes.h"
#include "nvim/macros_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
#include "nvim/option.h"
#include "nvim/path.h"
#include "nvim/pos_defs.h"
#include "nvim/strings.h"
#include "nvim/types_defs.h"
#include "nvim/vim_defs.h"
#include "charset.c.generated.h"
// a chartab is an array with 256 bits, each bit representing one of the characters 0-255.
#define SET_CHARTAB(chartab, c) (chartab)[(unsigned)(c) >> 6] |= (1ull << ((c) & 0x3f))
#define RESET_CHARTAB(chartab, c) (chartab)[(unsigned)(c) >> 6] &= ~(1ull << ((c) & 0x3f))
#define GET_CHARTAB(chartab, c) ((chartab)[(unsigned)(c) >> 6] & (1ull << ((c) & 0x3f)))
static uint64_t isf_chartab[4]; // chartab for 'isfname'
static uint64_t isi_chartab[4]; // chartab for 'isindent'
int buf_init_isk_chartab(buf_T *buf)
{
uint64_t save_chartab[4];
memcpy(save_chartab, buf->b_chartab, sizeof save_chartab);
memset(buf->b_chartab, 0, sizeof buf->b_chartab);
if (buf->b_p_lisp) { // don't ask
SET_CHARTAB(buf->b_chartab, '-');
}
if (parse_isopt(buf->b_p_isk, buf->b_chartab) == FAIL) {
memcpy(buf->b_chartab, save_chartab, sizeof save_chartab);
return FAIL;
}
return OK;
}
int init_isf_chartab(void)
{
uint64_t save_chartab[4];
memcpy(save_chartab, isf_chartab, sizeof save_chartab);
memset(isf_chartab, 0, sizeof isf_chartab);
isf_chartab[2] = 0xFFFFFFFF00000000; // there is no need
isf_chartab[3] = 0xFFFFFFFFFFFFFFFF; // to worry
if (parse_isopt(p_isf, isf_chartab) == FAIL) {
memcpy(isf_chartab, save_chartab, sizeof save_chartab);
return FAIL;
}
return OK;
}
int init_isi_chartab(void)
{
uint64_t save_chartab[4];
memcpy(save_chartab, isi_chartab, sizeof save_chartab);
memset(isi_chartab, 0, sizeof isi_chartab);
if (parse_isopt(p_isi, isi_chartab) == FAIL) {
memcpy(isi_chartab, save_chartab, sizeof save_chartab);
return FAIL;
}
return OK;
}
/// Checks the format for the option settings 'iskeyword', 'isident', 'isfname'
/// Returns FAIL if has an error, OK otherwise.
int check_isopt(char *var)
{
return parse_isopt(var, NULL);
}
/// @param chartab if NULL only check if option string is valid
int parse_isopt(const char *var, uint64_t *chartab)
{
const char *p = var;
// Parses the 'isident', 'iskeyword', 'isfname' options.
// Each option is a list of characters, character numbers or ranges,
// separated by commas, e.g.: "200-210,x,#-178,-"
while (*p) {
bool tilde = false;
bool do_isalpha = false;
if (*p == '^' && p[1] != NUL) {
tilde = true;
p++;
}
int c;
if (ascii_isdigit(*p)) {
c = getdigits_int((char **)&p, false, 0);
} else {
c = mb_ptr2char_adv(&p);
}
int c2 = -1;
if (*p == '-' && p[1] != NUL) {
p++;
if (ascii_isdigit(*p)) {
c2 = getdigits_int((char **)&p, false, 0);
} else {
c2 = mb_ptr2char_adv(&p);
}
}
if (
|