Procházet zdrojové kódy

Examples, rewrote parts of chapter 4, changes in chapter 5...

master
Ognjen Milan Robovic před 5 měsíci
rodič
revize
c5b959e4e4
6 změnil soubory, kde provedl 192 přidání a 53 odebrání
  1. +100
    -38
      chapter/chapter_4.c
  2. +9
    -2
      chapter/chapter_4.h
  3. +10
    -7
      chapter/chapter_5.c
  4. +5
    -4
      compile.sh
  5. +66
    -0
      example/xcb_window.c
  6. +2
    -2
      xhartae.c

+ 100
- 38
chapter/chapter_4.c Zobrazit soubor

@@ -55,7 +55,6 @@ about our character and string matching and 'syntax_select' to process our text
*/

static int syntax_count = 0; // Number of previously defined syntax rules.
static int syntax_active = FALSE; // Syntax "library" or subprogram was initialized if this value is TRUE.
static int * syntax_enrange = NULL; // Syntax rule can start with any character from 'syntax_begin' if this value is TRUE.
static int * syntax_derange = NULL; // Syntax rule can start with any character from 'syntax_end' if this value is TRUE.
static char * * syntax_begin = NULL; // Strings containing valid character (sub)sequence for begining the scan.
@@ -76,10 +75,10 @@ when 'syntax_active' is FALSE, we'll change it to true, so 'atexit' won't be exe
we're just deallocating (freeing) the memory, so we don't leak it and generate Valgrind warnings.
*/

