Browse Source

Merge pull request #8 from tsoding/logging

Refactoring for 0.1.0
Alexey Kutepov 4 years ago
parent
commit
cc4d873251
8 changed files with 195 additions and 41 deletions
  1. 22 0
      ChangeLog.md
  2. 4 0
      README.md
  3. 2 1
      examples/.gitignore
  4. 4 5
      examples/foreach.c
  5. 11 0
      examples/logging.c
  6. 3 4
      examples/string.c
  7. 3 1
      nobuild.c
  8. 146 30
      nobuild.h

+ 22 - 0
ChangeLog.md

@@ -0,0 +1,22 @@
+[semver](https://semver.org/) is implied.
+
+# 0.1.0-dev
+
+*Not Released Yet*
+
+- Introduced logging functions `INFO(fmt, ...)`, `WARN(fmt, ...)`, `ERRO(fmt, ...)`.
+- Introduced API conventions. Functions that start with `nobuild__` (double underscore) are private to the library and should not be relied upon. They can be changed in any release without a warning.
+
+## Deprecations
+
+All the deprecated functions and macros will be removed in the next major release.
+
+- `remove_ext(path)` is deprecated. Use `NOEXT(path)` instead.
+- `CONCAT_SEP(sep, ...)` is deprecated. Use `JOIN(sep, ...)` instead.
+- `concat_sep_impl(sep, ...)` is deprecated. Use `JOIN(sep, ...)` instead.
+
+# 0.0.1 — First Official Release
+
+*2021-01-27*
+
+- Implemented enough functionality to build https://github.com/tsoding/bm

+ 4 - 0
README.md

@@ -25,3 +25,7 @@ Keep in mind that [nobuild.h](./nobuild.h) is an [stb-style](https://github.com/
    - `$ cc nobuild.c -o nobuild` on POSIX systems
    - `$ cl.exe nobuild.c` on Windows with MSVC
 4. Run the build: `$ ./nobuild`
+
+## API Conventions
+
+- Functions from [nobuild.h](./nobuild.h) that start with `nobuild__` (double underscore) are private to the library and should not be relied upon. They can be changed in any release without a warning.

+ 2 - 1
examples/.gitignore

@@ -1,2 +1,3 @@
 string
-foreach
+foreach
+logging

+ 4 - 5
examples/foreach.c

@@ -6,7 +6,7 @@ void foreach_vargs(int ignore, ...)
     va_list args;
 
     FOREACH_VARGS(ignore, arg, args, {
-        printf("    %s\n", arg);
+        INFO("    %s", arg);
     });
 }
 
@@ -17,26 +17,25 @@ void foreach_array(void)
     };
 
     FOREACH_ARRAY(const char *, item, array, {
-        printf("    %s\n", item);
+        INFO("    %s", item);
     });
 }
 
 void foreach_file_in_dir(const char *dir_path)
 {
     FOREACH_FILE_IN_DIR(file, dir_path, {
-            printf("    %s\n", file);
+            INFO("    %s", file);
     });
 }
 
 #define DEMO(expr)                              \
     do {                                        \
-        printf(#expr"\n");                      \
+        INFO(#expr);                            \
         expr;                                   \
     } while(0)
 
 int main(int argc, char *argv[])
 {
-    printf("=== Foreach Macro Example ===\n");
     DEMO(foreach_vargs(69, "foo", "bar", "baz", NULL));
     DEMO(foreach_array());
     DEMO(foreach_file_in_dir("."));

+ 11 - 0
examples/logging.c

@@ -0,0 +1,11 @@
+#define NOBUILD_IMPLEMENTATION
+#include "../nobuild.h"
+
+int main(int argc, char *argv[])
+{
+    INFO("Informational Message");
+    WARN("Warning Message");
+    ERRO("Error Message");
+
+    return 0;
+}

+ 3 - 4
examples/string.c

@@ -2,14 +2,13 @@
 #include "../nobuild.h"
 
 #define DEMO(expr)                              \
-    printf(#expr " == \"%s\"\n", expr)
+    INFO(#expr " == \"%s\"", expr)
 
 int main(int argc, char *argv[])
 {
-    printf("=== String Manipulation Example ===\n");
     DEMO(CONCAT("foo", "bar", "baz"));
     DEMO(PATH("foo", "bar", "baz"));
-    DEMO(CONCAT_SEP("++", "foo", "bar", "baz"));
-    DEMO(remove_ext("main.c"));
+    DEMO(JOIN("++", "foo", "bar", "baz"));
+    DEMO(NOEXT("main.c"));
     return 0;
 }

+ 3 - 1
nobuild.c

@@ -3,7 +3,9 @@
 
 void check_example(const char *example)
 {
-    const char *example_path = PATH("examples", remove_ext(example));
+    const char *example_path = PATH("examples", NOEXT(example));
+
+    INFO("===== %s =====", NOEXT(example));
 
 #ifdef _WIN32
     CMD("cl.exe", "/Fe.\\examples\\", PATH("examples", example));

+ 146 - 30
nobuild.h

@@ -21,15 +21,11 @@
 //
 // ============================================================
 //
-// nobuild — 0.0.1 — Header only library for writing build recipes in C.
+// nobuild — 0.0.1-dev — Header only library for writing build recipes in C.
 //
 // https://github.com/tsoding/nobuild
 //
 // ============================================================
-//
-// ChangeLog (https://semver.org/ is implied)
-//
-//    0.0.1 First Official Release
 
 #ifndef NOBUILD_H_
 #define NOBUILD_H_
@@ -154,12 +150,13 @@
 // TODO(#5): there is no way to redirect the output of CMD to a file
 #define CMD(...)                                                \
     do {                                                        \
-        printf("[INFO] %s\n", CONCAT_SEP(" ", __VA_ARGS__));    \
+        INFO(JOIN(" ", __VA_ARGS__));                           \
         cmd_impl(69, __VA_ARGS__, NULL);                        \
     } while(0)
 
 const char *concat_impl(int ignore, ...);
 const char *concat_sep_impl(const char *sep, ...);
+const char *build__join(const char *sep, ...);
 void mkdirs_impl(int ignore, ...);
 void cmd_impl(int ignore, ...);
 void nobuild_exec(const char **argv);
@@ -167,10 +164,18 @@ const char *remove_ext(const char *path);
 char *shift(int *argc, char ***argv);
 
 #define CONCAT(...) concat_impl(69, __VA_ARGS__, NULL)
-#define CONCAT_SEP(sep, ...) concat_sep_impl(sep, __VA_ARGS__, NULL)
-#define PATH(...) CONCAT_SEP(PATH_SEP, __VA_ARGS__)
+#define CONCAT_SEP(sep, ...) build__deprecated_concat_sep(sep, __VA_ARGS__, NULL)
+#define JOIN(sep, ...) build__join(sep, __VA_ARGS__, NULL)
+#define PATH(...) JOIN(PATH_SEP, __VA_ARGS__)
 #define MKDIRS(...) mkdirs_impl(69, __VA_ARGS__, NULL)
+#define NOEXT(path) nobuild__remove_ext(path)
 
+void nobuild_log(FILE *stream, const char *tag, const char *fmt, ...);
+void nobuild_vlog(FILE *stream, const char *tag, const char *fmt, va_list args);
+
+void INFO(const char *fmt, ...);
+void WARN(const char *fmt, ...);
+void ERRO(const char *fmt, ...);
 #endif  // NOBUILD_H_
 
 #ifdef NOBUILD_IMPLEMENTATION
@@ -254,8 +259,84 @@ char *shift(int *argc, char ***argv);
 // minirent.h IMPLEMENTATION END ////////////////////////////////////////
 #endif // _WIN32
 
+const char *build__join(const char *sep, ...)
+{
+    const size_t sep_len = strlen(sep);
+    size_t length = 0;
+    size_t seps_count = 0;
+
+    va_list args;
+
+    FOREACH_VARGS(sep, arg, args, {
+        length += strlen(arg);
+        seps_count += 1;
+    });
+    assert(length > 0);
+
+    seps_count -= 1;
+
+    char *result = malloc(length + seps_count * sep_len + 1);
+
+    length = 0;
+    FOREACH_VARGS(sep, arg, args, {
+        size_t n = strlen(arg);
+        memcpy(result + length, arg, n);
+        length += n;
+
+        if (seps_count > 0) {
+            memcpy(result + length, sep, sep_len);
+            length += sep_len;
+            seps_count -= 1;
+        }
+    });
+
+    result[length] = '\0';
+
+    return result;
+}
+
+const char *build__deprecated_concat_sep(const char *sep, ...)
+{
+    WARN("DEPRECATED: Please don't use `CONCAT_SEP(sep, ...)`. Please use JOIN(sep, ...) instead. `CONCAT_SEP(sep, ...)` will be removed in the next major release.");
+
+    const size_t sep_len = strlen(sep);
+    size_t length = 0;
+    size_t seps_count = 0;
+
+    va_list args;
+
+    FOREACH_VARGS(sep, arg, args, {
+        length += strlen(arg);
+        seps_count += 1;
+    });
+    assert(length > 0);
+
+    seps_count -= 1;
+
+    char *result = malloc(length + seps_count * sep_len + 1);
+
+    length = 0;
+    FOREACH_VARGS(sep, arg, args, {
+        size_t n = strlen(arg);
+        memcpy(result + length, arg, n);
+        length += n;
+
+        if (seps_count > 0) {
+            memcpy(result + length, sep, sep_len);
+            length += sep_len;
+            seps_count -= 1;
+        }
+    });
+
+    result[length] = '\0';
+
+    return result;
+}
+
 const char *concat_sep_impl(const char *sep, ...)
 {
+    WARN("DEPRECATED: Please don't use `concat_sep_impl(sep, ...)`. Please use JOIN(sep, ...) instead. `concat_sep_impl(sep, ...)` will be removed in the next major release.");
+
     const size_t sep_len = strlen(sep);
     size_t length = 0;
     size_t seps_count = 0;
@@ -321,14 +402,12 @@ void mkdirs_impl(int ignore, ...)
 
         result[length] = '\0';
 
-        printf("[INFO] mkdir %s\n", result);
+        INFO("mkdir %s", result);
         if (mkdir(result, 0755) < 0) {
             if (errno == EEXIST) {
-                fprintf(stderr, "[WARN] directory %s already exists\n",
-                        result);
+                WARN("directory %s already exists", result);
             } else {
-                fprintf(stderr, "[ERROR] could not create directory %s: %s\n",
-                        result, strerror(errno));
+                ERRO("could not create directory %s: %s", result, strerror(errno));
                 exit(1);
             }
         }
@@ -359,36 +438,29 @@ const char *concat_impl(int ignore, ...)
     return result;
 }
 
-
-
-
 void nobuild_exec(const char **argv)
 {
 #ifdef _WIN32
     intptr_t status = _spawnvp(_P_WAIT, argv[0], (char * const*) argv);
     if (status < 0) {
-        fprintf(stderr, "[ERROR] could not start child process: %s\n",
-                strerror(errno));
+        ERRO("could not start child process: %s", strerror(errno));
         exit(1);
     }
 
     if (status > 0) {
-        fprintf(stderr, "[ERROR] command exited with exit code %d\n",
-                status);
+        ERRO("command exited with exit code %d", status);
         exit(1);
     }
 #else
     pid_t cpid = fork();
     if (cpid == -1) {
-        fprintf(stderr, "[ERROR] could not fork a child process: %s\n",
-                strerror(errno));
+        ERRO("could not fork a child process: %s", strerror(errno));
         exit(1);
     }
 
     if (cpid == 0) {
         if (execvp(argv[0], (char * const*) argv) < 0) {
-            fprintf(stderr, "[ERROR] could not execute child process: %s\n",
-                    strerror(errno));
+            ERRO("could not execute child process: %s", strerror(errno));
             exit(1);
         }
     } else {
@@ -399,17 +471,16 @@ void nobuild_exec(const char **argv)
             if (WIFEXITED(wstatus)) {
                 int exit_status = WEXITSTATUS(wstatus);
                 if (exit_status != 0) {
-                    fprintf(stderr, "[ERROR] command exited with exit code %d\n", exit_status);
-                    exit(-1);
+                    ERRO("command exited with exit code %d", exit_status);
+                    exit(1);
                 }
 
                 break;
             }
 
             if (WIFSIGNALED(wstatus)) {
-                fprintf(stderr, "[ERROR] command process was terminated by signal %d\n",
-                        WTERMSIG(wstatus));
-                exit(-1);
+                ERRO("command process was terminated by signal %d", WTERMSIG(wstatus));
+                exit(1);
             }
         }
     }
@@ -438,7 +509,7 @@ void cmd_impl(int ignore, ...)
     nobuild_exec(argv);
 }
 
-const char *remove_ext(const char *path)
+const char *nobuild__remove_ext(const char *path)
 {
     size_t n = strlen(path);
     while (n > 0 && path[n - 1] != '.') {
@@ -456,6 +527,12 @@ const char *remove_ext(const char *path)
     }
 }
 
+const char *remove_ext(const char *path)
+{
+    WARN("DEPRECATED: Please use `NOEXT(path)` instead of `remove_ext(path)`. `remove_ext(path)` will be removed in the next major release.");
+    nobuild__remove_ext(path);
+}
+
 char *shift(int *argc, char ***argv)
 {
     assert(*argc > 0);
@@ -465,4 +542,43 @@ char *shift(int *argc, char ***argv)
     return result;
 }
 
+void nobuild_log(FILE *stream, const char *tag, const char *fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+    nobuild_vlog(stream, tag, fmt, args);
+    va_end(args);
+}
+
+void nobuild_vlog(FILE *stream, const char *tag, const char *fmt, va_list args)
+{
+    fprintf(stream, "[%s] ", tag);
+    vfprintf(stream, fmt, args);
+    fprintf(stream, "\n");
+}
+
+void INFO(const char *fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+    nobuild_vlog(stdout, "INFO", fmt, args);
+    va_end(args);
+}
+
+void WARN(const char *fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+    nobuild_vlog(stderr, "WARN", fmt, args);
+    va_end(args);
+}
+
+void ERRO(const char *fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+    nobuild_vlog(stderr, "ERRO", fmt, args);
+    va_end(args);
+}
+
 #endif // NOBUILD_IMPLEMENTATION