eolian gen2: prepare gen/arguments/file infra
authorDaniel Kolesa <d.kolesa@osg.samsung.com>
Tue, 13 Sep 2016 16:01:05 +0000 (18:01 +0200)
committerDaniel Kolesa <d.kolesa@osg.samsung.com>
Fri, 7 Oct 2016 09:54:23 +0000 (11:54 +0200)
src/bin/eolian2/main.c

index b333a19..cf0aafe 100644 (file)
@@ -1,7 +1,225 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <unistd.h>
+
 #include <Eina.h>
+#include <Eolian.h>
+
+enum
+{
+   GEN_H        = 1 << 0,
+   GEN_H_LEGACY = 1 << 1,
+   GEN_H_STUB   = 1 << 2,
+   GEN_C        = 1 << 3,
+   GEN_C_IMPL   = 1 << 4
+};
+
+static const char *_dexts[5] =
+{
+  ".eo.h", ".eo.legacy.h", ".eo.stub.h", ".eo.c", ".eo.c"
+};
+
+static int
+_get_bit_pos(int flag)
+{
+   int pos = 0;
+   for (; !(flag & 1); flag >>= 1)
+     ++pos;
+   return pos;
+}
+
+static void
+_print_usage(const char *progn, FILE *outf)
+{
+   fprintf(outf, "Usage: %s [options] [input]\n", progn);
+   fprintf(outf, "Options:\n"
+                 "  -I inc        include path \"inc\"\n"
+                 "  -g type       generate file of type \"type\"\n"
+                 "  -o name       specify the base name for output\n"
+                 "  -o type:name  specify a particular output filename\n"
+                 "  -h            print this message and exit\n"
+                 "  -v            print version and exit\n"
+                 "\n"
+                 "Available types:\n"
+                 "  h: C header file (.eo.h)\n"
+                 "  l: Legacy C header file (.eo.legacy.h)\n"
+                 "  s: Stub C header file (.eo.stub.h)\n"
+                 "  c: C source file (.eo.c)\n"
+                 "  i: Implementation file (added into .eo.c)\n"
+                 "\n"
+                 "By default, the 'hcl' set is used.\n"
+                 "Output filenames are determined from input .eo filename.\n");
+}
+
+static void
+_print_version(FILE *outf)
+{
+   fprintf(outf, "Eolian C generator version: " PACKAGE_VERSION "\n");
+}
+
+static Eina_Bool
+_try_set_out(char t, char **outs, const char *val)
+{
+   int pos = -1;
+   switch (t)
+     {
+      case 'h':
+        pos = _get_bit_pos(GEN_H);
+        break;
+      case 'l':
+        pos = _get_bit_pos(GEN_H_LEGACY);
+        break;
+      case 's':
+        pos = _get_bit_pos(GEN_H_STUB);
+        break;
+      case 'c':
+        pos = _get_bit_pos(GEN_C);
+        break;
+      case 'i':
+        pos = _get_bit_pos(GEN_C_IMPL);
+        break;
+     }
+   if (pos < 0)
+     return EINA_FALSE;
+   if (outs[pos])
+     free(outs[pos]);
+   outs[pos] = strdup(val);
+   return EINA_TRUE;
+}
+
+static void _fill_all_outs(char **outs, const char *val)
+{
+   size_t vlen = strlen(val);
+   for (size_t i = 0; i < (sizeof(_dexts) / sizeof(char *)); ++i)
+   {
+      if (outs[i])
+        continue;
+      size_t dlen = strlen(_dexts[i]);
+      char *str = malloc(vlen + dlen + 1);
+      memcpy(str, val, vlen);
+      memcpy(str + vlen, _dexts[i], dlen);
+      str[vlen + dlen] = '\0';
+      outs[i] = str;
+   }
+}
 
 int
-main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
+main(int argc, char **argv)
 {
-   return 0;
+   int pret = 1;
+
+   eina_init();
+   eolian_init();
+
+   char *outs[5] = { NULL, NULL, NULL, NULL, NULL };
+
+   int gen_what = 0;
+   for (int opt; (opt = getopt(argc, argv, "I:g:o:hvV")) != -1;)
+     switch (opt)
+       {
+        case 0:
+          break;
+        case 'I':
+          printf("including file: '%s'\n", optarg);
+          if (!eolian_directory_scan(optarg))
+            {
+               fprintf(stderr, "eolian: could not scan '%s'\n", optarg);
+               goto end;
+            }
+          printf("include: %s\n", optarg);
+          break;
+        case 'g':
+          for (const char *wstr = optarg; *wstr; ++wstr)
+            switch (*wstr)
+              {
+               case 'h':
+                 gen_what |= GEN_H;
+                 break;
+               case 'l':
+                 gen_what |= GEN_H_LEGACY;
+                 break;
+               case 's':
+                 gen_what |= GEN_H_STUB;
+                 break;
+               case 'c':
+                 gen_what |= GEN_C;
+                 break;
+               case 'i':
+                 gen_what |= GEN_C_IMPL;
+                 break;
+               default:
+                 fprintf(stderr, "unknown type: '%c'\n", *wstr);
+                 goto end;
+              }
+        case 'o':
+          if (strchr(optarg, ':'))
+            {
+               const char *abeg = optarg;
+               const char *cpos = strchr(abeg, ':');
+               if (((cpos - abeg) != 1) || !_try_set_out(*abeg, outs, cpos + 1))
+                 {
+                    char *oa = strdup(abeg);
+                    oa[cpos - abeg] = '\0';
+                    fprintf(stderr, "unknown type: '%s'\n", oa);
+                    free(oa);
+                    goto end;
+                 }
+            }
+          else _fill_all_outs(outs, optarg);
+          break;
+        case 'h':
+          _print_usage(argv[0], stdout);
+          goto end;
+        case 'v':
+          _print_version(stdout);
+          goto end;
+        default:
+          _print_usage(argv[0], stderr);
+          goto end;
+       }
+
+   const char *input = argv[optind];
+   if (!input)
+     {
+        fprintf(stderr, "eolian: no input file\n");
+        goto end;
+     }
+
+   const char *ext = strrchr(input, '.');
+   if (!ext || strcmp(ext, ".eo"))
+     {
+        fprintf(stderr, "eolian: invalid input file '%s'\n", input);
+        goto end;
+     }
+
+   char *inoext = strdup(input);
+   inoext[ext - input] = '\0';
+   _fill_all_outs(outs, inoext);
+   free(inoext);
+
+   if (!gen_what)
+     gen_what = GEN_H | GEN_H_LEGACY | GEN_C;
+
+   printf("generating\n");
+   if (gen_what & GEN_H)
+     printf("generating header: %s\n", outs[_get_bit_pos(GEN_H)]);
+   if (gen_what & GEN_H_LEGACY)
+     printf("generating legacy header: %s\n", outs[_get_bit_pos(GEN_H_LEGACY)]);
+   if (gen_what & GEN_H_STUB)
+     printf("generating header stub: %s\n", outs[_get_bit_pos(GEN_H_STUB)]);
+   if (gen_what & GEN_C)
+     printf("generating source: %s\n", outs[_get_bit_pos(GEN_C)]);
+   if (gen_what & GEN_C_IMPL)
+     printf("generating impl: %s\n", outs[_get_bit_pos(GEN_C_IMPL)]);
+
+   pret = 0;
+end:
+   for (size_t i = 0; i < (sizeof(_dexts) / sizeof(char *)); ++i)
+     free(outs[i]);
+   eolian_shutdown();
+   eina_shutdown();
+
+   return pret;
 }