]> git.xolatile.top Git - emil-bake.git/commitdiff
Rewrite
authorEmil <emilwilliams@tuta.io>
Wed, 27 Sep 2023 22:50:55 +0000 (22:50 +0000)
committerEmil <emilwilliams@tuta.io>
Wed, 27 Sep 2023 22:50:55 +0000 (22:50 +0000)
baked.c

diff --git a/baked.c b/baked.c
index b7c26dae2a9db0e6622a2450553d22d917054cf4..13e26f3fe9b577315dc1c0994a592208752e43be 100644 (file)
--- a/baked.c
+++ b/baked.c
@@ -1,43 +1,4 @@
-/* baked.c - Ever burned a cake?
- *
- *  Copyright 2023 Emil Williams
- *
- *  baked is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 3
- *  as published by the Free Software Foundation.
- *
- *  You should have received a copy of the GNU General Public License
- *  version 3 along with this program. If not, see <https://www.gnu.org/licenses/gpl-3.0.en.html>.
- *
- * This program is independent of language, it simply expects the notation as listed below,
- *
- * EXEC:cc $@ -o $* -std=gnu99 -O2 -Wall -Wextra -Wpedantic -pipe $CFLAGS:STOP
- *
- * Which will run, and in this case, result in this program compiling itself.
- *
- * Another (functional) example:
- EXEC:
- CFLAGS='-std=gnu99 -O2 -Wall -Wextra -Wpedantic -pipe'
- cc $@ -o $* $CFLAGS # baked
- :STOP
- *
- * See install.sh for another example coded into a different language.
- * It is possible to override environmental variables, as in install.sh,
- * you can then have some dynamism.
- *
- * Realistically, any traditional shell script could be composed in this
- * fashion, and be embedded in any file. However, some programming languages
- * may not have multiline comments, so you may be restricted to a single line.
- *
- * with the flag CFLAGS='-DSHAKE_COMPAT' Shake compatibility will be enabled,
- * @COMPILECMD cc $@ -o $* -std=gnu99 -O2 -Wall -Wextra -Wpedantic -pipe $CFLAGS # SHAKE_COMPAT enabled
- *
- * TODO
- *
- * 1. somehow convince the compiler to do NULL checks before g_...
- *    so that allocs can be minimized even further (maybe it should be volatile)
- * 2. support #!/bin/someshell
- */
+/* EXEC:cc $@ -o $* -std=gnu89 -O2 -Wall -Wextra -Wpedantic -pipe $CFLAGS:STOP */
 
 #include <assert.h>
 #include <errno.h>
 #include <sys/stat.h>
 
 #ifndef SHAKE_COMPAT
-# define HELP                                                       \
-  "target-file\n"                                                   \
+# define HELP                                                           \
+  "target-file [arguments ...]\n"                                       \
   "Use the format `EXEC:command ...:STOP' within the target-file\n"
 # define START "EXEC:"
 # define STOP ":STOP"
 #else
-# define HELP                                                       \
-  "target-file\n"                                                   \
+# define HELP                                                           \
+  "target-file [arguments ...]\n"                                       \
   "Use the format `@COMPILECMD command ...\n' within the target-file\n"
 # define START "@COMPILECMD "
 # define STOP "\n"
 #endif
 
 #define DESC                                                          \
-  "\t$@  returns target-file value\n"                                 \
-  "\t$*  returns target-file without extension\n"                     \
+  "\t$@  returns target-file\n"                                       \
+  "\t$*  returns target-file without suffix\n"                        \
   "\t$+  returns arguments\n"
 
