forked from xolatile/xhartae
Pushing as an update, unfinished comments in chapter 3...
This commit is contained in:
parent
bbef2a609e
commit
17df8ad502
@ -50,51 +50,71 @@ static void echo_one_by_one (int number) {
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
@
|
||||
|
||||
You can find situations in which fall-through cases are good, for example, they can be very useful when encoding some CPU instructions into machine code, but guess what? The
|
||||
compiler will think you've made some kind of mistake, like that you forgot to break from those cases, and it'll warn you about it. I like to clean all compiler warnings (and some
|
||||
linter warnings, if they're not totally brain-dead), so I just don't use them. I know, sounds stupid, but there's usually some other way to do it, and to get the same solution.
|
||||
@
|
||||
Since we have several methods for printing text, they use standard output (terminal), file descriptor and a string respectively, we could implement them in separate functions, use
|
||||
function pointers or simply copy+paste bunch of code into lot of functions, and form a "function family". I'm using the simplest solution here, we have one general function, and
|
||||
explicitly declaring where I want my data to be printed. Simple as that. Lets call it 'printing_crossroad' for fun.
|
||||
*/
|
||||
|
||||
static void print_colour (char colour_id) { // We use "special" character '/' to use terminal colours.
|
||||
switch (colour_id) {
|
||||
case '/': out ("/", 1); break; // If we have literally typed "//" in our 'format' string, it'll just output "/".
|
||||
case '0': terminal_colour (COLOUR_GREY, EFFECT_BOLD); break; // Making the use of our 'terminal_colour' function.
|
||||
case '1': terminal_colour (COLOUR_RED, EFFECT_BOLD); break;
|
||||
case '2': terminal_colour (COLOUR_GREEN, EFFECT_BOLD); break;
|
||||
case '3': terminal_colour (COLOUR_YELLOW, EFFECT_BOLD); break;
|
||||
case '4': terminal_colour (COLOUR_BLUE, EFFECT_BOLD); break;
|
||||
case '5': terminal_colour (COLOUR_PINK, EFFECT_BOLD); break;
|
||||
case '6': terminal_colour (COLOUR_CYAN, EFFECT_BOLD); break;
|
||||
case '7': terminal_colour (COLOUR_WHITE, EFFECT_BOLD); break;
|
||||
case '-': terminal_cancel (); break; // Making the use of our 'terminal_cancel' function, "/-" will end colouring.
|
||||
default: out ("?", 1); break; // Now, if we provided some other character after "/", I like to make an intentional mismatch.
|
||||
} // It's not such a big mistake to abort the program, since it's obvious that results are bad.
|
||||
static void printing_crossroad (char * text, int size, int file, char * string) { // We pass a lot of arguments here, it makes things simpler below.
|
||||
if (file > 0) { // We don't want to print to standard input, which is file descriptor of value 0.
|
||||
file_write (file, text, size); // And we simply "output" our text of certain size to wanted location.
|
||||
} else if (string != NULL) {
|
||||
string_copy_limit (string, text, size);
|
||||
} else {
|
||||
out (text, size);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_format (char format_id, va_list argument_list) { // We use character '%' this time, same as 'printf' function does, lets see...
|
||||
switch (format_id) {
|
||||
static void print_colour (char colour_id, int file, char * string) {
|
||||
switch (colour_id) { // We use "special" character '/' to use terminal colours.
|
||||
case '/': printing_crossroad ("/", 1, file, string); break; // If we have literally typed "//" in our 'format' string, it'll just output "/".
|
||||
case '0': printing_crossroad ("\033[1;30m", 7, file, string); break; // Notice that we couldn't use function 'terminal_colour', it only uses standard output.
|
||||
case '1': printing_crossroad ("\033[1;31m", 7, file, string); break; // Since we want to support file descriptors and strings, we use 'printing_crossroad'.
|
||||
case '2': printing_crossroad ("\033[1;32m", 7, file, string); break;
|
||||
case '3': printing_crossroad ("\033[1;33m", 7, file, string); break;
|
||||
case '4': printing_crossroad ("\033[1;34m", 7, file, string); break;
|
||||
case '5': printing_crossroad ("\033[1;35m", 7, file, string); break;
|
||||
case '6': printing_crossroad ("\033[1;36m", 7, file, string); break;
|
||||
case '7': printing_crossroad ("\033[1;37m", 7, file, string); break;
|
||||
case '-': printing_crossroad ("\033[0m", 4, file, string); break;
|
||||
default: printing_crossroad ("?", 1, file, string); break; // Now, if we provided some other character after "/", I like to make an intentional mismatch.
|
||||
} // It's not such a big mistake to abort the program, since it's obvious that results are bad.
|
||||
}
|
||||
|
||||
static void print_format (char format_id, va_list argument_list, int file, char * string) {
|
||||
switch (format_id) { // We use character '%' this time, same as 'printf' function does, lets see...
|
||||
case '%': {
|
||||
out ("%", 1);
|
||||
printing_crossroad ("%", 1, file, string);
|
||||
} break;
|
||||
case 'i': {
|
||||
int integer; // Leave these local variables uninitialized (don't assign a value to them).
|
||||
int integer; // Leave these local variables uninitialized (don't assign a value to them).
|
||||
char * format;
|
||||
int length;
|
||||
integer = va_arg (argument_list, int); // Macro 'va_arg' will move argument from the list into our local variable, with the provided type.
|
||||
echo (number_to_string (integer)); // You might get the feeling that this isn't type safe, and you'd be totally right.
|
||||
length = string_length (format = number_to_string (integer));
|
||||
printing_crossroad (format, length, file, string); // You might get the feeling that this isn't type safe, and you'd be totally right.
|
||||
} break;
|
||||
case 'f': {
|
||||
double ieee754; // Because we used curly braces, we can declare local variables in these blocks of code.
|
||||
ieee754 = va_arg (argument_list, double); // I intentionally call this IEEE754 because I hate to use 'float' and 'double'.
|
||||
echo (number_to_string ((int) ieee754)); // And we're printing to terminal our (rounded) number.
|
||||
char * format;
|
||||
// And we're printing to terminal our (rounded) number.
|
||||
format = number_to_string ((int) ieee754);
|
||||
printing_crossroad (format, string_length (format), file, string);
|
||||
} break;
|
||||
case 's': {
|
||||
char * string; // Really simple stuff, but needs some time getting used to it, we're writing in an old language.
|
||||
string = va_arg (argument_list, char *); // In my opinion, this should be the part of the C language itself, not some macro black magic.
|
||||
echo (string); // You can write a bunch of variadic functions yourself if you want, to easy your workflow in some cases.
|
||||
char * literal; // Really simple stuff, but needs some time getting used to it, we're writing in an old language.
|
||||
literal = va_arg (argument_list, char *); // In my opinion, this should be the part of the C language itself, not some macro black magic.
|
||||
// You can write a bunch of variadic functions yourself if you want, to easy your workflow in some cases.
|
||||
printing_crossroad (literal, string_length (literal), file, string);
|
||||
} break;
|
||||
default: {
|
||||
out ("?", 1); // Again, I think it's best to print a bad thing, see it and fix it, then to abort the program in this case...
|
||||
printing_crossroad ("?", 1, file, string); // Again, I think it's best to print a bad thing, see it and fix it, then to abort the program in this case...
|
||||
} break;
|
||||
}
|
||||
|
||||
@ -132,10 +152,10 @@ void print (char * format, ...) {
|
||||
for (offset = 0; offset != length; ++offset) { // We start iterating through our 'format' string, and looking for special characters below.
|
||||
if (format [offset] == '/') { // Colouring special character is '/', and colours are specified from '0'...'7', and '-' to cancel them.
|
||||
++offset;
|
||||
print_colour (format [offset]); // We're calling function that will colour our printed text, this one is simple.
|
||||
print_colour (format [offset], 0, NULL); // We're calling function that will colour our printed text, this one is simple.
|
||||
} else if (format [offset] == '%') { // And formatting special character is '%', it'll use variadic arguments!
|
||||
++offset;
|
||||
print_format (format [offset], argument_list); // We're calling function that will format our agruments, so we pass variable 'argument_list'.
|
||||
print_format (format [offset], argument_list, 0, NULL); // We're calling function that will format our agruments, so we pass variable 'argument_list'.
|
||||
} else {
|
||||
out (& format [offset], 1); // Not a special character? Okay, we'll just print them one by one.
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ It is distributed in the hope that it will be useful or harmful, it really depen
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "chapter_0.h"
|
||||
#include "chapter_1.h"
|
||||
|
||||
/*
|
||||
Now, time has come to talk about (sadly) the most important standard library function in C programming language. Function 'printf' is like some semi-drunk old man, stumbling on
|
||||
|
10
compile.sh
10
compile.sh
@ -13,4 +13,14 @@ gcc -g -Wall -Wextra -Wpedantic -O0 -c -o xhartae.o xhartae.c
|
||||
|
||||
gcc -o xhartae xhartae.o chapters/chapter_0.o chapters/chapter_1.o chapters/chapter_2.o chapters/chapter_3.o
|
||||
|
||||
splint -weak -warnposix -retvalother -syntax -type chapters/chapter_0.h
|
||||
splint -weak -warnposix -retvalother -syntax -type chapters/chapter_0.c
|
||||
splint -weak -warnposix -retvalother -syntax -type chapters/chapter_1.h
|
||||
splint -weak -warnposix -retvalother -syntax -type chapters/chapter_1.c
|
||||
splint -weak -warnposix -retvalother -syntax -type chapters/chapter_2.h
|
||||
splint -weak -warnposix -retvalother -syntax -type chapters/chapter_2.c
|
||||
splint -weak -warnposix -retvalother -syntax -type chapters/chapter_3.h
|
||||
splint -weak -warnposix -retvalother -syntax -type chapters/chapter_3.c
|
||||
splint -weak -warnposix -retvalother -syntax -type xhartae.c
|
||||
|
||||
exit
|
||||
|
18
xhartae.c
18
xhartae.c
@ -6,16 +6,16 @@ And when you do redistribute it or modify it, it will use either version 3 of th
|
||||
It is distributed in the hope that it will be useful or harmful, it really depends... But no warranty what so ever, seriously. See GNU/GPLv3.
|
||||
*/
|
||||
|
||||
#ifndef STATIC_SOURCE
|
||||
#include "chapters/chapter_0.h"
|
||||
#include "chapters/chapter_1.h"
|
||||
#include "chapters/chapter_2.h"
|
||||
#include "chapters/chapter_3.h"
|
||||
#ifdef STATIC_SOURCE
|
||||
#include "chapters/chapter_0.c"
|
||||
#include "chapters/chapter_1.c"
|
||||
#include "chapters/chapter_2.c"
|
||||
#include "chapters/chapter_3.c"
|
||||
#else
|
||||
#include "chapters/chapter_0.c"
|
||||
#include "chapters/chapter_1.c"
|
||||
#include "chapters/chapter_2.c"
|
||||
#include "chapters/chapter_3.c"
|
||||
#include "chapters/chapter_0.h"
|
||||
#include "chapters/chapter_1.h"
|
||||
#include "chapters/chapter_2.h"
|
||||
#include "chapters/chapter_3.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user