Compare commits

...

4 Commits

Author SHA1 Message Date
Miguel M 28058cdac3 misc things: vscode configs and test data 2023-04-21 19:39:46 +01:00
Miguel M 709bc6f8c0 Can consume input 2023-04-21 19:39:21 +01:00
Miguel M 6e1af9c863 Added out-of-date condition to link recipe 2023-04-21 19:29:31 +01:00
Miguel M c741706a11 Fixes to make.py crossplatform and gcc flag-order compliant 2023-04-21 17:54:43 +01:00
6 changed files with 123 additions and 35 deletions

33
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,33 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/main.exe",
"args": ["<", "${workspaceFolder}/data/test_mat.txt"],
"stopAtEntry": true,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"preLaunchTask": "compile",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
},
]
}
]
}

3
.vscode/piped_run.sh vendored Executable file
View File

@ -0,0 +1,3 @@
#!/bin/bash
path=$(realpath “${BASH_SOURCE:-$0})
cat "$path/../data/test_mat.txt" | "$path/../main.exe"

10
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,10 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "compile",
"command": "python make.py compile",
"type": "shell"
}
]
}

View File

@ -1,4 +1,4 @@
3
1 1 -1
555 0.9 +2
555 0.9 2
-55 2 1555

28
make.py
View File

@ -6,8 +6,9 @@ from glob import glob
from sane import *
COMPILER = 'gcc'
COMPILE_FLAGS = ['-g',
'--std=c99',
COMPILE_FLAGS = ['-std=c99',
'-g',
'-O0',
'-Wall',
'-Werror',
'-fopenmp']
@ -19,7 +20,7 @@ EXE_NAME = 'main.exe'
ROOT = os.path.dirname(os.path.realpath(__file__))
if 'RELEASE' in os.environ:
COMPILE_FLAGS.append('-O2')
COMPILE_FLAGS[COMPILE_FLAGS.index('-O0')] = '-O2'
def as_object(source_path):
"""Takes a source path and returns the path to the corresponding compiled object."""
@ -43,18 +44,24 @@ def make_object_recipe(source_path):
conditions=[condition],
hooks=['obj_compile'])
def compile_obj():
sp.run([COMPILER, *COMPILE_FLAGS,
'-c', source_path,
'-o', object_path],
shell=True)
sp.run([COMPILER, '-c', *COMPILE_FLAGS,
'-o', object_path,
source_path])
source_files = glob('**/*.c', recursive=True)
source_files = [os.path.realpath(path)
for path in glob('**/*.c', recursive=True)]
for source_file in source_files:
make_object_recipe(source_file)
def exe_not_exists():
return not os.path.exists(EXE_NAME)
def old_exe():
object_files = [
os.path.realpath(path)
for path in glob('**/*.obj', recursive=True)]
return Sane.file_condition(object_files, [EXE_NAME])()
@recipe(hook_deps=['obj_compile'],
info='Compile the source files.')
@ -62,13 +69,12 @@ def compile():
pass
@recipe(recipe_deps=[compile],
conditions=[exe_not_exists],
conditions=[exe_not_exists, old_exe],
info='Links the main executable.')
def link():
obj_files = glob(os.path.join(OBJ_DIR, '**', '*.obj').replace('\\', '/'),
recursive=True)
sp.run([COMPILER, *obj_files, *LINK_FLAGS, '-o', EXE_NAME],
shell=True)
sp.run([COMPILER, *LINK_FLAGS, '-o', EXE_NAME, *obj_files])
@recipe(info='Removes all compiled objects.')
def clean():

View File