-#define die(fmt, ...) do { _die(fmt, ##__VA_ARGS__); goto stop; } while (0)
-
-static const char * argv0;
-static char * g_filename = NULL, * g_sh = NULL, * g_all = NULL;
-
-#define local_assert(expr, ret) do { assert(expr); return ret; } while(0)
-
-static void
-_die(const char * fmt, ...)
+static char *
+find(char * buf, const char * token)
 {
-  va_list ap;
-  assert(fmt);
-  fprintf(stderr, "%s: ", argv0);
-  va_start(ap, fmt);
-       vfprintf(stderr, fmt, ap);
-       va_end(ap);
-       if (fmt[0] &&
-      fmt[strlen(fmt)-1] == ':')
-  {
-               fputc(' ', stderr);
-               perror(NULL);
-       }
-  else
-  { fputc('\n', stderr); }
+  size_t len = strlen(token);
+  const char * stop = buf + strlen(buf);
+  do if (!strncmp(buf,token,len))
+  { return buf + len; }
+  while (buf < stop && ++buf);
+  return NULL;
 }
 
 static char *
 load(const char * fn)
 {
-  struct stat s;
+  char * buf = NULL;
   FILE * fp = fopen(fn, "rb");
-  if (!(stat(fn,&s)) &&
-      s.st_mode & S_IFREG &&
-      fp)
+  if (fp)
   {
+    struct stat s;
     size_t len;
-    char * buf;
-    len = s.st_size;
-    if (!(buf = malloc(len + 1)))
-    { return NULL; }
-    if (fread(buf, 1, len, fp) > strlen(STOP) + strlen(START))
-    {
-      buf[len] = '\0';
-      fclose(fp);
-      return buf;
-    }
+    if (! stat(fn,&s)
+    &&    s.st_mode & S_IFREG
+    &&   (len = s.st_size)
+    &&   (buf = malloc(len + 1))
+    &&    fread(buf, 1, len, fp) > strlen(STOP) + strlen(START))
+    { buf[len] = '\0'; }
     fclose(fp);
-    free(buf);
   }
-  return NULL;
+  return buf;
+}
+
+static char *
+find_region(const char * fn)
+{
+  size_t len;
+  char * buf, * start, * stop;
+
+  if (!(buf = load(fn)))
+  { fprintf(stderr, errno ? "cannot access '%s':" : "'%s': file too short", fn); return NULL; }
+
+  if (!(start = find(buf,   START))
+  ||  !(stop  = find(start, STOP)))
+  { fprintf(stderr, "No usable format located in '%s'", fn); return NULL; }
+
+  len = stop - start - strlen(STOP);
+  memmove(buf, start, len);
+  buf = realloc(buf, len + 1);
+  buf[len] = '\0';
+  return buf;
 }
 
 static void
@@ -140,148 +100,112 @@ root(char * root)
   swap(root + len, x);
   ret = chdir(root);
   swap(root + len, x);
-  printf("root:%d\n", ret);
   return ret;
 }
 
-static char *
-find(char * buf, const char * token)
-{
-  size_t len = strlen(token);
-  const char * stop = buf + strlen(buf);
-  do if (!strncmp(buf,token,len))
-  { return buf + len; }
-  while (buf < stop && ++buf);
-  return NULL;
-}
-
 static char *
 insert(const char * new, char * str, size_t offset, size_t shift)
 {
   size_t len = strlen(new);
   size_t max = strlen(str) + 1;
-  /* fprintf(stderr, "params '%s' '%s' %ld %ld\n", new, str, offset, shift); */
-  str = realloc(str, max + len);
-  local_assert(str, NULL);
+  /* str = realloc(str, max + len); */
   memmove(str + offset + len, str + offset + shift, max - offset - shift);
   memcpy(str + offset, new, len);
   return str;
 }
 
 static char *
-expand(char * buf, size_t len)
+expand(char * buf, char ** str)
 {
-  size_t i = 0;
-  char * str = "";
-  local_assert(buf, NULL);
+  size_t i, len = strlen(buf);
+  int x;
+  buf = realloc(buf, 500);
   for (i = 0; i < len; ++i)
   {
     if (buf[i] == '\\')
-    { i+=2; continue; }
-    if (buf[i] == '$')
+    { i += 2; continue; }
+    else if (buf[i] == '$')
     {
       switch (buf[++i])
       {
-      case '@': /* replace $@ with g_filename */
-        str = g_filename;
-        break;
-      case '*': /* replace $* with short nm */
-        str = g_sh;
-        break;
-      case '+': /* replace $+ with all args */
-        str = g_all ? g_all : "";
-        break;
+      case '@': x = 0; break;
+      case '*': x = 1; break;
+      case '+': x = 2; break;
       default: continue;
       }
-      buf = insert(str, buf, i - 1, 2);
+      buf = insert(str[x], buf, i - 1, 2);
       len = strlen(buf);
     }
   }
   return buf;
 }
 
