Compare commits
4 Commits
fe3d00a5f5
...
28058cdac3
Author | SHA1 | Date |
---|---|---|
Miguel M | 28058cdac3 | |
Miguel M | 709bc6f8c0 | |
Miguel M | 6e1af9c863 | |
Miguel M | c741706a11 |
|
@ -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
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
path=$(realpath “${BASH_SOURCE:-$0}”)
|
||||
cat "$path/../data/test_mat.txt" | "$path/../main.exe"
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "compile",
|
||||
"command": "python make.py compile",
|
||||
"type": "shell"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
3
|
||||
1 1 -1
|
||||
555 0.9 +2
|
||||
555 0.9 2
|
||||
-55 2 1555
|
28
make.py
28
make.py
|
@ -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():
|
||||
|
|
82
src/main.c
82
src/main.c
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue