file_write_read.c: move from cpp-cheat

Improve README C section with example tree.
This commit is contained in:
Ciro Santilli 六四事件 法轮功
2019-06-07 00:00:03 +00:00
parent 2a27157dbf
commit 9fba97740c
6 changed files with 178 additions and 11 deletions

View File

@@ -11659,6 +11659,8 @@ One "downside" of glibc is that it exercises much more kernel functionality on i
This section contains userland content, such as <<c>>, <<cpp>> and <<posix>> examples. This section contains userland content, such as <<c>>, <<cpp>> and <<posix>> examples.
Userland assembly content is located at: <<userland-assembly>>. It was split from this section basically becase we were hitting the HTML `h6` limit, stupid web :-)
This content makes up the bulk of the link:userland/[] directory. This content makes up the bulk of the link:userland/[] directory.
Getting started at: <<userland-setup>> Getting started at: <<userland-setup>>
@@ -11671,14 +11673,30 @@ This section was originally moved in here from: https://github.com/cirosantilli/
Programs under link:userland/c/[] are examples of link:https://en.wikipedia.org/wiki/ANSI_C[ANSI C] programming: Programs under link:userland/c/[] are examples of link:https://en.wikipedia.org/wiki/ANSI_C[ANSI C] programming:
* link:userland/c/hello.c[]
* main` and environment
** link:userland/c/return0.c[]
** link:userland/c/return1.c[]
** link:userland/c/return2.c[]
** link:userland/c/exit0.c[]
** link:userland/c/exit1.c[]
** link:userland/c/exit2.c[]
** link:userland/c/print_argv.c[]
* Standard library * Standard library
** assert.h ** `assert.h`
*** link:userland/c/assert_fail.c[] *** link:userland/c/assert_fail.c[]
** `stdlib.h` ** `stdlib.h`
*** Exit related *** exit
**** link:userland/c/abort.c[] **** link:userland/c/abort.c[]
*** malloc
Userland assembly content is located at: <<userland-assembly>>. It was split from this section basically becase we were hitting the HTML `h6` limit, stupid web :-) **** link:userland/c/out_of_memory.c[]
** `stdio.h`
*** link:userland/c/stderr.c[]
*** link:userland/c/getchar.c[]
*** File IO
**** link:userland/c/file_write_read.c[]
* Fun
** link:userland/c/infinite_loop.c[]
==== GCC C extensions ==== GCC C extensions
@@ -13084,7 +13102,7 @@ Note how Sn is weirdly packed inside Dn, and Dn weirdly packed inside Qn, likely
And you can't access the higher bytes at D16 or greater with Sn. And you can't access the higher bytes at D16 or greater with Sn.
===== ARM vadd instruction ===== ARM VADD instruction
* link:userland/arch/arm/vadd_scalar.S[]: see also: <<floating-point-assembly>> * link:userland/arch/arm/vadd_scalar.S[]: see also: <<floating-point-assembly>>
* link:userland/arch/arm/vadd_vector.S[]: see also: <<simd-assembly>> * link:userland/arch/arm/vadd_vector.S[]: see also: <<simd-assembly>>
@@ -13203,20 +13221,20 @@ link:userland/arch/aarch64/add_vector.S[]
Good first instruction to learn SIMD: <<simd-assembly>> Good first instruction to learn SIMD: <<simd-assembly>>
===== ARMv8 aarch64 fadd instruction ===== ARMv8 aarch64 FADD instruction
* link:userland/arch/aarch64/fadd_vector.S[]: see also: <<simd-assembly>> * link:userland/arch/aarch64/fadd_vector.S[]: see also: <<simd-assembly>>
* link:userland/arch/aarch64/fadd_scalar.S[]: see also: <<floating-point-assembly>> * link:userland/arch/aarch64/fadd_scalar.S[]: see also: <<floating-point-assembly>>
====== ARM fadd vs vadd ====== ARM FADD vs VADD
It is very confusing, but `fadds` and `faddd` in Aarch32 are <<gnu-gas-assembler-arm-unified-syntax,pre-UAL>> for `vadd.f32` and `vadd.f64` which we use in this tutorial: <<arm-vadd-instruction>> It is very confusing, but `fadds` and `faddd` in Aarch32 are <<gnu-gas-assembler-arm-unified-syntax,pre-UAL>> for `vadd.f32` and `vadd.f64` which we use in this tutorial: <<arm-vadd-instruction>>
The same goes for most ARMv7 mnemonics: `f*` is old, and `v*` is the newer better syntax. The same goes for most ARMv7 mnemonics: `f*` is old, and `v*` is the newer better syntax.
But then, in ARMv8, they decided to use <<armv8-aarch64-fadd-instruction>> as the main floating point add name, and get rid of `vadd`! But then, in ARMv8, they decided to use <<armv8-aarch64-fadd-instruction>> as the main floating point add name, and get rid of VADD!
Also keep in mind that fused multiply add is `fmadd`. Also keep in mind that fused multiply add is FMADD.
Examples at: <<simd-assembly>> Examples at: <<simd-assembly>>

10
lkmc.h
View File

@@ -4,6 +4,7 @@
#define LKMC_H #define LKMC_H
#if !defined(__ASSEMBLER__) #if !defined(__ASSEMBLER__)
#include <errno.h>
#include <inttypes.h> #include <inttypes.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
@@ -20,6 +21,15 @@ LKMC_ASSERT_EQ_DECLARE(32);
LKMC_ASSERT_EQ_DECLARE(64); LKMC_ASSERT_EQ_DECLARE(64);
void lkmc_assert_fail(uint32_t line); void lkmc_assert_fail(uint32_t line);
void lkmc_assert_memcmp(const void *s1, const void *s2, size_t n, uint32_t line); void lkmc_assert_memcmp(const void *s1, const void *s2, size_t n, uint32_t line);
#define LKMC_ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0]))
/* Standard action to take in case of a file IO error. */
#define LKMC_IO_ERROR(function, path) \
fprintf(stderr, "error: %s errno = %d, path = %s\n", function, errno, path); \
exit(EXIT_FAILURE);
#define LKMC_TMP_EXT ".tmp"
#define LKMC_TMP_FILE __FILE__ LKMC_TMP_EXT
#define LKMC_TMP_FILE_NAMED(name) __FILE__ "__" name LKMC_TMP_EXT
#endif #endif
/* Assert that the given branch instruction is taken. */ /* Assert that the given branch instruction is taken. */

View File

@@ -430,6 +430,7 @@ path_properties_tuples = (
'exit1.c': {'exit_status': 1}, 'exit1.c': {'exit_status': 1},
'exit2.c': {'exit_status': 2}, 'exit2.c': {'exit_status': 2},
'false.c': {'exit_status': 1}, 'false.c': {'exit_status': 1},
'file_write_read.c': {'baremetal': False},
'getchar.c': {'interactive': True}, 'getchar.c': {'interactive': True},
'infinite_loop.c': {'more_than_1s': True}, 'infinite_loop.c': {'more_than_1s': True},
'out_of_memory.c': {'disrupts_system': True}, 'out_of_memory.c': {'disrupts_system': True},

View File

@@ -5,5 +5,5 @@
LKMC_PROLOGUE LKMC_PROLOGUE
mov $3, %rax mov $3, %rax
dec %rax dec %rax
LKMC_ASSERT_EQ_32(%rax, $2) LKMC_ASSERT_EQ(%rax, $2)
LKMC_EPILOGUE LKMC_EPILOGUE

View File

@@ -0,0 +1,136 @@
#include <lkmc.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
/* Returns the size of the given open `FILE*`.
*
* If an error occurs, returns `-1L`.
*
* Does not work for pipes.
*/
long fget_file_size(FILE *fp) {
long oldpos;
long return_value;
oldpos = ftell(fp);
if (oldpos == -1L) {
return -1L;
}
if (fseek(fp, 0, SEEK_END) != 0) {
return -1L;
}
return_value = ftell(fp);
if (return_value == -1L) {
return -1L;
}
/* Restore the old position. */
if (fseek(fp, oldpos , SEEK_SET) != 0) {
return -1L;
}
return return_value;
}
/* Same as `file_size`, but takes the path instead of a `FILE*`. */
long file_size(char *path) {
FILE *fp;
long return_value;
fp = fopen(path, "r");
if (fp == NULL) {
return -1L;
}
return_value = fget_file_size(fp);
if (fclose(fp) == EOF) {
return -1L;
}
return return_value;
}
/* Read the entire file to a char[] dynamically allocated inside this function.
*
* Returns a pointer to the start of that array.
*
* In case of any error, returns NULL.
*
* http://stackoverflow.com/questions/174531/easiest-way-to-get-files-contents-in-c
*/
char *file_read(char *path) {
FILE *fp;
char *buffer;
long fsize;
fp = fopen(path , "rb");
if (fp == NULL) {
return NULL;
}
fsize = fget_file_size(fp);
if (fsize < 0){
fprintf(stderr, "could not determine lenght of:\n%s\n", path);
return NULL;
}
buffer = (char*)malloc(fsize);
if (buffer == NULL) {
return NULL;
}
if (fread(buffer, 1, fsize, fp) != (size_t)fsize) {
return NULL;
}
if (fclose(fp) == EOF){
return NULL;
}
return buffer;
}
/* Write a null terminated string to file
*
* Return -1 on failure, 0 on success.
*/
int file_write(char *path, char *write_string) {
long len;
FILE *fp;
fp = fopen(path, "wb");
if (fp == NULL) {
return -1;
}
len = strlen(write_string);
/* copy the file into the buffer: */
if (fwrite(write_string, 1, len, fp) != (size_t)len) {
return -1;
}
if (fclose(fp) == EOF) {
return -1;
}
return 0;
}
int main(void) {
char *path = LKMC_TMP_FILE;
char *input = "asdf\nqwer\n";
/* Write entire string to file at once. */
if (file_write(path, input) == -1) {
LKMC_IO_ERROR("file_write", path);
}
/* Read entire file at once to a string. */
{
char *output = file_read(path);
if (output == NULL) {
LKMC_IO_ERROR("file_read", path);
}
assert(strcmp(input, output) == 0);
free(output);
}
/* Get file size. */
{
long size = file_size(path);
if (size == -1) {
LKMC_IO_ERROR("file_size", path);
}
assert((size_t)size == strlen(input));
}
return EXIT_SUCCESS;
}

View File

@@ -1,4 +1,6 @@
/* Loop infinitely. Print an integer whenever a period is reached: /* https://github.com/cirosantilli/linux-kernel-module-cheat#c
*
* Loop infinitely. Print an integer whenever a period is reached:
* *
* .... * ....
* ./infinite_loop [period] * ./infinite_loop [period]