Преглед изворни кода

cmake, code organization, directory for binary can be easily changed and gets created if it does not exist already

Aaro Saila пре 1 година
родитељ
комит
6b787b99ed

+ 2 - 0
crunner/.gitignore

@@ -0,0 +1,2 @@
+build
+.cache

+ 14 - 0
crunner/CMakeLists.txt

@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 3.31)
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+
+project(crunner C)
+
+add_executable(${PROJECT_NAME}
+  src/main.c
+  src/args.c
+  src/file_info.c
+)
+
+target_include_directories(${PROJECT_NAME} PRIVATE
+  src/headers
+)

+ 0 - 72
crunner/crunner.c

@@ -1,72 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define MAX_ARG_LENGTH 1000
-
-#define VERSION "1.0"
-
-// TODO: Check file modification date and only recompile if binary is older.
-
-typedef struct {
-  char full_path[MAX_ARG_LENGTH];
-  char name[MAX_ARG_LENGTH];
-  char exec_name[MAX_ARG_LENGTH];
-  char dest_path[MAX_ARG_LENGTH + 6]; // /tmp/ + exec_name + \0
-} file_info;
-
-void parse_flags(char argv[][MAX_ARG_LENGTH], file_info* fi) {
-  if (strcmp(argv[1], "--version") == 0) {
-    printf("cr version: %s\n", VERSION);
-    exit(0);
-  }
-
-  strncpy(fi->full_path, argv[1], (sizeof(fi->full_path) / sizeof(char)) - 1);
-  const char* delim = "/";
-  char* first_token = strtok(argv[1], delim);
-
-  if (first_token == NULL) {
-    strncpy(fi->name, argv[1], (sizeof(fi->full_path) / sizeof(char)) - 1);
-  } else {
-    char* prev_token = first_token;
-    char* cur_token = first_token;
-    while (cur_token != NULL) {
-      prev_token = cur_token;
-      cur_token = strtok(NULL, delim);
-    }
-
-    strncpy(fi->name, prev_token, (sizeof(fi->full_path) / sizeof(char)) - 1);
-  }
-
-  strncpy(fi->exec_name, fi->name, sizeof(fi->exec_name) / sizeof(char));
-  fi->exec_name[strlen(fi->exec_name) - 2] = '\0';
-  strncpy(fi->dest_path, "/tmp/", (sizeof(fi->dest_path) / sizeof(char)) - 1);
-  strncat(fi->dest_path, fi->exec_name, (sizeof(fi->dest_path) / sizeof(char)) - 1);
-}
-
-int main(int argc, char* argv[]) {
-  if (argc < 2) {
-    printf("ERROR: Path to C file must be specified.\n");
-    return 1;
-  }
-
-  file_info fi;
-  char argv_copy[argc][MAX_ARG_LENGTH];
-  for (int i = 0; i < argc; i++) {
-    strncpy(argv_copy[i], argv[i], MAX_ARG_LENGTH);
-  }
-  parse_flags(argv_copy, &fi);
-
-  const int cmd_max_len = strlen("gcc ") + sizeof(fi.full_path) / sizeof(char) + strlen(" -o ") + sizeof(fi.dest_path) / sizeof(char);
-  char cmd[cmd_max_len];
-  strcpy(cmd, "gcc ");
-  strcat(cmd, fi.full_path);
-  strcat(cmd, " -o ");
-  strcat(cmd, fi.dest_path);
-  strcat(cmd, "\0");
-
-  system(cmd);
-  system(fi.dest_path);
-  
-  return 0;
-}

+ 52 - 0
crunner/src/args.c

@@ -0,0 +1,52 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+#include "crunner_config.h"
+#include "file_info.h"
+#include "util.h"
+
+extern const char* version;
+
+void handle_version(char** argv, int argc) {
+  bool match;
+  for (int i = 0; i < argc; i++) {
+    match = strcmp(argv[i], "--version") == 0 || strcmp(argv[i], "-v") == 0;
+    if (match) {
+      printf("Crunner version: %s\n", version);
+      exit(0);
+    }
+  }
+}
+
+void parse_args(char** argv, int argc, file_info* fi) {
+  handle_version(argv, argc);
+
+  // Get full path to c file
+  strncpy(fi->full_path, argv[1], ARR_SIZE(fi->full_path, char) - 1);
+  const char* delim = "/";
+  char* first_token = strtok(argv[1], delim);
+
+  // Get the name of the c file
+  if (first_token == NULL) {
+    strncpy(fi->name, argv[1], ARR_SIZE(fi->full_path, char) - 1);
+  } else {
+    char* prev_token = first_token;
+    char* cur_token = first_token;
+    while (cur_token != NULL) {
+      prev_token = cur_token;
+      cur_token = strtok(NULL, delim);
+    }
+
+    strncpy(fi->name, prev_token, ARR_SIZE(fi->name, char) - 1);
+  }
+
+  // Get the name and path of the to be compiled binary.
+  strncpy(fi->bin_name, fi->name, ARR_SIZE(fi->bin_name, char));
+  fi->bin_name[strlen(fi->bin_name) - 2] = '\0';
+
+  strncpy(fi->dest_path, CRUNNER_DIR_PATH, ARR_SIZE(fi->dest_path, char) - 1);
+  strncat(fi->dest_path, "/", 1);
+  strncat(fi->dest_path, fi->bin_name, ARR_SIZE(fi->dest_path, char) - 1);
+}

