]> git.seodisparate.com - SimpleArchiver/commitdiff
Impl. parser (TODO Fix invalid free crash) stream_03
authorStephen Seo <seo.disparate@gmail.com>
Thu, 27 Jun 2024 02:57:29 +0000 (11:57 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Thu, 27 Jun 2024 02:57:29 +0000 (11:57 +0900)
During testing, having at least three positional args cause an invalid
free crash. Should be investigated and fixed.

.gitignore
CMakeLists.txt
src/.lvimrc [new file with mode: 0644]
src/main.c
src/parser.c [new file with mode: 0644]
src/parser.h [new file with mode: 0644]

index 36cfdb92183335020e39e2d38fa37d280967caae..deed12c7a706d9321e0341383764b973885dfdee 100644 (file)
@@ -1,2 +1,3 @@
 /build*/
 compile_commands.json
+/.cache/
index 9ea54f8ab464d327f841655220304fe189adcaf8..8230cfedf4c48aa4a5d022dc295ad527f939cf76 100644 (file)
@@ -5,12 +5,13 @@ set(SimpleArchiver_VERSION 1.0)
 
 set(SimpleArchiver_SOURCES
     src/main.c
+    src/parser.c
 )
 
 add_compile_options(
     -Wall -Wextra -Wpedantic -Wno-missing-braces
     $<$<COMPILE_LANGUAGE:CXX>:-Weffc++>
-    $<$<CONFIG:DEBUG>:-O0>
+    $<$<CONFIG:DEBUG>:-Og>
 )
 
 if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
diff --git a/src/.lvimrc b/src/.lvimrc
new file mode 100644 (file)
index 0000000..77ce7d0
--- /dev/null
@@ -0,0 +1 @@
+set expandtab tabstop=2 softtabstop=2 shiftwidth=2
index c1d54f8a95003439beacc60f1e5d8fa39575a7dc..4a0f1dadcaccb9f6eefadcf0381454c2bd381d58 100644 (file)
  *
  * `main.c` is the entry-point of this software/program.
  */
-int main(int argc, char **argv) {
-    return 0;
+
+#include <stdio.h>
+
+#include "parser.h"
+
+int main(int argc, const char **argv) {
+  simple_archiver_print_usage();
+
+  //__attribute__((cleanup(simple_archiver_free_parsed)))
+  SDArchiverParsed parsed = simple_archiver_create_parsed();
+
+  simple_archiver_parse_args(argc, argv, &parsed);
+
+  puts("freeing");
+  simple_archiver_free_parsed(&parsed);
+  puts("end");
+  return 0;
 }
diff --git a/src/parser.c b/src/parser.c
new file mode 100644 (file)
index 0000000..28883d2
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2024 Stephen Seo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * `parser.c` is the source file for parsing args.
+ */
+
+#include "parser.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void simple_archiver_print_usage(void) {
+  puts("Usage flags:");
+  puts("-c : create archive file");
+  puts("-x : extract archive file");
+  puts("-f <filename> : filename to work on");
+  puts("--compressor <full_compress_cmd> : requires --decompressor");
+  puts("--decompressor <full_decompress_cmd> : requires --compressor");
+  puts("If creating archive file, remaining args specify files to archive.");
+  puts("If extracting archive file, remaining args specify files to extract.");
+}
+
+SDArchiverParsed simple_archiver_create_parsed(void) {
+  SDArchiverParsed parsed;
+
+  parsed.flags = 0;
+  parsed.filename = NULL;
+  parsed.compressor = NULL;
+  parsed.decompressor = NULL;
+  parsed.working_files = NULL;
+
+  return parsed;
+}
+
+int simple_archiver_parse_args(int argc, const char **argv,
+                               SDArchiverParsed *out) {
+  if (out->filename) {
+    free(out->filename);
+    out->filename = NULL;
+  }
+  if (out->compressor) {
+    free(out->compressor);
+    out->compressor = NULL;
+  }
+  if (out->decompressor) {
+    free(out->decompressor);
+    out->decompressor = NULL;
+  }
+
+  // Skip program name as it is the first arg usually.
+  --argc;
+  ++argv;
+
+  int is_remaining_args = 0;
+
+  while (argc > 0) {
+    if (!is_remaining_args) {
+      if (strcmp(argv[0], "-c") == 0) {
+        // unset first bit.
+        out->flags &= 0xFFFFFFFE;
+      } else if (strcmp(argv[0], "-x") == 0) {
+        // set first bit.
+        out->flags |= 0x1;
+      } else if (strcmp(argv[0], "-f") == 0 && argc > 1) {
+        int size = strlen(argv[1]) + 1;
+        out->filename = malloc(size);
+        strncpy(out->filename, argv[1], size);
+        --argc;
+        ++argv;
+      } else if (strcmp(argv[0], "--compressor") == 0 && argc > 1) {
+        int size = strlen(argv[1]) + 1;
+        out->compressor = malloc(size);
+        strncpy(out->compressor, argv[1], size);
+        --argc;
+        ++argv;
+      } else if (strcmp(argv[0], "--decompressor") == 0 && argc > 1) {
+        int size = strlen(argv[1]) + 1;
+        out->decompressor = malloc(size);
+        strncpy(out->decompressor, argv[1], size);
+        --argc;
+        ++argv;
+      } else if (argv[0][0] != '-') {
+        is_remaining_args = 1;
+        continue;
+      }
+    } else {
+      if (out->working_files == NULL) {
+        puts("first addition to working_files");
+        out->working_files = malloc(sizeof(char *) * 2);
+        int arg_length = strlen(argv[0]) + 1;
+        out->working_files[0] = malloc(arg_length);
+        strncpy(out->working_files[0], argv[0], arg_length);
+        out->working_files[1] = NULL;
+      } else {
+        puts("later addition to working_files");
+        int working_size = 1;
+        char **ptr = out->working_files;
+        while (ptr && *ptr) {
+          ++working_size;
+          ++ptr;
+        }
+        printf("working_size is %u\n", working_size);
+
+        // TODO verify this is necessary, using different variables.
+        ptr = out->working_files;
+        out->working_files = realloc(ptr, working_size + 1);
+
+        // Set new actual last element to NULL.
+        out->working_files[working_size] = NULL;
+        int size = strlen(argv[0]) + 1;
+        // Set last element to the arg.
+        out->working_files[working_size - 1] = malloc(size);
+        strncpy(out->working_files[working_size - 1], argv[0], size);
+      }
+    }
+
+    --argc;
+    ++argv;
+  }
+
+  return 0;
+}
+
+void simple_archiver_free_parsed(SDArchiverParsed *parsed) {
+  parsed->flags = 0;
+  if (parsed->filename) {
+    free(parsed->filename);
+    parsed->filename = NULL;
+  }
+  if (parsed->compressor) {
+    free(parsed->compressor);
+    parsed->compressor = NULL;
+  }
+  if (parsed->decompressor) {
+    free(parsed->decompressor);
+    parsed->decompressor = NULL;
+  }
+  if (parsed->working_files) {
+    char **ptr = parsed->working_files;
+    unsigned int idx = 0;
+    puts("freeing working_files strings...");
+    while (ptr[idx]) {
+      printf("Freeing at idx %u\n", idx);
+      free(ptr[idx]);
+      ++idx;
+    }
+    puts("freeing string array...");
+    free(parsed->working_files);
+    parsed->working_files = NULL;
+
+    puts("free_parsed is done.");
+  }
+}
diff --git a/src/parser.h b/src/parser.h
new file mode 100644 (file)
index 0000000..3f646a4
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2024 Stephen Seo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * `parser.h` is the header for parsing args.
+ */
+
+#ifndef SEODISPARATE_COM_SIMPLE_ARCHIVER_PARSER_H_
+#define SEODISPARATE_COM_SIMPLE_ARCHIVER_PARSER_H_
+
+typedef struct SDArchiverParsed {
+  /// Each bit is a flag.
+  /// 0b0 - is creating.
+  /// 0b1 - is extracting.
+  unsigned int flags;
+  /// Null-terminated string.
+  char *filename;
+  /// Null-terminated string.
+  char *compressor;
+  /// Null-terminated string.
+  char *decompressor;
+  /// Null-terminated strings in array of strings.
+  /// Last entry should be NULL.
+  /// Not used when extracting.
+  char **working_files;
+} SDArchiverParsed;
+
+extern void simple_archiver_print_usage(void);
+
+extern SDArchiverParsed simple_archiver_create_parsed(void);
+
+/// Expects the user to pass a pointer to an SDArchiverParsed.
+/// This means the user should have a SDArchiverParsed variable
+/// and it should be passed with e.g. "&var".
+extern int simple_archiver_parse_args(int argc, const char **argv,
+                                      SDArchiverParsed *out);
+
+extern void simple_archiver_free_parsed(SDArchiverParsed *parsed);
+
+#endif