<commit_before>#include <ctype.h>
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <cmd.h>

enum token {
	tok_nul,
	tok_cmd,
};

struct parse;

static size_t eat_ident(char *buffer, size_t length);
static size_t eat_spaces(char *buffer, size_t length);

struct parse {
	char *string;
	size_t length;
	enum token token;
	struct parse *chld[2];
};

#define eat(RES, VAR, EXPR, BUF, LEN) do {	  \
	size_t off=0; \
	while (off < (LEN)) { \
		VAR = (BUF)[off]; \
		if (!(EXPR)) break; \
		else ++off; \
	} \
	(RES) = off; \
} while (0)

size_t
eat_ident(char *buffer, size_t length)
{
	size_t result;
	eat(result, char c, !isspace(c), buffer, length);
	return result;
}

size_t
eat_spaces(char *buffer, size_t length)
{
	size_t result;
	eat(result, char c, isspace(c), buffer, length);
	return result;
}

int
parse_ln(struct parse **dest, char *buffer, size_t length)
{
	size_t offset;
	size_t extent;

	*dest = 0;

	offset = eat_spaces(buffer, length);
	if (offset >= length) return 0;

	*dest = malloc(sizeof *dest);
	if (!*dest) return ENOMEM;

	extent = eat_ident(buffer+offset, length-offset);

	dest[0]->token = tok_cmd;
	dest[0]->string = buffer+offset;
	dest[0]->length = extent;

	return 0;
}

int
exec_ln(struct edna *edna, struct parse *parse)
{
	struct command *cmd;

	cmd = cmd_lookup(edna->cmds, parse->string, parse->length);
	if (!cmd) {
		dprintf(1, "?\n");
		return 0;
	}

	return cmd->fun(edna, cmd->arg);
}<commit_msg>don't segfault on empty lines<commit_after>#include <ctype.h>
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <cmd.h>

enum token {
	tok_nul,
	tok_cmd,
};

struct parse;

static size_t eat_ident(char *buffer, size_t length);
static size_t eat_spaces(char *buffer, size_t length);

struct parse {
	char *string;
	size_t length;
	enum token token;
	struct parse *chld[2];
};

#define eat(RES, VAR, EXPR, BUF, LEN) do {	  \
	size_t off=0; \
	while (off < (LEN)) { \
		VAR = (BUF)[off]; \
		if (!(EXPR)) break; \
		else ++off; \
	} \
	(RES) = off; \
} while (0)

size_t
eat_ident(char *buffer, size_t length)
{
	size_t result;
	eat(result, char c, !isspace(c), buffer, length);
	return result;
}

size_t
eat_spaces(char *buffer, size_t length)
{
	size_t result;
	eat(result, char c, isspace(c), buffer, length);
	return result;
}

int
parse_ln(struct parse **dest, char *buffer, size_t length)
{
	size_t offset;
	size_t extent;

	*dest = 0;

	offset = eat_spaces(buffer, length);
	if (offset >= length) return 0;

	*dest = malloc(sizeof *dest);
	if (!*dest) return ENOMEM;

	extent = eat_ident(buffer+offset, length-offset);

	dest[0]->token = tok_cmd;
	dest[0]->string = buffer+offset;
	dest[0]->length = extent;

	return 0;
}

int
exec_ln(struct edna *edna, struct parse *parse)
{
	struct command *cmd;

	if (!parse) return 0;

	cmd = cmd_lookup(edna->cmds, parse->string, parse->length);
	if (!cmd) {
		dprintf(1, "?\n");
		return 0;
	}

	return cmd->fun(edna, cmd->arg);
}
{'fraction_non_alphanumeric': 0.1636904761904762, 'fraction_numerical': 0.007605820105820105, 'mean_word_length': 4.206540447504303, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6895848', 'n_tokens_mistral': 1288, 'n_tokens_neox': 1224, 'n_words': 328}