+ 12 - 0
crunner/src/file_info.c

@@ -0,0 +1,12 @@
+#include <stdio.h>
+
+#include "file_info.h"
+
+void print_file_info(file_info* fi) {
+  printf("file_info {\n");
+  printf("  full_path: %s\n", fi->full_path);
+  printf("  name     : %s\n", fi->name);
+  printf("  bin_name : %s\n", fi->bin_name);
+  printf("  dest_path: %s\n", fi->dest_path);
+  printf("}\n");
+}

+ 8 - 0
crunner/src/headers/args.h

@@ -0,0 +1,8 @@
+#ifndef ARGS_H_
+#define ARGS_H_
+
+#include "file_info.h"
+
+void parse_args(char** argv, int argc, file_info* fi);
+
+#endif // ARGS_H_

+ 12 - 0
crunner/src/headers/crunner_config.h

@@ -0,0 +1,12 @@
+#ifndef CRUNNER_CONFIG_H_
+#define CRUNNER_CONFIG_H_
+
+#define EXIT_CODE_SUCCESS 0
+#define EXIT_CODE_ERROR 1
+#define EXIT_CODE_DEBUG 2
+
+#define BUF_SIZE 256
+
+#define CRUNNER_DIR_PATH "/tmp/crunner"
+
+#endif // CRUNNER_CONFIG_H_

+ 15 - 0
crunner/src/headers/file_info.h

@@ -0,0 +1,15 @@
+#ifndef FILE_INFO_H_
+#define FILE_INFO_H_
+
+#include "crunner_config.h"
+
+typedef struct {
+  char full_path[BUF_SIZE];  // Ex. ./foo/bar.c
+  char name[BUF_SIZE];       // Ex. bar.c
+  char bin_name[BUF_SIZE];   // Ex. bar
+  char dest_path[BUF_SIZE];  // Ex. /tmp/bar
+} file_info;
+
+void print_file_info(file_info* fi);
+
+#endif // FILE_INFO_H_

+ 6 - 0
crunner/src/headers/util.h

@@ -0,0 +1,6 @@
+#ifndef UTIL_H_
+#define UTIL_H_
+
+#define ARR_SIZE(arr, type) (sizeof((arr)) / sizeof(type))
+
+#endif // UTIL_H_

+ 50 - 0
crunner/src/main.c

@@ -0,0 +1,50 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include "crunner_config.h"
+#include "file_info.h"
+#include "args.h"
+
+const char* version = "1.0.1";
+
+// TODO: Check file modification date and only recompile if binary is older.
+
+int main(int argc, char* argv[]) {
+  if (argc < 2) {
+    fprintf(stderr, "ERROR: Path to C file must be specified.\n");
+    return EXIT_CODE_ERROR;
+  }
+
+  // Create crunner directory if it does not exist.
+  if (opendir(CRUNNER_DIR_PATH) == NULL) {
+    if (errno == ENOENT) {
+      if (mkdir(CRUNNER_DIR_PATH, 0700) < 0) {
+        fprintf(stderr, "mkdir failed. ERRNO: %d\n", errno);
+        exit(EXIT_CODE_ERROR);
+      }
+    } else {
+      fprintf(stderr, "opendir failed. ERRNO: %d\n", errno);
+      exit(EXIT_CODE_ERROR);
+    }
+  }
+
+  file_info fi;
+  parse_args(argv, argc, &fi);
+
+  const int cmd_max_len = strlen("gcc ") + sizeof(fi.full_path) / sizeof(char) + strlen(" -o ") + sizeof(fi.dest_path) / sizeof(char);
+  char cmd[cmd_max_len];
+  strcpy(cmd, "gcc ");
+  strcat(cmd, fi.full_path);
+  strcat(cmd, " -o ");
+  strcat(cmd, fi.dest_path);
+  strcat(cmd, "\0");
+
+  system(cmd);
+  system(fi.dest_path);
+  
+  return EXIT_CODE_SUCCESS;
+}

+ 11 - 0
crunner/test.c

@@ -0,0 +1,11 @@
+/*
+  This file can be used to test the crunner program. 
+*/
+
+#include <stdio.h>
+
+int main() {
+  printf("Hello from test file.\n");
+
+  return 0;
+}