summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/generator.c
diff options
context:
space:
mode:
Diffstat (limited to 'mrbgems/generator.c')
-rw-r--r--mrbgems/generator.c305
1 files changed, 305 insertions, 0 deletions
diff --git a/mrbgems/generator.c b/mrbgems/generator.c
new file mode 100644
index 000000000..aff0fb69e
--- /dev/null
+++ b/mrbgems/generator.c
@@ -0,0 +1,305 @@
+#include <string.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <mrbconf.h>
+#include <stdlib.h>
+
+static int
+one (const struct dirent *unused)
+{
+ return 1;
+}
+
+/*
+ * Does a directory exist?
+ * yes => TRUE
+ * no => FALSE
+ * fs error => FALSE
+ *
+ */
+static int
+directory_exists(char path[4096]) {
+ DIR* dir = opendir(path);
+ if (dir)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/*
+ * Template generator for each GEM
+ *
+ * Arguments:
+ * before:
+ * String before each GEM template
+ * after:
+ * String after each GEM template
+ * start:
+ * String at the start of the template
+ * end:
+ * String at the end of the template
+ * skip_if_src_not_exist:
+ * TRUE => skip template for GEMs with SRC directory
+ * FALSE => template for all GEMs
+ *
+ */
+static char*
+for_each_gem (char before[1024], char after[1024],
+ char start[1024], char end[1024],
+ char dir_to_skip[1024])
+{
+ struct dirent **eps;
+ int n;
+ char gemname[1024] = { 0 };
+ char gemname_path[4096] = { 0 };
+ char src_path[4096] = { 0 };
+ struct stat attribut;
+
+ /* return value */
+ char* complete_line = malloc(4096 + sizeof(char));
+ strcpy(complete_line, "");
+ strcat(complete_line, start);
+
+ n = scandir("./g", &eps, one, alphasort);
+ if (n >= 0) {
+ int cnt;
+ for (cnt = 0; cnt < n; ++cnt) {
+ strcpy(gemname, eps[cnt]->d_name);
+ strcpy(gemname_path, "./g/");
+ strcat(gemname_path, gemname);
+ strcpy(src_path, gemname_path);
+ strcat(src_path, "/src");
+
+ if (strcmp(gemname, ".") == 0)
+ continue;
+ if (strcmp(gemname, "..") == 0)
+ continue;
+ if (strcmp(gemname, ".gitignore") == 0)
+ continue;
+
+ stat(gemname_path, &attribut);
+ if (S_ISDIR(attribut.st_mode) == 0) {
+ continue;
+ }
+
+ if (strcmp(dir_to_skip, "") != 0) {
+ strcpy(src_path, gemname_path);
+ strcat(src_path, "/");
+ strcat(src_path, dir_to_skip);
+
+ if (directory_exists(src_path) != TRUE)
+ continue;
+ }
+
+ strcat(complete_line, before);
+ strcat(complete_line, gemname);
+ strcat(complete_line, after);
+ }
+ }
+ else {
+ perror("Error while scanning the directory.");
+ }
+
+ strcat(complete_line, end);
+ return complete_line;
+}
+
+/*
+ * Gem Makefile Generator
+ *
+ */
+void
+make_gem_makefile()
+{
+ char *gem_check = { 0 };
+ int gem_empty;
+ int gem_c_empty;
+ int gem_ruby_empty;
+
+ printf("CFLAGS := -I. -I../../include -I../../src\n\n"
+ "ifeq ($(OS),Windows_NT)\n"
+ "MAKE_FLAGS = --no-print-directory CC=$(CC) LL=$(LL) ALL_CFLAGS='$(ALL_CFLAGS)'\n"
+ "else\n"
+ "MAKE_FLAGS = --no-print-directory CC='$(CC)' LL='$(LL)' ALL_CFLAGS='$(ALL_CFLAGS)'\n"
+ "endif\n\n");
+
+ /* is there any GEM available? */
+ gem_check = for_each_gem("", "", "", "", "");
+ if (strcmp(gem_check, "") == 0)
+ gem_empty = TRUE;
+ else
+ gem_empty = FALSE;
+
+ /* is there a C extension available? */
+ gem_check = for_each_gem("", "", "", "", "src");
+ if (strcmp(gem_check, "") == 0)
+ gem_c_empty = TRUE;
+ else
+ gem_c_empty = FALSE;
+
+ /* is there a Ruby extension available */
+ gem_check = for_each_gem("", "", "", "", "mrblib");
+ if (strcmp(gem_check, "") == 0)
+ gem_ruby_empty = TRUE;
+ else
+ gem_ruby_empty = FALSE;
+
+ printf(".PHONY : all\n");
+ if (gem_empty) {
+ printf("all :\n\n");
+ }
+ else {
+ if (gem_c_empty) {
+ printf("all : mrblib_gem.o\n"
+ "\t$(AR) rs ../../lib/libmruby.a mrblib_gem.o\n");
+ }
+ else if (gem_ruby_empty) {
+ printf("all : all_gems\n");
+ }
+ else {
+ printf("all : all_gems mrblib_gem.o\n"
+ "\t$(AR) rs ../../lib/libmruby.a mrblib_gem.o\n");
+ }
+
+ printf("\n");
+
+ /* Rule for building all C extensions of each Gem */
+ if (!gem_c_empty) {
+ printf("all_gems :\n%s\n",
+ for_each_gem("\t@$(MAKE) -C ", " $(MAKE_FLAGS)\n", "", "", "")
+ );
+ }
+
+ /* Rule for building all Ruby Extension of each Gem */
+ if (!gem_ruby_empty) {
+ printf("mrblib_gem.o : mrblib_gem.c\n\n"
+
+ "mrblib_gem.c : mrblib_gem.ctmp\n"
+ "\tcat $< > $@\n\n"
+
+ "mrblib_gem.ctmp : mrblib_gem.rbtmp\n"
+ "\t../../bin/mrbc -Bmrblib_gem_irep -o$@ $<\n\n"
+
+ "mrblib_gem.rbtmp :\n%s\n",
+ for_each_gem(" ", "/mrblib/*.rb", "\tcat", "> mrblib_gem.rbtmp", "mrblib")
+ );
+ }
+ }
+
+ printf("\n.PHONY : prepare-test\n"
+ "prepare-test :\n"
+ );
+ if (!gem_empty)
+ printf("%s",
+ for_each_gem(" ", "/test/*.rb ", "\tcat", " > mrbgemtest.rbtmp", "test")
+ );
+ else
+ printf("\t../generator rbtmp > mrbgemtest.rbtmp");
+ printf("\n\t../../bin/mrbc -Bmrbgemtest_irep -omrbgemtest.ctmp mrbgemtest.rbtmp\n\n");
+
+ printf(".PHONY : clean\n"
+ "clean :\n"
+ "\t$(RM) *.c *.d *.rbtmp *.ctmp *.o mrbtest\n");
+ if (!gem_empty)
+ printf("%s",
+ for_each_gem("\t@$(MAKE) clean -C ", " $(MAKE_FLAGS)\n", "", "", "")
+ );
+}
+
+/*
+ * init_gems.c Generator
+ *
+ */
+void
+make_init_gems()
+{
+ char *gem_check = { 0 };
+ int gem_c_empty;
+ int gem_ruby_empty;
+
+ /* is there a C extension available? */
+ gem_check = for_each_gem("", "", "", "", "src");
+ if (strcmp(gem_check, "") == 0)
+ gem_c_empty = TRUE;
+ else
+ gem_c_empty = FALSE;
+
+ /* is there a Ruby extension available */
+ gem_check = for_each_gem("", "", "", "", "mrblib");
+ if (strcmp(gem_check, "") == 0)
+ gem_ruby_empty = TRUE;
+ else
+ gem_ruby_empty = FALSE;
+
+ printf("/*\n"
+ " * This file contains a list of all\n"
+ " * initializing methods which are\n"
+ " * necessary to bootstrap all gems.\n"
+ " *\n"
+ " * IMPORTANT:\n"
+ " * This file was generated!\n"
+ " * All manual changes will get lost.\n"
+ " */\n\n"
+ "#include \"mruby.h\"\n"
+ "#include \"mruby/irep.h\"\n"
+ "#include \"mruby/dump.h\"\n"
+ "#include \"mruby/string.h\"\n"
+ "#include \"mruby/proc.h\"\n");
+
+ if (!gem_c_empty)
+ printf("\n%s",
+ for_each_gem("void mrb_", "_gem_init(mrb_state*);\n", "", "", "src")
+ );
+
+ if (!gem_ruby_empty)
+ printf("\nextern const char mrblib_gem_irep[];\n");
+
+ printf("\nvoid\n"
+ "mrb_init_mrbgems(mrb_state *mrb) {\n");
+
+ if (!gem_c_empty)
+ printf("%s",
+ for_each_gem(" mrb_", "_gem_init(mrb);\n", "", "", "src")
+ );
+
+ if (!gem_ruby_empty) {
+ printf(" int n = mrb_read_irep(mrb, mrblib_gem_irep);\n"
+ " mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb));\n"
+ " if (mrb->exc) {\n"
+ " mrb_p(mrb, mrb_obj_value(mrb->exc));\n"
+ " exit(0);\n"
+ " }\n");
+ }
+
+ printf("}");
+}
+
+void
+make_rbtmp()
+{
+ printf("\n");
+}
+
+int
+main (int argc, char *argv[])
+{
+ if (argc == 2) {
+ if (strcmp(argv[1], "makefile") == 0)
+ make_gem_makefile();
+ else if (strcmp(argv[1], "init_gems") == 0)
+ make_init_gems();
+ else if (strcmp(argv[1], "rbtmp") == 0)
+ make_rbtmp();
+ else
+ return 1;
+ }
+ else {
+ printf("Argument missing! Options: 'makefile', 'init_gems', 'rbtmp'");
+ return 1;
+ }
+
+ return 0;
+}