Browse Source

Realigned chapter 4 and added comments...

master
Ognjen Milan Robovic 5 months ago
parent
commit
c4c0d92136
3 changed files with 164 additions and 37 deletions
  1. +40
    -32
      chapter/chapter_4.c
  2. +26
    -5
      chapter/chapter_4.h
  3. +98
    -0
      example/ada.adb

+ 40
- 32
chapter/chapter_4.c View File

@@ -75,7 +75,7 @@ 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.
*/

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

if (syntax_count == 0) { // If syntax "library" wasn't used, we don't want to deallocate memory, we just return.
@@ -160,8 +160,8 @@ This is more complex, but if you use your eyes to look, your brain to comprehend
int syntax_select (char * string, int * length) {
int offset, select;

if (syntax_count == 0) { // Don't select without rules, return!
return (0);
if (syntax_count == 0) { // Don't select without rules, return!
return (syntax_count);
}

fatal_failure (string == NULL, "syntax_select: String is null.");
@@ -171,30 +171,34 @@ int syntax_select (char * string, int * length) {
// 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
// 'int' type for "type-safety simplicity". Keep in mind that we're not returning or modifying the string we provided, so it won't be null-terminated, instead I think
// it's best to modify only variable 'length', hence we check with 'string_compare_limit' function.
for (select = offset = 0; select != syntax_count; ++select) { // We're looping defined syntax rules:
if (syntax_enrange [select] == FALSE) { // Choosing the comparisson:
if (syntax_derange [select] == FALSE) {
if (string_compare_limit (string, syntax_begin [select], string_length (syntax_begin [select])) == TRUE) { // Limiting our string comparisson.
break; // If strings are same, we exit the loop.

for (select = offset = 0; select != syntax_count; ++select) { // We're looping defined syntax rules:
int begin = string_length (syntax_begin [select]);

if (syntax_enrange [select] == FALSE) { // Choosing the comparisson based on 'syntax_enrange':
if (syntax_derange [select] == FALSE) { // Either full string, or any character in it.
if (string_compare_limit (string, syntax_begin [select], begin) == TRUE) { // Limiting our string comparisson.
break; // If strings are same, we exit the loop.
}
} else {
if ((string_compare_limit (string, syntax_begin [select], string_length (syntax_begin [select])) == TRUE)
&& (character_compare_array (string [offset + string_length (syntax_begin [select])], syntax_end [select]) == TRUE)) {
if ((string_compare_limit (string, syntax_begin [select], begin) == TRUE) // We need to see if we found our string, and:
&& (character_compare_array (string [offset + begin], syntax_end [select]) == TRUE)) { // If next character, after the string is in 'syntax_end'.
break;
}
} // Otherwise, we implcitly continue the loop.
}
} else { // Else, we compare any character.
if (character_compare_array (string [offset], syntax_begin [select]) == TRUE) { // With our obviously named function...
break; // We found it, exit the loop!
} // If we didn't, just continue.
} else { // Else, we compare any character.
if (character_compare_array (string [offset], syntax_begin [select]) == TRUE) { // With our obviously named function...
break; // We found it, exit the loop!
} // If we didn't, just continue.
}
} // And now we have our 'select' value.
} // 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 '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) {

if (select >= syntax_count) { // If we didn't found our string, return.
* length = 1;
return (syntax_count);
}
@@ -203,30 +207,33 @@ int syntax_select (char * string, int * length) {
// to again, separate two cases for matching any character or full string, except that we use it to determine its' match-length. Important difference is also that there's
// special case where we have escape character matching, and where 'syntax_end' string is empty (but not NULL), so in that case we match only one character. We could have
// nested loop there, and second loop would need goto statement to exit it, so we only use one loop.
for (offset = 1; string [offset - 1] != '\0'; ++offset) { // Now, offset must be 1, and we loop...
if (string [offset] == syntax_escape [select]) { // Here's our escape exception.

for (offset = 1; string [offset - 1] != '\0'; ++offset) { // Now, offset must be 1, and we loop...
int end = string_length (syntax_end [select]);

if (string [offset] == syntax_escape [select]) { // Here's our escape exception.
++offset;
continue;
}

if (syntax_derange [select] == FALSE) { // Choosing what to compare, yet again...
if (string_compare_limit (& string [offset], syntax_end [select], string_length (syntax_end [select])) == TRUE) { // Again, we're comparing full string.
* length = offset + string_length (syntax_end [select]); // We found it, yaay!
if (syntax_derange [select] == FALSE) { // Choosing what to compare, yet again...
if (string_compare_limit (& string [offset], syntax_end [select], end) == TRUE) { // Again, we're comparing full string.
* length = offset + end; // We found it, yaay!
break;
}
} else {
if (syntax_end [select] [0] == CHARACTER_NULL) { // And here's our empty string exception.
* length = offset;
if (syntax_end [select] [0] == CHARACTER_NULL) { // And here's our empty string exception.
* length = offset; // On that case, we break from loop.
break;
}
if (character_compare_array (string [offset], syntax_end [select]) == TRUE) {
if (character_compare_array (string [offset], syntax_end [select]) == TRUE) { // Otherwise, we compare to see if the end is near!
* length = offset;
break;
}
} // These two loops look similar, but no!
} // And now we have our 'length' value.
} // These two loops look similar, but no!
} // And now we have our 'length' value.

return (select); // Lastly, return syntax rule index.
return (select); // Lastly, return syntax rule index.
}

/*
@@ -253,12 +260,12 @@ void syntax_highlight_c (void) {

int word;

if (syntax_count != 0) {
syntax_delete ();
if (syntax_count != 0) { // If syntax was used, free it, then we can redefine them.
syntax_delete (); // This way, we won't mix syntaces if we use this multiple times.
}

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, "/*", "*/", '\0', COLOUR_GREY, EFFECT_BOLD); // Below, we're simply using our 'syntax_define' function.
syntax_define (FALSE, FALSE, "//", "\n", '\0', COLOUR_GREY, EFFECT_BOLD); // I really don't think I need to explain those, so...
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);
@@ -361,6 +368,7 @@ void syntax_render_file (char * text_file, int x, int y) {
// Or, if you find this more intuitive:
// colour = (select < syntax_count) ? syntax_colour [select] : COLOUR_WHITE;
// effect = (select < syntax_count) ? syntax_effect [select] : EFFECT_NORMAL;

if (select >= syntax_count) { // Here, we're handling error value of 'syntax_select'.
colour = COLOUR_WHITE;
effect = EFFECT_NORMAL;


+ 26
- 5
chapter/chapter_4.h View File

@@ -27,13 +27,34 @@ 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 '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.
I'll write this huge 'syntax_render_file' function in somewhat procedural style of programming, so to say, and in the next chapter, we'll use more modular way, using many more
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 and 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.

I'll also list a few "traps" right here, where most programmers get caught in:

- My program needs to be cross-platform, fully portable, to run on Windblows, Machos, Leenoocks, Raspberries and on Commodore 64.
- My program needs to be huge, multiple files and folders, everything is abstracted out, even the wrappers for some library.
- My program doesn't need to free used memory, my operating system will do it for me, I don't care about memory leaks, only nerds do.
- My compiler warns about stupid things, I don't want to fix all compiler warnings, it'll make the code look bad.

First of all, there are a lot of standards, people who don't have more important work to do make those. There are a lot of CPU architectures, x86-64 being used a lot, then ISA
(instruction set architecture) such as CISC, RISC, MISC, OISC, and even more things that should't matter for you like SIMD, AVX, ST, MMX, XMM, YMM, ZMM, et fucking cetera. Then,
we have many many GPU hardware, they each have some part of their own ISA, writing direct code for one GPU won't work on other GPUs, so we need to use OpenGL, Vulkan or Direct3D.
Do you see where this is going, adding complexity on top of complexity, abstracting the abstractions, due to standardization.

If every company make their own standard, thinking they're smartest, there's no standardization. Just look at the mirror, at your PC, laptop, whatever, then take a look outside
the window, and say out loud "My program will be written in C, it will run on 64-bit CPUs, it will depend only on Vulkan API, it will use XCB for display.". Take a deep breath,
you're not writing some part of the program for the company, you're having fun, you're sane. Then again, pray to Khronos, your OS maintainers or developers and your GPU vendor
that your GPU supports Vulkan, that someone there, out in the big white world wrote a driver for it.

Keep in mind that I don't work for any programming related company and I want to, also I don't have college, I learned C by writing it a lot and reading it from time to time. Now,
hear me out, if 1000 people with some CS degree wrote a simple C program, all of those would look very similar. That's because they've been programmed into that line of thinking,
which is dangerous in my opinion for one reason: They think they're always right. I learned a lot from talking with smart people, some of them have CS degree, some not, so I don't
own what I know, no one owns anyones' knowledge, but they weren't always right. So, if you don't have a CS degree, you can learn C easier, that's my point.
*/

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);



+ 98
- 0
example/ada.adb View File

@@ -0,0 +1,98 @@
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Copyright (c) 2023 - Ognjen 'xolatile' Milan Robovic
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Xabina is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either
-- version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
-- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

with core;

package magic is

------------------------------------------------------------------------------------------

type list is (
ignite, illuminate, bladecharm, battlecry
);

type mark is mod 72;

------------------------------------------------------------------------------------------

type constant_type is new core.constant_type with
record
self : boolean := false;
health : integer := 0;
armour : integer := 0;
mana : integer := 0;
stamina : integer := 0;
distance : integer := 0;
tribute : natural := 0;
end record;

type variable_type is new core.variable_type with
record
enchantment : natural := 0;
end record;

type constant_list is array (list) of constant_type;
type variable_list is array (mark) of variable_type;

------------------------------------------------------------------------------------------

constant_data : constant constant_list := (
(core.magic, "Ignite ", '*', core.colour.yellow, core.effect.italic, false, -3, 0, 0, -1, 7, 1),
(core.magic, "Illuminate ", '*', core.colour.yellow, core.effect.italic, false, 0, 0, 0, -1, 13, 1),
(core.magic, "Bladecharm ", '*', core.colour.red, core.effect.italic, true, 0, -3, 0, -1, 7, 3),
(core.magic, "Battlecry ", '*', core.colour.red, core.effect.italic, true, -1, -1, 0, -1, 7, 2)
);

variable_data : variable_list;

------------------------------------------------------------------------------------------

procedure generate;
procedure render;

------------------------------------------------------------------------------------------

end magic;

with core, map;

package body magic is

------------------------------------------------------------------------------------------

procedure generate is
y : natural := 0;
x : natural := 0;
identifier : natural := 0;
begin
for this in map.mark
loop
y := core.randomize (0, natural (map.height'last));
x := core.randomize (0, natural (map.width'last));
identifier := core.randomize (0, natural (list'size));
map.variable_data (this) := (integer (y), integer (x), core.magic, identifier);
end loop;
end generate;

procedure render is
symbol : character := ' ';
colour : character := core.colour.white;
effect : character := core.effect.normal;
begin
for this in map.mark
loop
symbol := constant_data (list'val (map.variable_data (this).identifier)).symbol;
colour := constant_data (list'val (map.variable_data (this).identifier)).colour;
effect := constant_data (list'val (map.variable_data (this).identifier)).effect;
core.render_character (symbol, colour, effect, core.screen_height (map.variable_data (this).y), core.screen_width (map.variable_data (this).x));
end loop;
end render;

------------------------------------------------------------------------------------------

end magic;

Loading…
Cancel
Save