static void syntax_delete (void) {
void syntax_delete (void) {
int offset;

if (syntax_active == FALSE) { // If 'syntax' subprogram wasn't active, we don't want to deallocate memory, we just return.
if (syntax_count == 0) { // If syntax "library" wasn't used, we don't want to deallocate memory, we just return.
return;
}

@@ -103,8 +102,7 @@ static void syntax_delete (void) {
syntax_colour = deallocate (syntax_colour);
syntax_effect = deallocate (syntax_effect);

syntax_active = FALSE; // Lastly, I like to do this, but you don't have to. We'll use it in chapter five tho.
syntax_count = 0;
syntax_count = 0; // Lastly, I like to do this, but you don't have to. We'll use it in later chapter tho.
}

/*
@@ -112,22 +110,20 @@ In 'syntax_define' function we're reallocating (enlarging) memory, effectively a
be used with 'syntax_select' function to make our syntax highlighting. Lets explain what those function arguments do:

@C
static int syntax_define (int enrange, // Strict matching of string 'begin' in buffer range if FALSE, any character matching if TRUE.
int derange, // Strict matching of string 'end' in buffer range if FALSE, and again, any character matching if TRUE.
char * begin, // String of array of characters to begin matching.
char * end, // String of array of characters to end matching, I don't know why I explain these...
char escape, // Escape character, useful for C preprocessor.
int colour, // Colour.
int effect); // Effect, I hate explaining the code when the identifiers are descriptive.
int syntax_define (int enrange, // Strict matching of string 'begin' in buffer range if FALSE, any character matching if TRUE.
int derange, // Strict matching of string 'end' in buffer range if FALSE, and again, any character matching if TRUE.
char * begin, // String of array of characters to begin matching.
char * end, // String of array of characters to end matching, I don't know why I explain these...
char escape, // Escape character, useful for C preprocessor.
int colour, // Colour.
int effect); // Effect, I hate explaining the code when the identifiers are descriptive.
@
*/

static int syntax_define (int enrange, int derange, char * begin, char * end, char escape, int colour, int effect) {
if (syntax_active == FALSE) { // If our syntax data isn't active, we'll execute this once.
syntax_active = TRUE; // Now we set it to active state, and:

int syntax_define (int enrange, int derange, char * begin, char * end, char escape, int colour, int effect) {
if (syntax_count == 0) { // If our syntax isn't active, we'll execute this only once.
atexit (syntax_delete); // Mark this function to be executed at program exit point.
}
} // It's same if we use more 'syntax_highlight_*' functions.

fatal_failure (begin == NULL, "syntax_define: Begin string is null pointer."); // I don't like checking for errors, but here, voila.
fatal_failure (end == NULL, "syntax_define: End string is null pointer.");
@@ -161,12 +157,15 @@ static int syntax_define (int enrange, int derange, char * begin, char * end, ch
This is more complex, but if you use your eyes to look, your brain to comprehend and your heart to love, I'm sure that you'll understand it.
*/

static int syntax_select (char * string, int * length) {
int syntax_select (char * string, int * length) {
int offset, select;

fatal_failure (syntax_active == FALSE, "syntax_select: Syntax is not active."); // Don't select without rules, abort!
fatal_failure (string == NULL, "syntax_select: String is null.");
fatal_failure (length == NULL, "syntax_select: Length is null.");
if (syntax_count == 0) { // Don't select without rules, return!
return (0);
}

fatal_failure (string == NULL, "syntax_select: String is null.");
fatal_failure (length == NULL, "syntax_select: Length is null.");

// In this first part of the function, we need to check if our syntax rule has been detected at the string offset we've provided. We're looping defined syntax rules and
// choosing whether to compare any of the characters, or full string, depending on 'syntax_enrange' value which is essentially boolean, true or false, which I express with
@@ -192,7 +191,7 @@ static int syntax_select (char * string, int * length) {
} // And now we have our 'select' value.

// If there was no syntax rule detected, we need to return from a function, and increment the offset by setting variable 'length' to 1. If we don't increment it, at the
// first unrecognized character, our second nested-loop inside function 'preview_c_file' would use uninitialized or zero value, depending on how we structured our code
// first unrecognized character, our second nested-loop inside function 'syntax_render_file' would use uninitialized or zero value, depending on how we structured our code
// before that. We also return 'syntax_count' as the syntax rule index, which is invalid, and would produce Valgrind warning if we didn't handle it. In my unimportant
// opinion, this if statement is the ugliest part of the function.
if (select >= syntax_count) {
@@ -233,13 +232,16 @@ static int syntax_select (char * string, int * length) {
/*
Imagine my shock, we can now print coloured text, without regular expressions. Nothing much, we can print it without using 'curses_*' functions, but if we want to preview large,
well more than 24 line of code, we'd want to scroll it or modify it if we're making a text editor, hence, using curses is good. Lets see how our "mini-main" subprogram-like
function does its' work, and how we use 'syntax_*' functions in them.
function does its' work, and how we use 'syntax_*' functions in them, and I also want to make few syntax highlighting abstractions. We can call multiple 'syntax_highlight_*'
functions, but it would mix the highlighting of those languages in that case, so we use 'syntax_delete' to reset it.

Before we begin (Ada pun intended, remove this in final version), I won't (re)align 'separators' and 'keywords', because they fuck-up my comments, which I never write in my
"official" programs. I write comments only here, to explain stuff in more details. Have fun... Oh, and type of variable 'keywords' an array of string pointers of automatic length,
which we get with "sizeof (keywords) / sizeof (keywords [0])" part, for those keywords, it would be 32UL, and we cast it to integer. I use "long" comments outside of functions,
and "short" comments inside them, while aligning them to the longest line of code, or current indentation level.
*/

void preview_c_file (char * text_file, int x, int y) {
// Before we begin (Ada pun intended, remove this in final version), I won't (re)align 'separators' and 'keywords', because they fuck-up my comments, which I never write
// in my "official" programs. I write comments only here, to explain stuff in more details. Have fun... Oh, and type of variable 'keywords' an array of string pointers of
// automatic length, which we get with "sizeof (keywords) / sizeof (keywords [0])" part, for those keywords, it would be 32UL, and we cast it to integer.
void syntax_highlight_c (void) {
char * separators = ".,:;<=>+*-/%!&~^?|()[]{}'\" \t\r\n";

char * keywords [] = {
@@ -249,17 +251,17 @@ void preview_c_file (char * text_file, int x, int y) {
"char", "short", "int", "long", "signed", "unsigned", "float", "double"
};

char * text_data;

int word, reset_x, reset_y;
int word;

curses_configure ();
if (syntax_count != 0) {
syntax_delete ();
}

syntax_define (FALSE, FALSE, "/*", "*/", '\0', COLOUR_GREY, EFFECT_BOLD); // Below, we're simply using our 'syntax_define' function.
syntax_define (FALSE, FALSE, "//", "\n", '\0', COLOUR_GREY, EFFECT_BOLD);
syntax_define (FALSE, FALSE, "#", "\n", '\\', COLOUR_YELLOW, EFFECT_ITALIC);
syntax_define (FALSE, FALSE, "'", "'", '\\', COLOUR_PINK, EFFECT_BOLD);
syntax_define (FALSE, FALSE, "\"", "\"", '\\', COLOUR_PINK, EFFECT_NORMAL);
syntax_define (FALSE, FALSE, "/*", "*/", '\0', COLOUR_GREY, EFFECT_BOLD); // Below, we're simply using our 'syntax_define' function.
syntax_define (FALSE, FALSE, "//", "\n", '\0', COLOUR_GREY, EFFECT_BOLD);
syntax_define (FALSE, FALSE, "#", "\n", '\\', COLOUR_YELLOW, EFFECT_ITALIC);
syntax_define (FALSE, FALSE, "'", "'", '\\', COLOUR_PINK, EFFECT_BOLD);
syntax_define (FALSE, FALSE, "\"", "\"", '\\', COLOUR_PINK, EFFECT_NORMAL);

for (word = 0; word != (int) (sizeof (keywords) / sizeof (keywords [0])); ++word) {
syntax_define (FALSE, TRUE, keywords [word], separators, '\0', COLOUR_YELLOW, EFFECT_BOLD);
@@ -272,6 +274,66 @@ void preview_c_file (char * text_file, int x, int y) {
syntax_define (TRUE, TRUE, "abcdefghijklmnopqrstuvwxyz", separators, '\0', COLOUR_WHITE, EFFECT_NORMAL);
syntax_define (TRUE, TRUE, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', COLOUR_WHITE, EFFECT_BOLD);
syntax_define (TRUE, TRUE, "_", separators, '\0', COLOUR_WHITE, EFFECT_ITALIC);
}

void syntax_highlight_ada (void) {
char * separators = ".,:;<=>#+*-/&|()'\" \t\r\n";

char * keywords [] = {
"abort", "else", "new", "return", "abs", "elsif", "not", "reverse",
"abstract", "end", "null", "accept", "entry", "select", "access", "of",
"separate", "aliased", "exit", "or", "some", "all", "others", "subtype",
"and", "for", "out", "array", "function", "at", "tagged", "generic",
"package", "task", "begin", "goto", "pragma", "body", "private", "then",
"type", "case", "in", "constant", "until", "is", "raise", "use",
"if", "declare", "range", "delay", "limited", "record", "when", "delta",
"loop", "rem", "while", "digits", "renames", "with", "do", "mod",
"requeue", "xor", "procedure", "protected", "interface", "synchronized", "exception", "overriding",
"terminate"
};

int word;

if (syntax_count != 0) {
syntax_delete ();
}

syntax_define (FALSE, FALSE, "--", "\n", '\0', COLOUR_GREY, EFFECT_BOLD);
syntax_define (FALSE, FALSE, "'", "'", '\\', COLOUR_PINK, EFFECT_BOLD);
syntax_define (FALSE, FALSE, "\"", "\"", '\\', COLOUR_PINK, EFFECT_NORMAL);

for (word = 0; word != (int) (sizeof (keywords) / sizeof (keywords [0])); ++word) {
syntax_define (FALSE, TRUE, keywords [word], separators, '\0', COLOUR_YELLOW, EFFECT_BOLD);
}

syntax_define (TRUE, FALSE, "()#", "", '\0', COLOUR_BLUE, EFFECT_NORMAL);
syntax_define (TRUE, FALSE, ".,:;<=>+*-/&|'", "", '\0', COLOUR_CYAN, EFFECT_NORMAL);

syntax_define (TRUE, TRUE, "0123456789", separators, '\0', COLOUR_PINK, EFFECT_BOLD);
syntax_define (TRUE, TRUE, "abcdefghijklmnopqrstuvwxyz", separators, '\0', COLOUR_WHITE, EFFECT_NORMAL);
syntax_define (TRUE, TRUE, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', COLOUR_WHITE, EFFECT_BOLD);
syntax_define (TRUE, TRUE, "_", separators, '\0', COLOUR_WHITE, EFFECT_ITALIC);
}

void syntax_render_file (char * text_file, int x, int y) {
char * text_data; // This local variable will hold our data.

int reset_x, reset_y; // Since we're using curses, we want to reset the offset.

curses_configure (); // Curses configuration, aka printing ugly text.

switch (file_type (text_file)) { // Depending on our file extension, we select highlighting.
case FILE_TYPE_C_SOURCE:
case FILE_TYPE_C_HEADER:
syntax_highlight_c ();
break;
case FILE_TYPE_ADA_BODY:
case FILE_TYPE_ADA_SPECIFICATION:
syntax_highlight_ada ();
break;
default:
break;
}

text_data = file_record (text_file); // And, imagine, importing our file data into a buffer!

@@ -285,10 +347,10 @@ void preview_c_file (char * text_file, int x, int y) {

x = reset_x;
y = reset_y;
select = syntax_count;
select = syntax_count; // I intentionally set this to an invalid value.
length = 0;

for (offset = 0; offset < string_length (text_data); offset += length) { // And it's time to start rendering our C file.
for (offset = 0; offset < string_length (text_data); offset += length) { // And it's time to start rendering our file.
int suboffset, colour, effect;

select = syntax_select (& text_data [offset], & length); // Here we're evaluating variables 'select' and 'length'.


+ 9
- 2
chapter/chapter_4.h Zobrazit soubor

@@ -27,12 +27,19 @@ example, some of them will require functions from some or all previous chapter s
chapters. Instead of that, we'll (re)implement newer stuff with different approach if necessary. That way, you can be sure that if you're reading chapter four, for example, it'll
only use functions and variables defined in chapters zero to three. Lets begin.

I'll write this huge 'preview_c_file' function in procedural style, so to say, and in the next chapter, we'll reimplement it in more modular way, using other functions. Learning
I'll write this huge 'syntax_render_file' function in procedural style, so to say, and in the next chapter, we'll reimplement it in more modular way, using other functions. Learning
anything, including the C programming language, is like a journey. Maybe you think it won't last long, and it ends up being quite long journey, or maybe you think it'll be very
long, that you'll walk miles and miles, and it ends up being short (you rage-quit). The final destination you're going towards always depends on where you left-off, where you're
coming from. For example, if you wrote Ada, you'll like chapter four, if you wrote C++, you'll like chapter five.
*/

extern void preview_c_file (char * text_file, int x, int y);
extern void syntax_delete (void);
extern int syntax_define (int enrange, int derange, char * begin, char * end, char escape, int colour, int effect);
extern int syntax_select (char * string, int * length);

extern void syntax_highlight_c (void);
extern void syntax_highlight_ada (void);

extern void syntax_render_file (char * text_file, int x, int y);

#endif

+ 10
- 7
chapter/chapter_5.c Zobrazit soubor

@@ -149,6 +149,9 @@ void blesses_synchronize (void) {
if (blesses_signal == 24) {
blesses_active = FALSE;
}
if (blesses_signal == 25) {
blesses_zoom = ! blesses_zoom;
}
} break;
default: {
} break;
@@ -163,7 +166,7 @@ void blesses_synchronize (void) {
blesses_sub_framebuffer = allocate (blesses_window_width * blesses_window_height * (int) sizeof (* blesses_sub_framebuffer));
}

// blesses_sub_framebuffer = allocate ((blesses_window_width * blesses_window_height * (int) sizeof (* blesses_sub_framebuffer)) / ((blesses_zoom == TRUE) * 4));
// blesses_sub_framebuffer = allocate ((blesses_window_width * blesses_window_height * (int) sizeof (* blesses_sub_framebuffer)) / ((blesses_zoom == TRUE) ? 4 : 1));

blesses_framebuffer = allocate (blesses_window_width * blesses_window_height * (int) sizeof (* blesses_framebuffer));
}
@@ -176,9 +179,9 @@ void blesses_synchronize (void) {
void blesses_render_background_colour (int background) {
int x, y;

for (y = 0; y != blesses_window_height / ((blesses_zoom == TRUE) * 2); ++y) {
for (x = 0; x != blesses_window_width / ((blesses_zoom == TRUE) * 2); ++x) {
blesses_sub_framebuffer [y * (blesses_window_width / ((blesses_zoom == TRUE) * 2)) + x] = (int) (0XFF000000 | (unsigned int) background);
for (y = 0; y != blesses_window_height / ((blesses_zoom == TRUE) ? 2 : 1); ++y) {
for (x = 0; x != blesses_window_width / ((blesses_zoom == TRUE) ? 2 : 1); ++x) {
blesses_sub_framebuffer [y * (blesses_window_width / ((blesses_zoom == TRUE) ? 2 : 1)) + x] = (int) (0XFF000000 | (unsigned int) background);
}
}
}
@@ -201,8 +204,8 @@ void blesses_render_character (char character, int foreground, int background, i

int offset;

if ((x <= -1) || (x >= blesses_window_width / ((blesses_zoom == TRUE) * 2) - BLESSES_FONT_WIDTH)) return;
if ((y <= -1) || (y >= blesses_window_height / ((blesses_zoom == TRUE) * 2) - BLESSES_FONT_HEIGHT)) return;
if ((x <= -1) || (x >= blesses_window_width / ((blesses_zoom == TRUE) ? 2 : 1) - BLESSES_FONT_WIDTH)) return;
if ((y <= -1) || (y >= blesses_window_height / ((blesses_zoom == TRUE) ? 2 : 1) - BLESSES_FONT_HEIGHT)) return;

fatal_failure (blesses_sub_framebuffer == NULL, "blesses : render_character : Sub framebuffer was not allocated.");
fatal_failure (blesses_framebuffer == NULL, "blesses : render_character : Framebuffer was not allocated.");
@@ -216,7 +219,7 @@ void blesses_render_character (char character, int foreground, int background, i
int u = offset / BLESSES_FONT_WIDTH + y;
int v = offset % BLESSES_FONT_WIDTH + x;

blesses_sub_framebuffer [u * (blesses_window_width / ((blesses_zoom == TRUE) * 2)) + v] = ((font_code [(int) (character - ' ')] >> offset) % 2)
blesses_sub_framebuffer [u * (blesses_window_width / ((blesses_zoom == TRUE) ? 2 : 1)) + v] = ((font_code [(int) (character - ' ')] >> offset) % 2)
? foreground
: background;
}


+ 5
- 4
compile.sh Zobrazit soubor

@@ -16,11 +16,12 @@ gcc -g -Wall -Wextra -Wpedantic -O0 -c -o xhartae.o xhartae.c

gcc -o xhartae xhartae.o chapter/chapter_0.o chapter/chapter_1.o chapter/chapter_2.o chapter/chapter_3.o chapter/chapter_4.o chapter/chapter_5.o chapter/chapter_6.o -lxcb -lxcb-image

gcc -g -Wall -Wextra -Wpedantic -Werror -O0 -o program/program_0 program/program_0.c
gcc -g -Wall -Wextra -Wpedantic -Werror -O0 -o program/program_1 program/program_1.c
gcc -g -Wall -Wextra -Wpedantic -Werror -O0 -o program/program_2 program/program_2.c
gcc -g -Wall -Wextra -Wpedantic -Werror -Ofast -o program/program_0 program/program_0.c
gcc -g -Wall -Wextra -Wpedantic -Werror -Ofast -o program/program_1 program/program_1.c
gcc -g -Wall -Wextra -Wpedantic -Werror -Ofast -o program/program_2 program/program_2.c
gcc -g -Wall -Wextra -Wpedantic -Werror -Ofast -o program/program_z program/program_z.c

gcc -g -Wall -Wextra -Wpedantic -Werror -Ofast -o play_game program/program_z.c
gcc -g -Wall -Wextra -Wpedantic -Werror -Ofast -o example/xcb_window example/xcb_window.c -lxcb

#~splint -weak -warnposix -retvalother -syntax -type chapter/chapter_0.h
#~splint -weak -warnposix -retvalother -syntax -type chapter/chapter_0.c


+ 66
- 0
example/xcb_window.c Zobrazit soubor

@@ -0,0 +1,66 @@
#include <xcb/xcb.h>

#include <stdlib.h>

int main (void) {
int active = 1;

unsigned short int window_width = 640;
unsigned short int window_height = 480;

xcb_window_t window = 0;
xcb_connection_t * connection = NULL;
xcb_screen_t * screen = NULL;
xcb_generic_event_t * event = NULL;

unsigned int window_flags [2] = {
0,
XCB_EVENT_MASK_NO_EVENT |
XCB_EVENT_MASK_EXPOSURE |
XCB_EVENT_MASK_RESIZE_REDIRECT |
XCB_EVENT_MASK_KEY_RELEASE |
XCB_EVENT_MASK_KEY_PRESS |
XCB_EVENT_MASK_BUTTON_RELEASE |
XCB_EVENT_MASK_BUTTON_PRESS
};

connection = xcb_connect (NULL, NULL);

screen = xcb_setup_roots_iterator (xcb_get_setup (connection)).data;

window = xcb_generate_id (connection);

window_flags [0] = screen->black_pixel;

xcb_create_window (connection, screen->root_depth, window, screen->root, 0, 0, window_width, window_height, 10, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual,
XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, window_flags);

xcb_map_window (connection, window);

xcb_flush (connection);

while (active) {
event = xcb_wait_for_event (connection);

switch (event->response_type & 127) {
case XCB_EXPOSE:
xcb_flush (connection);
break;
case XCB_KEY_PRESS:
if ((int) ((xcb_key_press_event_t *) event)->detail == 24) {
active = 0;
}
break;
default:
break;
}

free (event);
}

xcb_destroy_window (connection, window);

xcb_disconnect (connection);

return (0);
}

+ 2
- 2
xhartae.c Zobrazit soubor

@@ -133,7 +133,7 @@ int main (int argc, char * * argv) {
(void) argc;
(void) argv;

preview_c_file ("program/program_1.c", 0, 0);
syntax_render_file ("program/program_1.c", 0, 0);

blesses_configure ();

@@ -143,7 +143,7 @@ int main (int argc, char * * argv) {
blesses_synchronize ();
}

preview_c_file ("program/program_2.c", 0, 0);
syntax_render_file ("example/ada.adb", 0, 0);

return (EXIT_SUCCESS);
}

Načítá se…
Zrušit
Uložit