commit 73e50f5a351a6bb185473e1a26c62ea823db5bdd
parent db121368383fa3e47ec60eaf126218f15c006c83
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 4 Mar 2026 17:05:05 +0100
Start implementation of sln-get utility
It queries the data of a tree and prints it on the standard output.
Currently, the default behavior is to print general information about
the tree, such as the number of nodes. Enable -m option displays instead
the tree root mesh
Diffstat:
| M | Makefile | | | 7 | +++++-- |
| A | src/sln_get.c | | | 257 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
2 files changed, 262 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
@@ -82,7 +82,7 @@ libsln.o: $(OBJ)
################################################################################
# Utils
################################################################################
-UTIL_SRC = src/sln_build.c
+UTIL_SRC = src/sln_build.c src/sln_get.c
UTIL_OBJ = $(UTIL_SRC:.c=.o)
UTIL_DEP = $(UTIL_SRC:.c=.d)
@@ -97,11 +97,14 @@ LDFLAGS_UTIL = $(LDFLAGS_EXE) $(LIBS_UTIL)
utils: library $(UTIL_DEP)
@$(MAKE) -fMakefile \
$$(for i in $(UTIL_DEP); do printf -- '-f%s\n' "$${i}"; done) \
- sln-build
+ sln-build sln-get
sln-build: config.mk sln-local.pc src/sln_build.o $(LIBNAME)
$(CC) $(CFLAGS_UTIL) -o $@ src/sln_build.o $(LDFLAGS_UTIL)
+sln-get: config.mk sln-local.pc src/sln_get.o $(LIBNAME)
+ $(CC) $(CFLAGS_UTIL) -o $@ src/sln_get.o $(LDFLAGS_UTIL)
+
$(UTIL_DEP): config.mk sln-local.pc
@$(CC) $(CFLAGS_UTIL) -MM -MT "$(@:.d=.o) $@" $(@:.d=.c) -MF $@
diff --git a/src/sln_get.c b/src/sln_get.c
@@ -0,0 +1,257 @@
+/* Copyright (C) 2022, 2026 |Méso|Star> (contact@meso-star.com)
+ * Copyright (C) 2026 Université de Lorraine
+ * Copyright (C) 2022 Centre National de la Recherche Scientifique
+ * Copyright (C) 2022 Université Paul Sabatier
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#define _POSIX_C_SOURCE 200112L /* getopt */
+
+#include "sln.h"
+
+#include <rsys/mem_allocator.h>
+
+#include <unistd.h>
+
+/* Draft of the command sln-get # Default print information
+ [-lr] # go to left/right
+ [-L<n>] [-R<n>] # go to n times left/right
+ [-m] # output mesh
+ [-v] # verbosity
+ [-h] # short help
+ [tree] */
+
+enum output_type {
+ OUTPUT_DESCRIPTOR,
+ OUTPUT_MESH,
+ OUTPUT_COUNT__
+};
+
+struct args {
+ const char* tree; /* NULL <=> read from standard input */
+
+ enum output_type output_type;
+
+ /* Miscellaneous */
+ int quit;
+ int verbose;
+};
+#define ARGS_DEFAULT__ {NULL, OUTPUT_DESCRIPTOR, 0, 0}
+static const struct args ARGS_DEFAULT = ARGS_DEFAULT__;
+
+struct cmd {
+ struct args args;
+
+ struct sln_device* sln;
+ struct sln_tree* tree;
+
+ struct shtr* shtr;
+};
+#define CMD_NULL__ {0}
+static const struct cmd CMD_NULL = CMD_NULL__;
+
+/*******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+static void
+usage(FILE* stream)
+{
+ fprintf(stream, "usage: sln-get [-hmv] [tree]\n");
+}
+
+static res_T
+args_init(struct args* args, int argc, char** argv)
+{
+ int opt = 0;
+ res_T res = RES_OK;
+
+ ASSERT(args);
+
+ *args = ARGS_DEFAULT;
+
+ while((opt = getopt(argc, argv, "hmv")) != -1) {
+ switch(opt) {
+ case 'h':
+ usage(stdout);
+ args->quit = 1;
+ goto exit;
+ case 'm': args->output_type = OUTPUT_MESH; break;
+ case 'v': args->verbose += (args->verbose < 3); break;
+ default: res = RES_BAD_ARG; break;
+ }
+ if(res != RES_OK) {
+ if(optarg) {
+ fprintf(stderr, "%s: invalid option argument '%s' -- '%c'\n",
+ argv[0], optarg, opt);
+ }
+ goto error;
+ }
+ }
+
+ if(optind < argc) args->tree = argv[optind];
+
+exit:
+ return res;
+error:
+ usage(stderr);
+ goto exit;
+}
+
+static void
+cmd_release(struct cmd* cmd)
+{
+ ASSERT(cmd);
+ if(cmd->sln) SLN(device_ref_put(cmd->sln));
+ if(cmd->tree) SLN(tree_ref_put(cmd->tree));
+ if(cmd->shtr) SHTR(ref_put(cmd->shtr));
+}
+
+static res_T
+cmd_init(struct cmd* cmd, const struct args* args)
+{
+ struct sln_device_create_args sln_args = SLN_DEVICE_CREATE_ARGS_DEFAULT;
+ struct sln_tree_read_args tree_args = SLN_TREE_READ_ARGS_NULL;
+ struct shtr_create_args shtr_args = SHTR_CREATE_ARGS_DEFAULT;
+ res_T res = RES_OK;
+
+ ASSERT(cmd && args);
+
+ *cmd = CMD_NULL;
+
+ shtr_args.verbose = args->verbose;
+ res = shtr_create(&shtr_args, &cmd->shtr);
+ if(res != RES_OK) goto error;
+
+ sln_args.verbose = args->verbose;
+ res = sln_device_create(&sln_args, &cmd->sln);
+ if(res != RES_OK) goto error;
+
+ tree_args.shtr = cmd->shtr;
+ if(args->tree) {
+ tree_args.file = NULL;
+ tree_args.filename = args->tree;
+ } else {
+ tree_args.file = stdin;
+ tree_args.filename = "stdin";
+ }
+ res = sln_tree_read(cmd->sln, &tree_args, &cmd->tree);
+ if(res != RES_OK) goto error;
+
+ cmd->args = *args;
+
+exit:
+ return res;
+error:
+ cmd_release(cmd);
+ *cmd = CMD_NULL;
+ goto exit;
+}
+
+static res_T
+print_descriptor(const struct cmd* cmd)
+{
+ struct sln_tree_desc desc = SLN_TREE_DESC_NULL;
+ res_T res = RES_OK;
+ ASSERT(cmd);
+
+ res = sln_tree_get_desc(cmd->tree, &desc);
+ if(res != RES_OK) goto error;
+
+ printf("#nodes: %lu\n", (unsigned long)desc.nnodes);
+ printf("#vertices: %lu\n", (unsigned long)desc.nvertices);
+ printf("type: %s\n", sln_mesh_type_cstr(desc.mesh_type));
+ printf("decimation error: %.4e\n", desc.mesh_decimation_err);
+ printf("line profile: %s\n", sln_line_profile_cstr(desc.line_profile));
+ printf("#lines per leaf: %lu\n", (unsigned long)desc.max_nlines_per_leaf);
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+print_mesh(const struct cmd* cmd)
+{
+ struct sln_mesh mesh = SLN_MESH_NULL;
+ const struct sln_node* node = NULL;
+ size_t i = 0;
+ res_T res = RES_OK;
+ ASSERT(cmd);
+
+ node = sln_tree_get_root(cmd->tree);
+ if(node == NULL) goto exit; /* Tree is empty */
+
+ res = sln_node_get_mesh(cmd->tree, node, &mesh);
+ if(res != RES_OK) goto error;
+
+ FOR_EACH(i, 0, mesh.nvertices) {
+ printf("%g %g\n",
+ mesh.vertices[i].wavenumber,
+ mesh.vertices[i].ka);
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+cmd_run(const struct cmd* cmd)
+{
+ res_T res = RES_OK;
+
+ switch(cmd->args.output_type) {
+ case OUTPUT_DESCRIPTOR:
+ res = print_descriptor(cmd);
+ break;
+ case OUTPUT_MESH:
+ res = print_mesh(cmd);
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
+ if(res != RES_OK) goto error;
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+/*******************************************************************************
+ * The program
+ ******************************************************************************/
+int
+main(int argc, char** argv)
+{
+ struct args args = ARGS_DEFAULT;
+ struct cmd cmd = CMD_NULL;
+ int err = 0;
+ res_T res = RES_OK;
+
+ if((res = args_init(&args, argc, argv)) != RES_OK) goto error;
+ if(args.quit) goto exit;
+
+ if((res = cmd_init(&cmd, &args)) != RES_OK) goto error;
+ if((res = cmd_run(&cmd)) != RES_OK) goto error;
+
+exit:
+ cmd_release(&cmd);
+ CHK(mem_allocated_size() == 0);
+ return err;
+error:
+ err = 1;
+ goto exit;
+}