More to come...
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

175 рядки
10KB

  1. #ifndef CHAPTER_4_HEADER
  2. #define CHAPTER_4_HEADER
  3. #include "chapter_0.h"
  4. #include "chapter_1.h"
  5. #include "chapter_2.h"
  6. #include "chapter_3.h"
  7. /*
  8. In this chapter, you'll learn about:
  9. - Programming languages
  10. - Syntax highlighting
  11. - Importance of readability
  12. - Differences between languages
  13. - More on memory management
  14. - Using curses
  15. I believe that this chapter should be a breakpoint for you to write a simple C program. So far, we've learned in:
  16. - chapter 0: To format our code properly in order to increase readability and we've implemented some core functions for memory management, strings and input / output.
  17. - chapter 1: To declare and define functions, and we've covered character and file descriptor related functions, as well as ASCII table and discussed C keywords.
  18. - chapter 2: To use external variables, function pointers and minor part of 'libncurses' reimplementation that doesn't care about portability.
  19. - chapter 3: To use standard library 'printf' function, and to implement variadic argument functions, while also covering functions and switch statement in more depth.
  20. From this moment onwards, some chapters will have few functions called 'program_*', which we can use to build even larger programs. They'll each have their own dependencies, for
  21. example, some of them will require functions from some or all previous chapter source and header files, but I'll make sure not to use in them functions that'll be in future
  22. 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
  23. only use functions and variables defined in chapters zero to three. Lets begin.
  24. I'll write this huge 'program_curses_view_file' function in somewhat procedural style of programming, so to say, and in the next chapter, we'll use more modular way, using many
  25. 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
  26. 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
  27. 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.
  28. I'll also list a few "traps" right here, where most programmers get caught in:
  29. - My program needs to be cross-platform, fully portable, to run on Windblows, Machos, Leenoocks, Raspberries and on Commodore 64.
  30. - My program needs to be huge, multiple files and folders, everything is abstracted out, even the wrappers for some library.
  31. - 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.
  32. - My compiler warns about stupid things, I don't want to fix all compiler warnings, it'll make the code look bad.
  33. 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
  34. (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,
  35. 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.
  36. Do you see where this is going, adding complexity on top of complexity, abstracting the abstractions, due to standardization. Then again, we have many programming languages, some
  37. of them have multiple standards, like C, C++, Ada, Fortran, basically, popular programming languages. For some of those languages, there are multiple compilers, and sometimes they
  38. support language extensions that aren't the part of the core language. That's why nothing is truly portable.
  39. 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
  40. 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,
  41. 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
  42. that your GPU supports Vulkan, that someone there, out in the big white world wrote a driver for it.
  43. 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,
  44. 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,
  45. 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
  46. 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.
  47. C is good programming language to learn first because it shows you what can you create with very simple tools. Now, lets get to syntax highlighting:
  48. I'll say it as many times as I need, readability is the key to good software. If your code is readable, yet simple, without structure-hell or function-hell, but you don't have the
  49. knowledge to optimize it currently, if you share it under some permissive license and show it to other people who (probably) know more about optimizing the program than you, they
  50. might have less trouble "fixing" it. Again, this depends on more factors, how many global variables you have, because without them compiler will (maybe / probably) be able to
  51. optimize it for you. But the source code being readable is a good start.
  52. However, no matter how readable and nicely formatted it is, it would be harder to read if everything is printed in white text on black background (like it's with ed text editor).
  53. When you open your text editor of choice, as soon as you see certain colour, you know it's a keyword, not an identifier, you notice comments and probably ignore them, it's a good
  54. thing, right? So, there are more than one ways to parse a text file and determine what's a keyword, a number, a string, etc. I'm using simple approach from my older program, which
  55. was made to replace me constantly using '$ cat text_file.c' in terminal.
  56. Imagine this:
  57. This is an array of characters, in C type 'char', and only the last one is '\0', aka CHARACTER_NULL in our enumeration.
  58. [.................................................................................................................................................................................]
  59. This is how we parse it, determine where some syntax rule begins, where it ends, how long it is, without changing that array of characters, aka string.
  60. [.................................................................................................................................................................................]
  61. ^ - at the start, we're pointing to first character, whose index is 0.
  62. ^^^ - then we try to match (for example) first 3 characters, if there's a syntax rule like that, with strict comparison.
  63. ^ - if we matched it, then we need to check if next character, 4th one (with index 3), an ending character or string.
  64. ^ - if it is, we return index of that rule (with function 'syntax_select') and length is 3, without changing the offset.
  65. And we repeat that process until we reach the end of the string, that null termination, it's not a fast algorithm, but it's simple. Easy.
  66. With all that said, learning C is great and all, but lets see some other programming languages, some minimal program in few of them, hello world for example.
  67. @C
  68. // I didn't use preprocessor in this example or real C comments with asterix.
  69. extern int puts (const char *);
  70. int main (void) {
  71. puts ("Hello world!");
  72. return (0);
  73. }
  74. @
  75. @Ada
  76. -- Also, 'use' keyword would apply the namespace, more on that later.
  77. with ada.text_io;
  78. procedure hello_world is
  79. begin
  80. ada.text_io.put_line ("Hello world!");
  81. end hello_world;
  82. @
  83. @C++
  84. // This is C++23 standard, they like new stuff anyway, but it can look more like C if you want.
  85. import module std;
  86. int main () {
  87. std::print ("Hello world!\n");
  88. }
  89. @
  90. @HolyC
  91. // Masterpiece.
  92. "Hello world!\n";
  93. @
  94. @Flat
  95. ; This will run only on 64-bit GNU/Linux OS without issues.
  96. format ELF64 executable 3
  97. segment readable executable
  98. mov rax, 1
  99. mov rdi, 1
  100. mov rsi, string
  101. mov rdx, [length]
  102. syscall
  103. mov rax, 60
  104. mov rdi, 0
  105. syscall
  106. segment readable writable
  107. string db 'Hello world!', 10, 0
  108. length dq $-string
  109. @
  110. @Fortran
  111. ! Fortran is great programming language, but it can be autistic at times.
  112. program hello_world
  113. print *, 'Hello world!'
  114. end program hello_world
  115. @
  116. @Python
  117. # Well, they call it "second best language for everything" for some reason...
  118. print ("Hello world!")
  119. @
  120. Learning C well will make learning those other programming languages, except assembly languages, a walk in the park.
  121. */
  122. extern int syntax_define (int enrange, int derange, char * begin, char * end, char escape, int colour, int effect); // This must be called before 'syntax_select' function.
  123. extern int syntax_select (char * string, int * length); // And we're not dealing with null-terminated strings here.
  124. // Internally use 'syntax_define' to make C (and Ada below) syntax highlighting, it will use global variables internal to 'chapter_4.c' file.
  125. // Worth noting:
  126. // - We'll only have one "predefined syntax highlighting" per file type, because we don't want them to clash with each other.
  127. // - We could use several syntax highlighting rules if we made one more level of arrays for all those global variables, and a rule to switch between them.
  128. // - If you want to add support for some other language, you can try to make, for example 'syntax_highlight_python', it'll be a good exercise.
  129. extern void syntax_highlight_c (void);
  130. extern void syntax_highlight_ada (void);
  131. extern void program_curses_view_file (char * text_file, int x, int y); // This is our subprogram that'll view some textual file in terminal, using our curses "library".
  132. #endif