瀏覽代碼

Pushing as an update, unfinished comments in chapter 3...

master^2
父節點
當前提交
17df8ad502
共有 4 個檔案被更改,包括 67 行新增36 行删除
  1. +47
    -27
      chapters/chapter_3.c
  2. +1
    -0
      chapters/chapter_3.h
  3. +10
    -0
      compile.sh
  4. +9
    -9
      xhartae.c

+ 47
- 27
chapters/chapter_3.c 查看文件

@@ -50,51 +50,71 @@ static void echo_one_by_one (int number) {
default: break; 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 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 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. 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_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) { // We use character '%' this time, same as 'printf' function does, lets see...
switch (format_id) {
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 '%': { case '%': {
out ("%", 1);
printing_crossroad ("%", 1, file, string);
} break; } break;
case 'i': { 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. 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; } break;
case 'f': { case 'f': {
double ieee754; // Because we used curly braces, we can declare local variables in these blocks of code. 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'. 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; } break;
case 's': { 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; } break;
default: { 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; } 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. 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. if (format [offset] == '/') { // Colouring special character is '/', and colours are specified from '0'...'7', and '-' to cancel them.
++offset; ++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! } else if (format [offset] == '%') { // And formatting special character is '%', it'll use variadic arguments!
++offset; ++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 { } else {
out (& format [offset], 1); // Not a special character? Okay, we'll just print them one by one. out (& format [offset], 1); // Not a special character? Okay, we'll just print them one by one.
} }


+ 1
- 0
chapters/chapter_3.h 查看文件

@@ -12,6 +12,7 @@ It is distributed in the hope that it will be useful or harmful, it really depen
#include <stdarg.h> #include <stdarg.h>


#include "chapter_0.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 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
- 0
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 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 exit

+ 9
- 9
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. 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 #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 #endif


/* /*


Loading…
取消
儲存