nasmfm

sfm rewrite
git clone https://git.afify.dev/nasmfm.git
Log | Files | Refs | LICENSE

commit 7072e37fbe7fd4b2f3c4aa2e7563ff4ea407717c
parent 33bd1a644eee0e0d3feb9e9dae562005f9d9194d
Author: afify <hassan@afify.dev>
Date:   Sat, 12 Mar 2022 20:15:39 +0300

[feat] signals

Diffstat:
MMakefile | 12++----------
Aconfig.def.h | 25+++++++++++++++++++++++++
Mnasmfm.c | 362++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Aterm.c | 252+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aterm.h | 41+++++++++++++++++++++++++++++++++++++++++
Autf8.c | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Autf8.h | 15+++++++++++++++
Autil.c | 44++++++++++++++++++++++++++++++++++++++++++++
Autil.h | 17+++++++++++++++++
9 files changed, 652 insertions(+), 169 deletions(-)

diff --git a/Makefile b/Makefile @@ -3,7 +3,7 @@ include config.mk -SRC = nasmfm.c +SRC = nasmfm.c term.c utf8.c util.c OBJ = ${SRC:.c=.o} all: options nasmfm @@ -17,7 +17,7 @@ options: .c.o: ${CC} -c ${CFLAGS} $< -${OBJ}: config.mk +${OBJ}: config.h config.mk config.h: cp config.def.h $@ @@ -28,14 +28,6 @@ nasmfm: ${OBJ} clean: rm -f nasmfm ${OBJ} nasmfm-${VERSION}.tar.gz -dist: clean - mkdir -p nasmfm-${VERSION} - cp -R LICENSE Makefile README.md config.def.h config.mk\ - nasmfm.1 nasmfm.png termbox.h util.h ${SRC} nasmfm-${VERSION} - tar -cf nasmfm-${VERSION}.tar nasmfm-${VERSION} - gzip nasmfm-${VERSION}.tar - rm -rf nasmfm-${VERSION} - install: nasmfm mkdir -p ${DESTDIR}${PREFIX}/bin cp -f nasmfm ${DESTDIR}${PREFIX}/bin diff --git a/config.def.h b/config.def.h @@ -0,0 +1,25 @@ +/* See LICENSE file for copyright and license details. */ + +#ifndef CONFIG_H +#define CONFIG_H + +/* colors fg, bg att*/ +static const Cpair cdir = { 31, 0, NORM }; +static const Cpair cfile = { 243, 0, NORM }; +static const Cpair clnk = { 96, 0, NORM }; +static const Cpair cblk = { 95, 0, NORM }; +static const Cpair cchr = { 94, 0, NORM }; +static const Cpair cifo = { 93, 0, NORM }; +static const Cpair csock = { 92, 0, NORM }; +static const Cpair cexec = { 91, 0, NORM }; +static const Cpair cother = { 90, 0, NORM }; + +static const Cpair cframe = { 233, 233, NORM }; +static const Cpair cpanell = { 166, 233, BOLD }; +static const Cpair cpanelr = { 5, 233, BOLD }; +static const Cpair cerr = { 124, 0, NORM }; +static const Cpair cprompt = { 33, 0, NORM }; +static const Cpair csearch = { 255, 0, NORM }; +static const Cpair cstatus = { 243, 0, NORM }; + +#endif /* CONFIG_H */ diff --git a/nasmfm.c b/nasmfm.c @@ -1,217 +1,261 @@ /* See LICENSE file for copyright and license details. */ -#include <sys/ioctl.h> - -#include <ctype.h> -#include <errno.h> -#include <stddef.h> +#include <signal.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <termios.h> #include <unistd.h> +#include "term.h" +#include "util.h" + /* macros */ -#define CTRL_KEY(k) ((k)&0x1f) -#define CLEAR_SCREEN abAppend(&ab, "\x1b[2J", 4); -#define CURSOR_TOP_LEFT abAppend(&ab, "\x1b[H", 3); -#define CURSOR_HIDE abAppend(&ab, "\x1b[?25l", 6); -#define CURSOR_SHOW abAppend(&ab, "\x1b[?25h", 6); -#define ABUF_INIT \ - { \ - NULL, 0 \ - } +#define MAX_P 4096 +#define MAX_N 255 +#define MAX_USRI 32 +#define MAX_EXT 4 +#define MAX_STATUS 255 +#define MAX_LINE 4096 +#define MAX_USRN 32 +#define MAX_GRPN 32 +#define MAX_DTF 32 +#define CURSOR(x) (x)->direntr[(x)->hdir - 1] /* typedef */ -/* function declarations */ +typedef struct { + char name[MAX_N]; + gid_t group; + mode_t mode; + off_t size; + time_t dt; + uid_t user; +} Entry; + +typedef struct { + //int pane_id; + char dirn[MAX_P]; // dir name cwd + //char *filter; + //Entry *direntr; // dir entries + //int dirc; // dir entries sum + //int hdir; // highlighted dir + int x_srt; + int x_end; + //int firstrow; + //int parent_firstrow; + //int parent_row; // FIX + Cpair dircol; + //int inotify_wd; + //int event_fd; +} Pane; typedef struct { - int cx; - int cy; - int rows; - int cols; - struct termios orig_termios; -} Term; - -struct abuf { - char *b; - int len; -}; + const char **ext; + size_t exlen; + const void *v; + size_t vlen; +} Rule; + +typedef union { + uint16_t key; /* one of the TB_KEY_* constants */ + uint32_t ch; /* unicode character */ +} Evkey; + +typedef union { + int i; + const void *v; +} Arg; + +typedef struct { + const Evkey evkey; + void (*func)(const Arg *); + const Arg arg; +} Key; /* global variables */ -Term term; +static Term *term; +static pthread_t fsev_thread; +static Pane panes[2]; +static Pane *cpane; +static int pane_idx; +static char *editor[2]; +static char fed[] = "vi"; +static char *shell[2]; +static char sh[] = "/bin/sh"; +//static int theight, twidth, hwidth, scrheight; +//static int *sel_indexes; +//static size_t sel_len = 0; +//static char **sel_files; +//static int cont_vmode = 0; +//static int cont_change = 0; +static pid_t fork_pid = 0, main_pid; +//#if defined(_SYS_INOTIFY_H) +//#define READEVSZ 16 +//static int inotify_fd; +//#elif defined(_SYS_EVENT_H_) +//#define READEVSZ 0 +//static int kq; +//struct kevent evlist[2]; /* events we want to monitor */ +//struct kevent chlist[2]; /* events that were triggered */ +//static struct timespec gtimeout; +//#endif +#if defined(__linux__) || defined(__FreeBSD__) +#define OFF_T "%ld" +#elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) +#define OFF_T "%lld" +#endif +enum { Left, Right }; /* panes */ +enum { Wait, DontWait }; /* spawn forks */ -/* function implementations */ -void -abAppend(struct abuf *ab, const char *s, int len) -{ - char *new = realloc(ab->b, ab->len + len); - if (new == NULL) - return; - memcpy(&new[ab->len], s, len); - ab->b = new; - ab->len += len; -} -void -abFree(struct abuf *ab) -{ - free(ab->b); -} +/* configuration, allows nested code to access above variables */ +#include "config.h" -void -die(const char *s) +static void +listdir(Pane *pane) { - //CLEAR_SCREEN - //CURSOR_TOP_LEFT - perror(s); - exit(1); + // print pane cwd + twrite(pane->x_srt, 0, pane->dirn, strlen(pane->dirn), pane->dircol); } -void -disableRawMode() +static void +set_panes(void) { - if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &term.orig_termios) == -1) - die("tcsetattr"); -} + char *home; + char cwd[MAX_P]; -void -enableRawMode() -{ - if (tcgetattr(STDIN_FILENO, &term.orig_termios) == -1) - die("tcgetattr"); - atexit(disableRawMode); - struct termios raw = term.orig_termios; - - raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); - raw.c_oflag &= ~(OPOST); - raw.c_cflag |= (CS8); - raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); - raw.c_cc[VMIN] = 0; - raw.c_cc[VTIME] = 1; - - if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1) - die("tcsetattr"); -} + home = getenv("HOME"); + if (home == NULL) + home = "/"; + if ((getcwd(cwd, sizeof(cwd)) == NULL)) + strncpy(cwd, home, MAX_P); -void -editorDrawRows(struct abuf *ab) -{ - int y; - for (y = 0; y < term.rows; y++) { - if (y == term.rows / 3) { - char welcome[80]; - int welcomelen = snprintf(welcome, sizeof(welcome), - "Kilo editor -- version nasmfm"); - if (welcomelen > term.cols) - welcomelen = term.cols; - int padding = (term.cols - welcomelen) / 2; - if (padding) { - abAppend(ab, "~", 1); - padding--; - } - while (padding--) - abAppend(ab, " ", 1); - abAppend(ab, welcome, welcomelen); - } else { - abAppend(ab, "~", 1); - } - abAppend(ab, "\x1b[K", 3); - if (y < term.rows - 1) { - abAppend(ab, "\r\n", 2); - } - } -} + pane_idx = Left; /* cursor pane */ + cpane = &panes[pane_idx]; -void -editorRefreshScreen() -{ - struct abuf ab = ABUF_INIT; - abAppend(&ab, "\x1b[?25l", 6); - abAppend(&ab, "\x1b[H", 3); - editorDrawRows(&ab); - char buf[32]; - snprintf(buf, sizeof(buf), "\x1b[%d;%dH", term.cy + 1, term.cx + 1); - abAppend(&ab, buf, strlen(buf)); - abAppend(&ab, "\x1b[?25h", 6); - write(STDOUT_FILENO, ab.b, ab.len); - abFree(&ab); + //panes[Left].pane_id = 0; + panes[Left].x_srt = 2; + panes[Left].x_end = (term->cols / 2) - 1; + panes[Left].dircol = cpanell; + //panes[Left].firstrow = 0; + //panes[Left].direntr = ecalloc(0, sizeof(Entry)); + strncpy(panes[Left].dirn, cwd, MAX_P); + //panes[Left].hdir = 1; + //panes[Left].inotify_wd = -1; + //panes[Left].parent_row = 1; + + //panes[Right].pane_id = 1; + panes[Right].x_srt = (term->cols / 2) + 2; + panes[Right].x_end = term->cols - 1; + panes[Right].dircol = cpanelr; + //panes[Right].firstrow = 0; + //panes[Right].direntr = ecalloc(0, sizeof(Entry)); + strncpy(panes[Right].dirn, home, MAX_P); + //panes[Right].hdir = 1; + //panes[Right].inotify_wd = -1; + //panes[Right].parent_row = 1; } -char -editorReadKey() +static void +get_editor(void) { - int nread; - char c; - while ((nread = read(STDIN_FILENO, &c, 1)) != 1) { - if (nread == -1 && errno != EAGAIN) - die("read"); - } - return c; + editor[0] = getenv("EDITOR"); + editor[1] = NULL; + + if (editor[0] == NULL) + editor[0] = fed; } -void -twrite(int x, int y, char *str, size_t len) +static void +get_shell(void) { - if (x > term.rows || y > term.cols) - return; - char buf[term.cols]; - size_t full_buf; - - snprintf(buf, term.cols, "\x1b[%d;%df%s", x, y, str); - full_buf = strlen(buf); - write(STDOUT_FILENO, buf, full_buf); + shell[0] = getenv("SHELL"); + shell[1] = NULL; + + if (shell[0] == NULL) + shell[0] = sh; } void -editorProcessKeypress() +keypress() { - char c = editorReadKey(); + char c = getkey(); char buf[50]; - snprintf(buf, sizeof(buf), "THIS IS LETTER %c [%ld]=>", c, sizeof(buf)); + Cpair col; + int signo = 156; + snprintf(buf, sizeof(buf), "<%d>THIS IS LETTER %c [%ld] => %d/%d", + main_pid, c, sizeof(buf), term->cols, term->rows); switch (c) { case 'q': - write(STDOUT_FILENO, "\x1b[2J", 4); - write(STDOUT_FILENO, "\x1b[H", 3); + CLEAR_SCREEN + //CURSOR_TOP_LEFT + CURSOR_SHOW exit(0); break; default: - twrite(10, 10, buf, strlen(buf)); + col.bg = 0; + col.fg = 211; + col.attr = RVS; + + tprintf(2, term->rows -2, col, "SIGWINCH = %d\n", signo); + //twrite(2, term->rows - 2, buf, strlen(buf), col); break; } } -int -getWindowSize(int *rows, int *cols) +void +sighandler(int signo) { - struct winsize ws; - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) { - return -1; - } else { - *cols = ws.ws_col; - *rows = ws.ws_row; - return 0; + Cpair col; + col.bg = 0; + col.fg = 211; + col.attr = RVS; + + switch (signo) { + case SIGWINCH: + get_term_size(&term->rows, &term->cols); + CLEAR_SCREEN + //CURSOR_TOP_LEFT + draw_frame(); + tprintf(3,3, col, "SIGWINCH = %d [%d-%d]", signo, term->cols,term->rows); + break; + case SIGUSR1: + tprintf(1, 1, col, "SIGUSR1 = %d", signo); + break; + case SIGUSR2: + tprintf(1, 1, col, "SIGUSR2 = %d", signo); + break; } + } -void -initEditor() +static int +start_signal(void) { - term.cx = 0; - term.cy = 0; - if (getWindowSize(&term.rows, &term.cols) == -1) - die("getWindowSize"); + struct sigaction sa; + main_pid = getpid(); + sa.sa_handler = sighandler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + sigaction(SIGUSR1, &sa, 0); + sigaction(SIGUSR2, &sa, 0); + sigaction(SIGWINCH, &sa, 0); + return 0; } int main(int argc, char *argv[]) { - enableRawMode(); - initEditor(); - write(STDOUT_FILENO, "\x1b[2J", 4); - write(STDOUT_FILENO, "\x1b[H", 3); + term = init_term(); + draw_frame(); + set_panes(); + get_editor(); + get_shell(); + listdir(&panes[Left]); + listdir(&panes[Right]); + start_signal(); while (1) { - //editorRefreshScreen(); - editorProcessKeypress(); + keypress(); } return 0; } diff --git a/term.c b/term.c @@ -0,0 +1,252 @@ +/* See LICENSE file for copyright and license details. */ + +#include <sys/ioctl.h> + +#include <ctype.h> +#include <errno.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <termios.h> +#include <unistd.h> +#include <wchar.h> +#include <stdint.h> + +#include "term.h" +#include "utf8.h" +#include "util.h" + +/* macros */ +/* typedef */ +/* function declarations */ +/* global variables */ +static Term oterm; + +/* function implementations */ + +void +die(const char *s) +{ + CLEAR_SCREEN + //CURSOR_TOP_LEFT + perror(s); + exit(1); +} + + +void +disableRawMode() +{ + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &oterm.orig_termios) == -1) + die("tcsetattr"); +} + + +void +raw_mode() +{ + if (tcgetattr(STDIN_FILENO, &oterm.orig_termios) == -1) + die("tcgetattr"); + atexit(disableRawMode); + struct termios raw = oterm.orig_termios; + + raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + raw.c_oflag &= ~(OPOST); + raw.c_cflag |= (CS8); + raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); + raw.c_cc[VMIN] = 0; + raw.c_cc[VTIME] = 1; + + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1) + die("tcsetattr"); +} + +int +get_term_size(int *rows, int *cols) +{ + struct winsize ws; + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) { + return -1; + } else { + *cols = ws.ws_col; + *rows = ws.ws_row; + return 0; + } +} + +Term* +init_term() +{ + raw_mode(); + CLEAR_SCREEN + //CURSOR_TOP_LEFT + CURSOR_HIDE + oterm.cx = 0; + oterm.cy = 0; + if (get_term_size(&oterm.rows, &oterm.cols) == -1) + die("getWindowSize"); + return &oterm; +} + + +void +twrite(int x, int y, char *str, size_t len, Cpair col) +{ + if (x > oterm.cols || y > oterm.rows) + return; + char buf[oterm.cols]; + size_t full_buf; + + snprintf(buf, oterm.cols, + "\x1b[%d;%df\x1b[%d;48;5;%d;38;5;%dm%s\x1b[0;0m", + y, x, col.attr, col.bg, col.fg, str); + full_buf = strlen(buf); + write(STDOUT_FILENO, buf, full_buf); +} + +void +tprintf(int x, int y, Cpair col, const char *fmt, ...) +{ + if (x > oterm.cols || y > oterm.rows) + return; + char buf[oterm.cols]; // fmt result + char str[oterm.cols]; // with color and position + size_t full_buf; + va_list vl; + va_start(vl, fmt); + (void)vsnprintf(buf, oterm.cols, fmt, vl); + va_end(vl); + + //print_tb(buf, x, y, col.fg, col.bg); + snprintf(str, oterm.cols, + "\x1b[%d;%df\x1b[%d;48;5;%d;38;5;%dm%s\x1b[0;0m", + y, x, col.attr, col.bg, col.fg, buf); + full_buf = strlen(str); + write(STDOUT_FILENO, str, full_buf); +} + +void +move_to_col(int y) +{ + char buf[8]; + size_t full_buf; + snprintf(buf, 8, "\x1b[%dG", y); + full_buf = strlen(buf); + write(STDOUT_FILENO, buf, full_buf); +} + +void +draw_frame() +{ + int y; + char str[4]; + size_t str_len; + Rune d = 0x2588; + + str_len = utf8encode(d, str); + + // TODO move_to_col + char buf[16]; + int colframe = 233; + size_t full_buf; + snprintf(buf, 16, "\x1b[38;5;%dm", colframe); + full_buf = strlen(buf); + write(STDOUT_FILENO, buf, full_buf); + + for (y = 0; y < oterm.cols ; y++) { + write(STDOUT_FILENO, str, str_len); + } + for (y = 1; y < oterm.rows - 2; y++) { + write(STDOUT_FILENO, str, str_len); + move_to_col(oterm.cols/2); + write(STDOUT_FILENO, str, str_len); + write(STDOUT_FILENO, str, str_len); + move_to_col(oterm.cols); + write(STDOUT_FILENO, str, str_len); + if (y < oterm.rows - 3) { + write(STDOUT_FILENO, "\r\n", 2); + } + } + for (y = 0; y < oterm.cols; y++) { + write(STDOUT_FILENO, str, str_len); + } + for (y = 0; y < oterm.cols; y++) { + write(STDOUT_FILENO, str, str_len); + } + write(STDOUT_FILENO, "\x1b[0;0m", 6); +} + +char +getkey() +{ + int nread; + char c; + while ((nread = read(STDIN_FILENO, &c, 1)) != 1) { + if (nread == -1 && errno != EAGAIN) + die("read"); + } + return c; +} + +//void +//abAppend(struct abuf *ab, const char *s, int len) +//{ +// char *new = realloc(ab->b, ab->len + len); +// if (new == NULL) +// return; +// memcpy(&new[ab->len], s, len); +// ab->b = new; +// ab->len += len; +//} +//void +//abFree(struct abuf *ab) +//{ +// free(ab->b); +//} + +//void +//editorDrawRows(struct abuf *ab) +//{ +// int y; +// for (y = 0; y < term.rows; y++) { +// if (y == term.rows / 3) { +// char welcome[80]; +// int welcomelen = snprintf(welcome, sizeof(welcome), +// "Kilo editor -- version nasmfm"); +// if (welcomelen > term.cols) +// welcomelen = term.cols; +// int padding = (term.cols - welcomelen) / 2; +// if (padding) { +// abAppend(ab, "~", 1); +// padding--; +// } +// while (padding--) +// abAppend(ab, " ", 1); +// abAppend(ab, welcome, welcomelen); +// } else { +// abAppend(ab, "~", 1); +// } +// abAppend(ab, "\x1b[K", 3); +// if (y < term.rows - 1) { +// abAppend(ab, "\r\n", 2); +// } +// } +//} + +//void +//editorRefreshScreen() +//{ +// struct abuf ab = { NULL, 0 }; +// abAppend(&ab, "\x1b[?25l", 6); +// abAppend(&ab, "\x1b[H", 3); +// CURSOR_TOP_LEFT +// editorDrawRows(&ab); +// char buf[32]; +// snprintf(buf, sizeof(buf), "\x1b[%d;%dH", term.cy + 1, term.cx + 1); +// abAppend(&ab, buf, strlen(buf)); +// abAppend(&ab, "\x1b[?25h", 6); +// write(STDOUT_FILENO, ab.b, ab.len); +// abFree(&ab); +//} diff --git a/term.h b/term.h @@ -0,0 +1,41 @@ +/* See LICENSE file for copyright and license details. */ + +#ifndef TERM_H +#define TERM_H + +#define CTRL_KEY(k) ((k)&0x1f) +#define CLEAR_SCREEN write(STDOUT_FILENO, "\x1b[2J\x1b[H", 7); +#define CURSOR_HIDE write(STDOUT_FILENO, "\x1b[?25l", 6); +#define CURSOR_SHOW write(STDOUT_FILENO, "\x1b[?25h", 6); + +#define NORM 0 +#define BOLD 1 +#define RVS 7 + +typedef struct { + int cx; + int cy; + int rows; + int cols; + struct termios orig_termios; +} Term; + +struct abuf { + char *b; + int len; +}; + +typedef struct { + uint16_t fg; + uint16_t bg; + uint8_t attr; +} Cpair; + +Term* init_term(void); +void draw_frame(void); +void twrite(int, int, char *, size_t, Cpair); +void tprintf(int, int, Cpair, const char *, ...); +void move_to_col(int); +char getkey(void); +int get_term_size(int *, int *); +#endif /* TERM_H */ diff --git a/utf8.c b/utf8.c @@ -0,0 +1,53 @@ +/* See LICENSE file for copyright and license details. */ + +#include <stdio.h> +#include <stdint.h> + +#include "utf8.h" +#include "util.h" + +/* macros */ +/* typedef */ +/* function declarations */ +/* global variables */ +/* function implementations */ + + +static const uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; +static const uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; +static const Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; +static const Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; + +size_t +utf8validate(Rune *u, size_t i) +{ + if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) + *u = UTF_INVALID; + for (i = 1; *u > utfmax[i]; ++i) + ; + + return i; +} + +char +utf8encodebyte(Rune u, size_t i) +{ + return utfbyte[i] | (u & ~utfmask[i]); +} +size_t +utf8encode(Rune u, char *c) +{ + size_t len, i; + + len = utf8validate(&u, 0); + if (len > UTF_SIZ) + return 0; + + for (i = len - 1; i != 0; --i) { + c[i] = utf8encodebyte(u, 0); + u >>= 6; + } + c[0] = utf8encodebyte(u, len); + + return len; +} diff --git a/utf8.h b/utf8.h @@ -0,0 +1,15 @@ +/* See LICENSE file for copyright and license details. */ + +#ifndef UTF8_H +#define UTF8_H + +#define UTF_SIZ 4 +#define UTF_INVALID 0xFFFD + +typedef uint_least32_t Rune; +typedef unsigned char uchar; + +size_t utf8validate(Rune *, size_t); +size_t utf8encode(Rune, char *); +char utf8encodebyte(Rune, size_t); +#endif /* UTF8_H */ diff --git a/util.c b/util.c @@ -0,0 +1,44 @@ +/* See LICENSE file for copyright and license details. */ +#include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "util.h" + +void * +ecalloc(size_t nmemb, size_t size) +{ + void *p; + p = calloc(nmemb, size); + FAIL_IF(p == NULL, "calloc"); + return p; +} + +//void * +//erealloc(void *p, size_t len) +//{ +// if ((p = realloc(p, len)) == NULL) +// die("realloc: %s\n", strerror(errno)); +// return p; +//} + +//void +//die(const char *fmt, ...) +//{ +// va_list ap; +// +// va_start(ap, fmt); +// (void)vfprintf(stderr, fmt, ap); +// va_end(ap); +// +// if (fmt[0] != '\0' && fmt[strlen(fmt)-1] == ':') { +// (void)fputc(' ', stderr); +// perror(NULL); +// } else { +// (void)fputc('\n', stderr); +// } +// +// exit(EXIT_FAILURE); +//} diff --git a/util.h b/util.h @@ -0,0 +1,17 @@ +/* See LICENSE file for copyright and license details. */ + +#ifndef UTIL_H +#define UTIL_H + +#define MAX(A, B) ((A) > (B) ? (A) : (B)) +#define MIN(A, B) ((A) < (B) ? (A) : (B)) +#define LEN(A) (sizeof(A)/sizeof(A[0])) +#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) +#define FAIL_IF(EXP, MSG) {if(EXP){fprintf(stderr, "[\033[31mFAILED %d\033[0m] %s\n", __LINE__, MSG);exit(EXIT_FAILURE);}} +#define PERROR(EXP) {if(EXP){print_error(strerror(errno));}}; + +void *ecalloc(size_t, size_t); +void *erealloc(void*, size_t); +//void die(const char *fmt, ...); + +#endif /* UTIL_H */