-static void
-init(char ** argv, int argc)
+static char *
+shorten(char * fn)
 {
-  size_t i, len;
-
-  /* g_filename */
-  g_filename = malloc(strlen(argv[1]) + 1);
-  strcpy(g_filename, argv[1]);
-
-  /* sh */
-  { size_t last = 0;
-  len = strlen(argv[1]); /* co-opting len */
-  g_sh = malloc(len + 1);
+  size_t i, last = 0, len = strlen(fn);
+  char * sh = malloc(len + 1);
   for (i = 0; i < len; ++i)
   {
-    if (argv[1][i] == '.')
+    if (fn[i] == '.')
     { last = i; }
   }
   last = last ? last : i;
-  strncpy(g_sh, argv[1], last);
-  g_sh[last] = '\0';
-  } /* EOL last */
-  /* all */
+  strncpy(sh, fn, last);
+  sh[last] = '\0';
+  return sh;
+}
+
+static char *
+all_args(size_t argc, char ** argv)
+{
+  char * all = NULL;
   if (argc > 2)
   {
+    size_t i, len = 0;
+    for (i = 2; i < argc; ++i)
+    { len += strlen(argv[i]); }
+    all = malloc(len + 1);
+    all[len] = '\0';
     len = 0;
-    i = 2;
-    while (i < (size_t) argc)
+    for (i = 2; i < argc; ++i)
     {
+      strcpy(all + len, argv[i]);
       len += strlen(argv[i]);
-      ++i;
-    }
-    g_all = malloc(len + 1);
-    g_all[len] = '\0';
-    len = 0;
-    i = 2;
-    while (i < (size_t) argc)
-    {
-      strcpy(g_all + len, argv[i]);
-      len += strlen(argv[i]);
-      ++i;
     }
   }
+  return all;
 }
 
 int
 main(int argc, char ** argv)
 {
-  int ret = 0;
-  char * buf = NULL;
-  { size_t len;
-  { char * start, * stop;
-
-  argv0 = argv[0];
-
+  int ret;
+  char * str[3];
+  char * buf;
   if (argc < 2)
-  { die(HELP); }
+  {
+    fprintf(stderr, "%s: %s", argv[0], HELP DESC);
+    return 1;
+  }
 
-  if (!(buf = load(argv[1]))
-      ||      root(argv[1]))
-  { die(errno ? "cannot access '%s':" : "'%s': file too short", argv[1]); }
+  /* filename */
+  str[0] = argv[1];
 
-  if (!(start = find(buf,   START))
-      ||  !(stop  = find(start, STOP)))
-  { die("No usable format located in '%s'", argv[1]); }
+  /* sh */
+  str[1] = shorten(argv[1]);
 
-  init(argv, argc);
+  /* all */
 
-  len = stop - start - strlen(STOP);
-  memmove(buf, start, len);
-  } /* EOL start stop*/
-  buf = realloc(buf, len + 1);
-  buf[len] = '\0';
+  str[2] = all_args((size_t) argc, argv);
+
+  buf = find_region(argv[1]);
+  root(argv[1]);
+  buf = expand(buf, str);
   fprintf(stderr, "Exec: %s\nOutput:\n", buf);
-  buf = expand(buf, len);
-  } /* EOL len */
   fprintf(stderr, "Result: %d\n", (ret = system(buf)));
-
-stop:
-  free(g_filename);
-  free(g_sh);
-  free(g_all);
+  free(str[2]);
+  free(str[1]);
   free(buf);
   return ret;
 }