@ -19,10 +19,12 @@ typedef struct
// The data is organized as <string length> <chars...>, such that the `char`s
// are casted to `int_fast32_t` to allow for the mixed types.
grid_data_t *data_head;
// Array of pointers to the start of each entry string.
grid_data_t **entries_head;
// Number of elements.
// Array of indices in `data_head` of the start of each string.
size_t *entries_head;
// Number of bytes.
size_t data_len;
// Number of entries.
size_t entries_len;
} grid_t;
// Parameters for `increase_input_buffers`.
@ -30,15 +32,54 @@ typedef struct
{
size_t data_cap;
grid_data_t *data_head;
grid_data_t **entries_head;
size_t *entries_head;
} increase_input_buffers_params_t;
// Prints a debug view of a `grid_t` to standard output.
void debug_print_grid(grid_t *grid)
{
printf("Grid { row_len: %zu, data_head: %p, entries_head: %p, data_len: %zu }",
(grid->row_len), (void*)(grid->data_head), (void*)(grid->entries_head),
(grid->data_len));
printf("Grid ( row_len: %zu, data_head: %p, entries_head: %p, data_len: %zu, entries_len: %zu ) { ",
(grid->row_len), (void *)(grid->data_head), (void *)(grid->entries_head),
(grid->data_len), (grid->entries_len));
printf("data: [");
size_t str_counter = 0;
for (size_t i = 0; i < grid->data_len; i++)
{
if (i > 0)
{
printf(", ");
}
else
{
printf(" ");
}
_Bool is_char = 1;
if (grid->entries_len > 0 && str_counter < grid->entries_len) {
if ((grid->entries_head)[str_counter] == i) {
is_char = 0;
str_counter += 1;
}
}
if (is_char) {
printf("'%c'", (char)((grid->data_head)[i]));
} else {
printf("%" PRIgridDATA, (grid->data_head)[i]);
}
}
printf("], entries: [");
for (size_t i = 0; i < grid->entries_len; i++)
{
if (i > 0)
{
printf(", ");
}
else
{
printf(" ");
}
printf("%zu", (grid->entries_head)[i]);
}
printf("] }\n");
}
// Increases the data buffers used in `parse_input`.
@ -84,13 +125,13 @@ grid_t parse_input(void)
size_t data_cap = 32; // Initial value is arbitrary.
size_t data_len = 0; // Number of characters written so far.
size_t str_len = 0; // Number of strings written so far.
size_t entries_len = 0; // Number of strings written so far.
grid_data_t *data_head = malloc(data_cap * sizeof(grid_data_t));
size_t *entries_head = malloc(data_cap * sizeof(size_t));
_Bool spaces = 1;
char scanned;
while ((scanned = scanf("%c", &scanned)) != EOF)
while (scanf("%c", &scanned) != EOF)
{
if (isspace(scanned))
{
@ -99,26 +140,21 @@ grid_t parse_input(void)
else
{
// A little input sanitization.
if (scanned == '+')
{
// We can ignore plus signs, assuming we have (\+|\-)?\d+(\.\d+)?(E\d+)?
continue;
}
if (!(isdigit(scanned) || (scanned == '-') || (scanned == '.')))
{
printf(
"Foreign character %c found when processing input, aborting.",
scanned);
"Foreign character %c (%x) found when processing input, aborting.",
scanned, scanned);
exit(EXIT_FAILURE);
}
if (spaces)
{
// New row
str_len += 1;
// New string
entries_len += 1;
data_len += 1; // The byte for the string length
// data_head[data_len] is already correctly initialized to 0.
entries_head[str_len - 1] = data_len - 1;
entries_head[entries_len - 1] = data_len - 1;
}
spaces = 0;
@ -143,18 +179,17 @@ grid_t parse_input(void)
data_head[data_len - 1] = scanned;
// Increase the length of current string
grid_data_t *cur_len = entries_head[str_len - 1];
*cur_len += 1;
data_head[entries_head[entries_len - 1]] += 1;
}
} // End of scan loop
// Input sanitization: confirm that the number of entries read is a multiple
// of the number of entries in a row.
if (!((str_len % row_len) == 0))
if (!((entries_len % row_len) == 0))
{
printf("Number of entries is not consistent with provided row length. "
"Got row length of %zu, and read %zu entries. Aborting.",
row_len, str_len);
row_len, entries_len);
// No need to free the buffers.
exit(EXIT_FAILURE);
}
@ -164,6 +199,7 @@ grid_t parse_input(void)
.data_head = data_head,
.entries_head = entries_head,
.data_len = data_len,
.entries_len = entries_len,
};
return grid;