clean up, merged prototypes and anon's prototype rework
This commit is contained in:
parent
f2cca50f97
commit
452d55d012
24
Makefile
24
Makefile
@ -1,15 +1,27 @@
|
|||||||
CFLAGS:=-std=c99 -O2 -Wall -Wextra -Wpedantic -Wvla -Wshadow -Wundef
|
include chad.mk
|
||||||
|
DEBUG:=1
|
||||||
|
CFLAGS:=-std=c99 -O2 -Wvla -Wshadow -Wundef $(if ${DEBUG}, ${CHAD_DEBUG},'')
|
||||||
CPPFLAGS:=-D_FORTIFY_SOURCE=2
|
CPPFLAGS:=-D_FORTIFY_SOURCE=2
|
||||||
|
|
||||||
SRC.dir:=src/
|
SRC.dir:=source/
|
||||||
SRC:=$(shell find ${SRC.dir} -iname '*.c')
|
SRC:=$(shell find ${SRC.dir} -iname '*.c')
|
||||||
|
HDR:=$(shell find ${SRC.dir} -iname '*.h')
|
||||||
OBJ:=$(subst .c,.o,${SRC})
|
OBJ:=$(subst .c,.o,${SRC})
|
||||||
|
|
||||||
|
OUT:=hl
|
||||||
|
OUTARGS:=${OUT} < source/main.c
|
||||||
|
|
||||||
|
main: ${OBJ} ${HDR}
|
||||||
|
${LINK.c} ${OBJ} -o hl
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
${COMPILE.c} $< -o $@
|
${COMPILE.c} $< -o $@
|
||||||
|
|
||||||
hl: ${OBJ}
|
install:
|
||||||
${LINK.c} ${OBJ} -o $@
|
cp hl /usr/bin/hl
|
||||||
|
|
||||||
new:
|
clean:
|
||||||
g++ src2/main.cpp -o hl -ggdb
|
-rm ${OBJ}
|
||||||
|
-rm ${OUT}
|
||||||
|
|
||||||
|
test: chad_test
|
||||||
|
21
chad.mk
Normal file
21
chad.mk
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Make script for Chad projects
|
||||||
|
# This script depends on the following variables
|
||||||
|
# - OUT : output program name
|
||||||
|
# - OUTARGS : default flags to fork ${OUT} with
|
||||||
|
|
||||||
|
#
|
||||||
|
CHAD_DEBUG:=-Og -ggdb -pg -fno-inline
|
||||||
|
|
||||||
|
# Programs to check warnings for as defined by the Chad standard
|
||||||
|
GCC:=gcc
|
||||||
|
GCC.warnings:=-Wall -Wextra -Wpedantic
|
||||||
|
CLANG:=clang
|
||||||
|
CLANG.warnings:=-Weverything
|
||||||
|
VALGRIND:=valgrind
|
||||||
|
|
||||||
|
chad_test:
|
||||||
|
${GCC} ${GCC.warnings} ${SRC} -o ${OUT}
|
||||||
|
${CLANG} ${GCC.warnings} ${SRC} -o ${OUT}
|
||||||
|
${VALGRIND} ${OUT} ${OUTARGS}
|
||||||
|
|
||||||
|
.DEFAULT_GOAL:=main
|
100
hl_xolatile.c
100
hl_xolatile.c
@ -1,100 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#define UNUSED(x) ((void) (x))
|
|
||||||
|
|
||||||
#define ALLOCATION_CHUNK (10UL)
|
|
||||||
|
|
||||||
enum {
|
|
||||||
NORMAL, BOLD, DARKNESS, ITALIC,
|
|
||||||
UNDERLINE, BLINK, DUNNO_6, REVERSE,
|
|
||||||
INVISIBLE
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
GREY, RED, GREEN, YELLOW,
|
|
||||||
BLUE, PINK, CYAN, WHITE,
|
|
||||||
CANCEL
|
|
||||||
};
|
|
||||||
|
|
||||||
static char * buffer = NULL;
|
|
||||||
static size_t buffer_size = 0;
|
|
||||||
|
|
||||||
static void render_character(char * character) {
|
|
||||||
write(STDOUT_FILENO, character, sizeof (*character));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void render_string(char * string) {
|
|
||||||
write(STDOUT_FILENO, string, strlen(string));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void render_colour(int colour,
|
|
||||||
int effect) {
|
|
||||||
char format[8] = "\033[ ;3 m";
|
|
||||||
|
|
||||||
format[2] = (char) (effect % 9) + '0';
|
|
||||||
format[5] = (char) (colour % 8) + '0';
|
|
||||||
|
|
||||||
render_string(format);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void render_cancel(void) {
|
|
||||||
render_string("\033[0m");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int is_separator(char character) {
|
|
||||||
if (( isascii(character))
|
|
||||||
&& (!isalnum(character))
|
|
||||||
&& (character != '_')) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int compare_multiple_strings(char * string,
|
|
||||||
const char * * strings,
|
|
||||||
const int count) {
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (!strcmp(string, strings[i])) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
} while (++i != count);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc,
|
|
||||||
char * * argv) {
|
|
||||||
UNUSED(argc);
|
|
||||||
UNUSED(argv);
|
|
||||||
|
|
||||||
buffer = realloc(buffer, ALLOCATION_CHUNK);
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (!((buffer_size + 1) % ALLOCATION_CHUNK)) {
|
|
||||||
// Linear incremental reallocation (advanced)!
|
|
||||||
size_t chunks = (buffer_size + 1) / ALLOCATION_CHUNK;
|
|
||||||
buffer = realloc(buffer, ++chunks * ALLOCATION_CHUNK);
|
|
||||||
}
|
|
||||||
buffer[buffer_size] = '\0';
|
|
||||||
read(STDIN_FILENO, &buffer[buffer_size], sizeof (*buffer));
|
|
||||||
++buffer_size;
|
|
||||||
} while (buffer[buffer_size - 1]);
|
|
||||||
|
|
||||||
buffer[buffer_size - 1] = '\0';
|
|
||||||
|
|
||||||
render_colour(RED, BOLD);
|
|
||||||
render_string(buffer);
|
|
||||||
render_cancel();
|
|
||||||
|
|
||||||
free (buffer);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
default:
|
|
||||||
gcc -g -Wall -Wextra -Wpedantic -o hl hl_xolatile.c
|
|
||||||
clang -g -Weverything -o hl hl_xolatile.c
|
|
||||||
|
|
||||||
# 'This shit requires to be in /usr/bin currently...'
|
|
||||||
# 'There are unused functions that will be used, ignore now.'
|
|
||||||
# 'Next please do [$ sudo cp hl /usr/bin/hl].'
|
|
||||||
# 'Then test it with example [$ echo ABCDEF | valgrind hl].'
|
|
34
source/chad.h
Normal file
34
source/chad.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef CHAD_H
|
||||||
|
#define CHAD_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define UNUSED(x) ((void)x)
|
||||||
|
|
||||||
|
// Terminal manipulation
|
||||||
|
#define TERMINAL_RESET "\033[0m"
|
||||||
|
|
||||||
|
#define TERMINAL_COLOR_FG_BLACK "\033[30m"
|
||||||
|
#define TERMINAL_COLOR_FG_RED "\033[31m"
|
||||||
|
#define TERMINAL_COLOR_FG_GREEN "\033[32m"
|
||||||
|
#define TERMINAL_COLOR_FG_YELLOW "\033[33m"
|
||||||
|
#define TERMINAL_COLOR_FG_BLUE "\033[34m"
|
||||||
|
#define TERMINAL_COLOR_FG_MAGENTA "\033[35m"
|
||||||
|
#define TERMINAL_COLOR_FG_CYAN "\033[36m"
|
||||||
|
#define TERMINAL_COLOR_FG_WHITE "\033[37m"
|
||||||
|
|
||||||
|
#define TERMINAL_COLOR_BG_BLACK "\033[40m"
|
||||||
|
#define TERMINAL_COLOR_BG_RED "\033[41m"
|
||||||
|
#define TERMINAL_COLOR_BG_GREEN "\033[42m"
|
||||||
|
#define TERMINAL_COLOR_BG_YELLOW "\033[43m"
|
||||||
|
#define TERMINAL_COLOR_BG_BLUE "\033[44m"
|
||||||
|
#define TERMINAL_COLOR_BG_MAGENTA "\033[45m"
|
||||||
|
#define TERMINAL_COLOR_BG_CYAN "\033[46m"
|
||||||
|
#define TERMINAL_COLOR_BG_WHITE "\033[47m"
|
||||||
|
|
||||||
|
#define TERMINAL_STYLE_BOLD "\033[1m"
|
||||||
|
#define TERMINAL_STYLE_ITALICS "\033[3m"
|
||||||
|
#define TERMINAL_STYLE_REVERSE "\033[7m"
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
106
source/hl.h
Normal file
106
source/hl.h
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <uthash.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "chad.h"
|
||||||
|
|
||||||
|
typedef void (*attribute_callback_t)(const char * const string,
|
||||||
|
const int length,
|
||||||
|
void * const attributes);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char * key;
|
||||||
|
attribute_callback_t callback;
|
||||||
|
UT_hash_handle hh;
|
||||||
|
} display_t;
|
||||||
|
display_t * display_table = NULL;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void * attributes;
|
||||||
|
struct hl_group_t * link;
|
||||||
|
} hl_group_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
KEYWORD,
|
||||||
|
MATCH,
|
||||||
|
REGION
|
||||||
|
} token_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
hl_group_t * hl;
|
||||||
|
token_t t;
|
||||||
|
char* syntax;
|
||||||
|
} token; // XXX: this will have to be renamed
|
||||||
|
|
||||||
|
/* Temp solution
|
||||||
|
*/
|
||||||
|
token * token_table[1000];
|
||||||
|
int token_table_top = 0;
|
||||||
|
|
||||||
|
token * new_token(const char * const syntax,
|
||||||
|
const token_t t,
|
||||||
|
const hl_group_t * const g) {
|
||||||
|
token * mt = (token*)malloc(sizeof(token));
|
||||||
|
mt->hl = g;
|
||||||
|
mt->t = t;
|
||||||
|
mt->syntax = syntax;
|
||||||
|
token_table[token_table_top++] = mt;
|
||||||
|
return mt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void new_keyword_tokens(const char * const * words,
|
||||||
|
hl_group_t * const g) {
|
||||||
|
while (*words) {
|
||||||
|
new_token(*words, KEYWORD, g);
|
||||||
|
words = words + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int token_fits(const char* const pattern,
|
||||||
|
const char* const to) {
|
||||||
|
if (pattern == NULL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (int i = 0;; i++) {
|
||||||
|
if (pattern[i] == '\00') {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
if (to[i] == '\00'
|
||||||
|
|| pattern[i] != to[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_word_separator(const char character) {
|
||||||
|
if (( isascii(character))
|
||||||
|
&& (!isalnum(character))
|
||||||
|
&& ( character != '_')) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_string(const char * const string,
|
||||||
|
const char * const mode) {
|
||||||
|
for (const char * s = string; *s != '\00';) {
|
||||||
|
int f;
|
||||||
|
int i = 0;
|
||||||
|
for (; i < token_table_top; i++) {
|
||||||
|
f = token_fits(token_table[i]->syntax, s);
|
||||||
|
if(f){ break; };
|
||||||
|
}
|
||||||
|
//
|
||||||
|
display_t * display;
|
||||||
|
HASH_FIND_STR(display_table, mode, display);
|
||||||
|
//
|
||||||
|
if(f){
|
||||||
|
display->callback(s, f, token_table[i]->hl->attributes);
|
||||||
|
s += f;
|
||||||
|
} else {
|
||||||
|
display->callback(s, 0, NULL);
|
||||||
|
++s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
95
source/main.c
Normal file
95
source/main.c
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include "hl.h"
|
||||||
|
|
||||||
|
#define ALLOCATION_CHUNK (10UL)
|
||||||
|
|
||||||
|
static char * buffer = NULL;
|
||||||
|
static size_t buffer_size = 0;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int attribute;
|
||||||
|
int foreground_color;
|
||||||
|
int background_color;
|
||||||
|
} terminal_hl_t;
|
||||||
|
|
||||||
|
void cterm_render_callback(const char * const string,
|
||||||
|
const int length,
|
||||||
|
void * const attributes) {
|
||||||
|
if(!length){
|
||||||
|
putchar(*string);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UNUSED(attributes);
|
||||||
|
fputs(TERMINAL_STYLE_BOLD, stdout);
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
putchar(*(string+i));
|
||||||
|
}
|
||||||
|
fputs(TERMINAL_RESET, stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc,
|
||||||
|
char * * argv) {
|
||||||
|
UNUSED(argc);
|
||||||
|
UNUSED(argv);
|
||||||
|
|
||||||
|
// Buffer init
|
||||||
|
buffer = realloc(buffer, ALLOCATION_CHUNK);
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (!((buffer_size + 1) % ALLOCATION_CHUNK)) {
|
||||||
|
/* Linear incremental reallocation (advanced)!
|
||||||
|
*/
|
||||||
|
size_t chunks = (buffer_size + 1) / ALLOCATION_CHUNK;
|
||||||
|
buffer = realloc(buffer, ++chunks * ALLOCATION_CHUNK);
|
||||||
|
}
|
||||||
|
buffer[buffer_size] = '\0';
|
||||||
|
read(STDIN_FILENO, &buffer[buffer_size], sizeof (*buffer));
|
||||||
|
++buffer_size;
|
||||||
|
} while (buffer[buffer_size - 1]);
|
||||||
|
|
||||||
|
buffer[buffer_size - 1] = '\0';
|
||||||
|
|
||||||
|
// Highlight init
|
||||||
|
const char * c_keywords[] = {
|
||||||
|
"register", "volatile", "auto", "const", "static", "extern", "if", "else",
|
||||||
|
"do", "while", "for", "continue", "switch", "case", "default", "break",
|
||||||
|
"enum", "union", "struct", "typedef", "goto", "void", "return", "sizeof",
|
||||||
|
"char", "short", "int", "long", "signed", "unsigned", "float", "double",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
const char * preprocessor_keywords[] = {
|
||||||
|
"#include", "#pragma", "#define", "#undef", "#ifdef", "#ifndef", "#elifdef", "#elifndef",
|
||||||
|
"#if", "#elif", "#else", "#endif", "#embed", "#line", "#error", "#warning",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
terminal_hl_t my_hl = (terminal_hl_t) {
|
||||||
|
.attribute = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
display_t * cterm = &(display_t) {
|
||||||
|
.key = "cterm",
|
||||||
|
.callback = cterm_render_callback
|
||||||
|
};
|
||||||
|
hl_group_t mygroup = (hl_group_t) {
|
||||||
|
.link = NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
HASH_ADD_STR(display_table,
|
||||||
|
key,
|
||||||
|
cterm);
|
||||||
|
new_keyword_tokens(c_keywords, &mygroup);
|
||||||
|
new_keyword_tokens(preprocessor_keywords, &mygroup);
|
||||||
|
|
||||||
|
//
|
||||||
|
render_string(buffer, "cterm");
|
||||||
|
putchar('\n');
|
||||||
|
free (buffer);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
386
src/main.c
386
src/main.c
@ -1,386 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#define ALLOCATION_CHUNK (1024UL)
|
|
||||||
#define ALLOCATION_LIMIT (1024UL * 1024UL)
|
|
||||||
|
|
||||||
#ifndef PROGRAM_NAME
|
|
||||||
# define PROGRAM_NAME "hl"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum { NORMAL, BOLD, DARKNESS, ITALIC, UNDERLINE, BLINK, DUNNO_6, REVERSE, INVISIBLE };
|
|
||||||
enum { GREY, RED, GREEN, YELLOW, BLUE, PINK, CYAN, WHITE, CANCEL };
|
|
||||||
|
|
||||||
static int colour_short_comment = GREY;
|
|
||||||
static int colour_long_comment = GREY;
|
|
||||||
static int colour_short_string = PINK;
|
|
||||||
static int colour_long_string = RED;
|
|
||||||
static int colour_separator = BLUE;
|
|
||||||
static int colour_number = CYAN;
|
|
||||||
static int colour_keyword = YELLOW;
|
|
||||||
static int colour_preprocessor = YELLOW;
|
|
||||||
static int colour_default = WHITE;
|
|
||||||
|
|
||||||
static int effect_short_comment = BOLD;
|
|
||||||
static int effect_long_comment = BOLD;
|
|
||||||
static int effect_short_string = BOLD;
|
|
||||||
static int effect_long_string = BOLD;
|
|
||||||
static int effect_separator = BOLD;
|
|
||||||
static int effect_number = BOLD;
|
|
||||||
static int effect_keyword = BOLD;
|
|
||||||
static int effect_preprocessor = BOLD;
|
|
||||||
static int effect_default = BOLD;
|
|
||||||
|
|
||||||
static unsigned long int buffer_size = 0;
|
|
||||||
|
|
||||||
static void render_character (
|
|
||||||
char character
|
|
||||||
) {
|
|
||||||
putchar (character);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void render_string (
|
|
||||||
char * string
|
|
||||||
) {
|
|
||||||
while (* string) render_character (* string++);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void render_colour (
|
|
||||||
int colour,
|
|
||||||
int effect
|
|
||||||
) {
|
|
||||||
if (colour == CANCEL) {
|
|
||||||
render_string ("\033[0m");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
render_string ("\033[");
|
|
||||||
render_character ((char) (effect % 9) + '0');
|
|
||||||
render_string (";3");
|
|
||||||
render_character ((char) (colour % 8) + '0');
|
|
||||||
render_character ('m');
|
|
||||||
}
|
|
||||||
|
|
||||||
static int is_space (
|
|
||||||
char character
|
|
||||||
) {
|
|
||||||
switch (character)
|
|
||||||
{
|
|
||||||
case ' ': case '\t': case '\r': case '\n':
|
|
||||||
return (1);
|
|
||||||
default:
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int is_separator (
|
|
||||||
char character
|
|
||||||
) {
|
|
||||||
switch (character)
|
|
||||||
{
|
|
||||||
case ' ': case '\t': case '\r': case '\n':
|
|
||||||
case '+': case '-': case '*': case '/':
|
|
||||||
case '(': case ')': case '[': case ']':
|
|
||||||
case '{': case '}': case '<': case '>':
|
|
||||||
case ';': case ':': case ',': case '.':
|
|
||||||
case '!': case '&': case '|': case '?':
|
|
||||||
case '~': case '^': case '%': case '=':
|
|
||||||
return (1);
|
|
||||||
default:
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int compare_multiple_strings (
|
|
||||||
char * string,
|
|
||||||
const char ** strings,
|
|
||||||
const int count
|
|
||||||
) {
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (strcmp (string, strings [i]) == 0) {
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
++i;
|
|
||||||
} while (i != count);
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int render_short_comment (
|
|
||||||
char * buffer,
|
|
||||||
int data_offset
|
|
||||||
) {
|
|
||||||
render_colour (colour_short_comment, effect_short_comment);
|
|
||||||
|
|
||||||
do {
|
|
||||||
render_character (buffer [data_offset]);
|
|
||||||
++data_offset;
|
|
||||||
} while ((buffer [data_offset] != '\n') && (buffer [data_offset] != '\0'));
|
|
||||||
|
|
||||||
render_character (buffer [data_offset]);
|
|
||||||
++data_offset;
|
|
||||||
|
|
||||||
return (data_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int render_long_comment (
|
|
||||||
char * buffer,
|
|
||||||
int data_offset
|
|
||||||
) {
|
|
||||||
render_colour (colour_long_comment, effect_long_comment);
|
|
||||||
|
|
||||||
do {
|
|
||||||
render_character (buffer [data_offset]);
|
|
||||||
++data_offset;
|
|
||||||
} while (((buffer [data_offset] != '/') ||
|
|
||||||
(buffer [data_offset - 1] != '*')) &&
|
|
||||||
(buffer [data_offset] != '\0'));
|
|
||||||
|
|
||||||
render_character (buffer [data_offset]);
|
|
||||||
++data_offset;
|
|
||||||
|
|
||||||
return (data_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int render_short_string (
|
|
||||||
char * buffer,
|
|
||||||
int data_offset
|
|
||||||
) {
|
|
||||||
render_colour (colour_short_string, effect_short_string);
|
|
||||||
|
|
||||||
do {
|
|
||||||
render_character (buffer [data_offset]);
|
|
||||||
++data_offset;
|
|
||||||
if (buffer [data_offset - 1] == '\\') {
|
|
||||||
render_character (buffer [data_offset]);
|
|
||||||
++data_offset;
|
|
||||||
}
|
|
||||||
} while ((buffer [data_offset] != '\'') && (buffer [data_offset] != '\0'));
|
|
||||||
|
|
||||||
render_character (buffer [data_offset]);
|
|
||||||
++data_offset;
|
|
||||||
|
|
||||||
return (data_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int render_long_string (
|
|
||||||
char * buffer,
|
|
||||||
int data_offset
|
|
||||||
) {
|
|
||||||
render_colour (colour_long_string, effect_long_string);
|
|
||||||
|
|
||||||
do {
|
|
||||||
render_character (buffer [data_offset]);
|
|
||||||
++data_offset;
|
|
||||||
if (buffer [data_offset - 1] == '\\') {
|
|
||||||
render_character (buffer [data_offset]);
|
|
||||||
++data_offset;
|
|
||||||
}
|
|
||||||
} while ((buffer [data_offset] != '"') && (buffer [data_offset] != '\0'));
|
|
||||||
|
|
||||||
render_character (buffer [data_offset]);
|
|
||||||
++data_offset;
|
|
||||||
|
|
||||||
return (data_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int render_separator (
|
|
||||||
char * buffer,
|
|
||||||
int data_offset
|
|
||||||
) {
|
|
||||||
if (is_space (buffer [data_offset]) != 0) {
|
|
||||||
render_colour (WHITE, NORMAL);
|
|
||||||
} else {
|
|
||||||
render_colour (colour_separator, effect_separator);
|
|
||||||
}
|
|
||||||
|
|
||||||
render_character (buffer [data_offset]);
|
|
||||||
++data_offset;
|
|
||||||
|
|
||||||
return (data_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int render_number (
|
|
||||||
char * buffer,
|
|
||||||
int data_offset
|
|
||||||
) {
|
|
||||||
render_colour (colour_number, effect_number);
|
|
||||||
|
|
||||||
do {
|
|
||||||
render_character (buffer [data_offset]);
|
|
||||||
++data_offset;
|
|
||||||
} while ((is_separator (buffer [data_offset]) == 0) && (buffer [data_offset] != '\0'));
|
|
||||||
|
|
||||||
return (data_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int render_word (
|
|
||||||
char * buffer,
|
|
||||||
int data_offset
|
|
||||||
) {
|
|
||||||
const char * c_keywords [32] = {
|
|
||||||
"register", "volatile", "auto", "const", "static", "extern", "if", "else",
|
|
||||||
"do", "while", "for", "continue", "switch", "case", "default", "break",
|
|
||||||
"enum", "union", "struct", "typedef", "goto", "void", "return", "sizeof",
|
|
||||||
"char", "short", "int", "long", "signed", "unsigned", "float", "double"
|
|
||||||
};
|
|
||||||
|
|
||||||
const char * preprocessor_keywords [16] = {
|
|
||||||
"#include", "#pragma", "#define", "#undef", "#ifdef", "#ifndef", "#elifdef", "#elifndef",
|
|
||||||
"#if", "#elif", "#else", "#endif", "#embed", "#line", "#error", "#warning"
|
|
||||||
};
|
|
||||||
|
|
||||||
char * word = NULL;
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
do {
|
|
||||||
word = realloc (word, sizeof (* word) * (unsigned long int) (i + 1));
|
|
||||||
word [i] = buffer [data_offset + i];
|
|
||||||
++i;
|
|
||||||
} while ((is_separator (buffer [data_offset + i]) == 0) && (buffer [data_offset + i] != '\0'));
|
|
||||||
|
|
||||||
word = realloc (word, sizeof (* word) * (unsigned long int) (i + 1));
|
|
||||||
word [i] = '\0';
|
|
||||||
|
|
||||||
if (compare_multiple_strings (word, c_keywords, 32) != 0) {
|
|
||||||
render_colour (colour_keyword, effect_keyword);
|
|
||||||
} else if (compare_multiple_strings (word, preprocessor_keywords, 16) != 0) {
|
|
||||||
render_colour (colour_preprocessor, effect_preprocessor);
|
|
||||||
} else {
|
|
||||||
render_colour (colour_default, effect_default);
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
render_character (buffer [data_offset]);
|
|
||||||
++data_offset;
|
|
||||||
} while ((is_separator (buffer [data_offset]) == 0) && (buffer [data_offset] != '\0'));
|
|
||||||
|
|
||||||
free (word);
|
|
||||||
|
|
||||||
return (data_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
handle_buffer(
|
|
||||||
char * buffer
|
|
||||||
) {
|
|
||||||
int offset = 0;
|
|
||||||
while (buffer [offset] != '\0') {
|
|
||||||
if ((buffer [offset] == '/') && (buffer [offset + 1] == '/')) {
|
|
||||||
offset = render_short_comment (buffer, offset);
|
|
||||||
} else if ((buffer [offset] == '/') && (buffer [offset + 1] == '*')) {
|
|
||||||
offset = render_long_comment (buffer, offset);
|
|
||||||
} else if (buffer [offset] == '\'') {
|
|
||||||
offset = render_short_string (buffer, offset);
|
|
||||||
} else if (buffer [offset] == '"') {
|
|
||||||
offset = render_long_string (buffer, offset);
|
|
||||||
} else if (is_separator (buffer [offset]) != 0) {
|
|
||||||
offset = render_separator (buffer, offset);
|
|
||||||
} else if ((buffer [offset] >= '0') && (buffer [offset] <= '9')) {
|
|
||||||
offset = render_number (buffer, offset);
|
|
||||||
} else {
|
|
||||||
offset = render_word (buffer, offset);
|
|
||||||
}
|
|
||||||
render_colour (CANCEL, NORMAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
|
||||||
slurp(const char * fn)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
char * b;
|
|
||||||
FILE * fp = fopen(fn, "r");
|
|
||||||
if (fp)
|
|
||||||
{
|
|
||||||
fseek(fp, 0, SEEK_END);
|
|
||||||
len = ftell(fp);
|
|
||||||
rewind(fp);
|
|
||||||
b = malloc(len);
|
|
||||||
if (b &&
|
|
||||||
len != fread(b, 1, len, fp))
|
|
||||||
{ perror(PROGRAM_NAME); }
|
|
||||||
fclose(fp);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ return NULL; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* "Short" */
|
|
||||||
#define SHORT_OPT(c,s) \
|
|
||||||
if ((c == argv[0][0] && argv[0][1] == '\0') || \
|
|
||||||
0 == strncmp(argv[0], s, strlen(s)))
|
|
||||||
|
|
||||||
#define OPT(s) \
|
|
||||||
if (0 == strncmp(argv[0], s, strlen(s)))
|
|
||||||
|
|
||||||
int main (
|
|
||||||
int argc,
|
|
||||||
char ** argv
|
|
||||||
) {
|
|
||||||
char * buffer = NULL;
|
|
||||||
|
|
||||||
if (argc != 1) {
|
|
||||||
(void) argv;
|
|
||||||
while (++argv, --argc) {
|
|
||||||
if (argv[0][0] == '-') {
|
|
||||||
argv[0]++;
|
|
||||||
SHORT_OPT ('?',"help") {
|
|
||||||
fprintf (stderr, PROGRAM_NAME ": hl [OPTIONS] FILES ...\n");
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
OPT ("version") {
|
|
||||||
fprintf(stderr, PROGRAM_NAME ": Version 9000\n");
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fprintf (stderr, PROGRAM_NAME ": Unrecognized option '%s'\n", argv [0]);
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ((buffer = slurp (argv [0]))) {
|
|
||||||
handle_buffer (buffer);
|
|
||||||
free (buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = realloc (buffer, ALLOCATION_CHUNK);
|
|
||||||
|
|
||||||
#define MEMFAIL(v) if (v == NULL) { perror(PROGRAM_NAME); return (1); }
|
|
||||||
MEMFAIL(buffer);
|
|
||||||
|
|
||||||
do {
|
|
||||||
if ((buffer_size + 1) % ALLOCATION_CHUNK == 0) {
|
|
||||||
buffer = realloc (buffer,
|
|
||||||
((buffer_size + 1)
|
|
||||||
/ ALLOCATION_CHUNK + 1)
|
|
||||||
* ALLOCATION_CHUNK);
|
|
||||||
MEMFAIL(buffer);
|
|
||||||
}
|
|
||||||
buffer [buffer_size] = '\0'; /* Fixing Valgrind warnings... */
|
|
||||||
read (STDIN_FILENO, & buffer [buffer_size], sizeof (* buffer));
|
|
||||||
++buffer_size;
|
|
||||||
} while ((buffer [buffer_size - 1] != '\0') /*||
|
|
||||||
(buffer_size != ALLOCATION_LIMIT)*/);
|
|
||||||
|
|
||||||
buffer [buffer_size - 1] = '\0';
|
|
||||||
|
|
||||||
// Checking if short comments work...
|
|
||||||
/* Checking if long comments work... */
|
|
||||||
|
|
||||||
handle_buffer(buffer);
|
|
||||||
|
|
||||||
free (buffer);
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
#include <map>
|
|
||||||
#include <vector>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
BOLD,
|
|
||||||
ITALICS,
|
|
||||||
UNDERLINE,
|
|
||||||
END
|
|
||||||
} attr_t;
|
|
||||||
|
|
||||||
typedef void (*attr_callback_t)(void);
|
|
||||||
void bold_on(void){
|
|
||||||
fputs("\033[1m", stdout);
|
|
||||||
}
|
|
||||||
void bold_off(void){
|
|
||||||
fputs("\033[0m", stdout);
|
|
||||||
}
|
|
||||||
attr_callback_t attr_callbacks[END*2] = {
|
|
||||||
(attr_callback_t)bold_on,
|
|
||||||
(attr_callback_t)bold_off,
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef int color;
|
|
||||||
|
|
||||||
struct hl_t {
|
|
||||||
attr_t attrs;
|
|
||||||
color fg_color;
|
|
||||||
color bg_color;
|
|
||||||
//? font;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct hl_group {
|
|
||||||
char* name;
|
|
||||||
std::map<char*, hl_t> o;
|
|
||||||
hl_group* link;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
KEYWORD,
|
|
||||||
MATCH,
|
|
||||||
REGION
|
|
||||||
} token_t;
|
|
||||||
|
|
||||||
struct token{
|
|
||||||
hl_group* hl;
|
|
||||||
token_t t;
|
|
||||||
char* syntax;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<token*> token_table;
|
|
||||||
|
|
||||||
token* newtoken(char* syntax, token_t t, hl_group* g){
|
|
||||||
token* mt = new (token){
|
|
||||||
.hl = g,
|
|
||||||
.t = t,
|
|
||||||
.syntax = syntax
|
|
||||||
};
|
|
||||||
token_table.push_back(mt);
|
|
||||||
return mt;
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
#include "Highlight.h"
|
|
||||||
|
|
||||||
const char *const test_string = "this (test) is my test string which im with testing in this test";
|
|
||||||
|
|
||||||
int fits(const char* const pattern, const char* const to){
|
|
||||||
if(pattern == NULL){ return true; }
|
|
||||||
for(int i = 0;; i++){
|
|
||||||
if(pattern[i] == '\00'){ return i; }
|
|
||||||
if(to[i] == '\00' or pattern[i] != to[i]){ return false; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void render_string(const char* const string, char* mode){
|
|
||||||
for(const char* s = string; *s != '\00';){
|
|
||||||
for(auto &i : token_table){
|
|
||||||
int f;
|
|
||||||
f = fits(i->syntax, s);
|
|
||||||
if(f){
|
|
||||||
int pos = i->hl->o.find(mode)->second.attrs;
|
|
||||||
attr_callbacks[pos]();
|
|
||||||
for(int h = 0; h < f; h++){
|
|
||||||
putchar(*(s+h));
|
|
||||||
}
|
|
||||||
attr_callbacks[pos+1]();
|
|
||||||
s += f;
|
|
||||||
}else{
|
|
||||||
putchar(*s);
|
|
||||||
++s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
signed main(){
|
|
||||||
hl_group mygroup = (hl_group){
|
|
||||||
.name = "test",
|
|
||||||
.link = NULL
|
|
||||||
};
|
|
||||||
mygroup.o["cterm"] = (hl_t){
|
|
||||||
.attrs = BOLD
|
|
||||||
};
|
|
||||||
token* mytoken = newtoken("test", KEYWORD, &mygroup);
|
|
||||||
render_string(test_string, "cterm");
|
|
||||||
putchar('\n');
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user