~ chicken-core (chicken-5) 2d2646296bbe5633829be17b008889ba8f13a304


commit 2d2646296bbe5633829be17b008889ba8f13a304
Author:     felix <felix@call-with-current-continuation.org>
AuthorDate: Thu Aug 18 17:48:17 2016 +0200
Commit:     felix <felix@call-with-current-continuation.org>
CommitDate: Sun Nov 13 11:32:20 2016 +0100

    added chicken-do program

diff --git a/Makefile.cross-linux-mingw b/Makefile.cross-linux-mingw
index 488d41b0..567004bb 100644
--- a/Makefile.cross-linux-mingw
+++ b/Makefile.cross-linux-mingw
@@ -76,13 +76,13 @@ include $(SRCDIR)/defaults.make
 ifndef BUILD_SETUP_TOOLS
 TARGETS = libchicken$(A) $(CHICKEN_PROGRAM)$(EXE) $(CSI_PROGRAM)$(EXE) \
 	$(CHICKEN_PROFILE_PROGRAM)$(EXE) $(CSC_PROGRAM)$(EXE) lib$(PROGRAM_PREFIX)chicken$(PROGRAM_SUFFIX)$(SO) \
-	$(CHICKEN_BUG_PROGRAM)$(EXE)
+	$(CHICKEN_BUG_PROGRAM)$(EXE) $(CHICKEN_DO_PROGRAM)$(EXE)
 else
 TARGETS = libchicken$(A) $(CHICKEN_PROGRAM)$(EXE) $(CSI_PROGRAM)$(EXE) \
 	$(CHICKEN_PROFILE_PROGRAM)$(EXE) $(CSC_PROGRAM)$(EXE) lib$(PROGRAM_PREFIX)chicken$(PROGRAM_SUFFIX)$(SO) \
 	$(CHICKEN_INSTALL_PROGRAM)$(EXE) $(CHICKEN_UNINSTALL_PROGRAM)$(EXE) \
 	$(CHICKEN_STATUS_PROGRAM)$(EXE) \
-	$(CHICKEN_BUG_PROGRAM)$(EXE)
+	$(CHICKEN_BUG_PROGRAM)$(EXE) $(CHICKEN_DO_PROGRAM)$(EXE)
 endif
 
 chicken-config.h: chicken-defaults.h
diff --git a/chicken-do.c b/chicken-do.c
new file mode 100644
index 00000000..c2fe6b2a
--- /dev/null
+++ b/chicken-do.c
@@ -0,0 +1,82 @@
+/* chicken-do: execute command if dependency changed or target is out of date*/
+
+
+#include "chicken.h"
+#include <sys/stat.h>
+#include <errno.h>
+
+
+void usage(int code)
+{
+  fputs("usage: chicken-do [-q] [-h] TARGET COMMAND ... : DEPENDENCIES ...\n", stderr);
+  exit(code);
+}
+
+
+int execute(char **argv)
+{
+  execvp(argv[ 0 ], argv);
+  /* returns only in case of error */
+  perror("executing command failed");
+  exit(1);
+}
+
+
+int main(int argc, char *argv[]) 
+{
+  int i, count, a = 0;
+  char **args = (char **)malloc(sizeof(char *) * argc);
+  char *target;
+  struct stat st, sd;
+  int quiet = 0;
+
+  if(argc < 3) usage(1);
+
+  target = argv[ 1 ];
+
+  for(i = 2; i < argc; ++i) {
+    if(*argv[ i ] == '-') {
+      switch(argv[ i ][ 1 ]) {
+      case 'q': quiet = 1; break;
+      case 'h': usage(0);
+      default: usage(1);
+      }
+    }
+    else if(!strcmp(argv[ i ], ":")) break;
+    else args[ a++ ] = argv[ i ];
+  }
+
+  if(i == argc) usage(1);
+
+  args[ a ] = NULL;
+  
+  if(stat(target, &st) == -1) {
+    if(errno == ENOENT) goto build;
+
+    fprintf(stderr, "%s: %s\n", target, strerror(errno));
+    exit(1);
+  }
+
+  for(++i; i < argc; ++i) {
+    if(stat(argv[ i ], &sd) == -1) {
+      fprintf(stderr, "%s: %s\n", argv[ i ], strerror(errno));
+      exit(1);
+    }      
+
+    if(sd.st_mtime > st.st_mtime) goto build;
+  }
+
+  return 0;
+
+build:
+  if(!quiet) {
+    fputs("  ", stdout);
+
+    for(i = 0; i < a; ++i)
+      printf(" %s", args[ i ]);
+
+    putchar('\n');
+  }
+
+  execute(args);
+}
diff --git a/defaults.make b/defaults.make
index 68e0e578..b8b9f672 100644
--- a/defaults.make
+++ b/defaults.make
@@ -282,6 +282,7 @@ CHICKEN_INSTALL_PROGRAM = $(PROGRAM_PREFIX)chicken-install$(PROGRAM_SUFFIX)
 CHICKEN_UNINSTALL_PROGRAM = $(PROGRAM_PREFIX)chicken-uninstall$(PROGRAM_SUFFIX)
 CHICKEN_STATUS_PROGRAM = $(PROGRAM_PREFIX)chicken-status$(PROGRAM_SUFFIX)
 CHICKEN_BUG_PROGRAM = $(PROGRAM_PREFIX)chicken-bug$(PROGRAM_SUFFIX)
+CHICKEN_DO_PROGRAM = $(PROGRAM_PREFIX)chicken-do$(PROGRAM_SUFFIX)
 CHICKEN_DEBUGGER_PROGRAM ?= $(PROGRAM_PREFIX)feathers$(PROGRAM_SUFFIX)$(SCRIPT_EXT)
 IMPORT_LIBRARIES = $(DYNAMIC_IMPORT_LIBRARIES) \
 		   $(PRIMITIVE_IMPORT_LIBRARIES) \
@@ -298,7 +299,7 @@ TARGETLIBS ?= lib$(PROGRAM_PREFIX)chicken$(PROGRAM_SUFFIX)$(A)
 TARGETS += $(TARGETLIBS) $(CHICKEN_STATIC_EXECUTABLE) \
 	$(CSI_STATIC_EXECUTABLE) $(CHICKEN_PROFILE_PROGRAM)$(EXE) \
 	$(CSC_PROGRAM)$(EXE) \
-	$(CHICKEN_BUG_PROGRAM)$(EXE) $(CHICKEN_DEBUGGER_PROGRAM)
+	$(CHICKEN_BUG_PROGRAM)$(EXE) $(CHICKEN_DO_PROGRAM)$(EXE) $(CHICKEN_DEBUGGER_PROGRAM)
 else
 CHICKEN_STATIC_EXECUTABLE = $(CHICKEN_PROGRAM)-static$(EXE)
 CSI_STATIC_EXECUTABLE = $(CSI_PROGRAM)-static$(EXE)
@@ -309,7 +310,7 @@ TARGETS += $(TARGETLIBS) $(CHICKEN_SHARED_EXECUTABLE) \
 	$(CSI_SHARED_EXECUTABLE) $(CHICKEN_PROFILE_PROGRAM)$(EXE) \
 	$(CSC_PROGRAM)$(EXE) $(CHICKEN_INSTALL_PROGRAM)$(EXE) $(CHICKEN_UNINSTALL_PROGRAM)$(EXE) \
 	$(CHICKEN_STATUS_PROGRAM)$(EXE) setup-download.so setup-api.so \
-	$(CHICKEN_BUG_PROGRAM)$(EXE) $(CHICKEN_DEBUGGER_PROGRAM) \
+	$(CHICKEN_BUG_PROGRAM)$(EXE) $(CHICKEN_DO_PROGRAM)$(EXE) $(CHICKEN_DEBUGGER_PROGRAM) \
 	$(IMPORT_LIBRARIES:%=%.import.so)
 endif
 ifdef WINDOWS
@@ -454,6 +455,9 @@ endif
 	$(call echo, >>, $@,#ifndef C_CHICKEN_BUG_PROGRAM)
 	$(call echo, >>, $@,# define C_CHICKEN_BUG_PROGRAM "$(CHICKEN_BUG_PROGRAM)")
 	$(call echo, >>, $@,#endif)
+	$(call echo, >>, $@,#ifndef C_CHICKEN_DO_PROGRAM)
+	$(call echo, >>, $@,# define C_CHICKEN_DO_PROGRAM "$(CHICKEN_DO_PROGRAM)")
+	$(call echo, >>, $@,#endif)
 	$(call echo, >>, $@,#ifndef C_CHICKEN_INSTALL_PROGRAM)
 	$(call echo, >>, $@,# define C_CHICKEN_INSTALL_PROGRAM "$(CHICKEN_INSTALL_PROGRAM)")
 	$(call echo, >>, $@,#endif)
diff --git a/rules.make b/rules.make
index 3017cc7e..244663ab 100644
--- a/rules.make
+++ b/rules.make
@@ -68,7 +68,7 @@ MANPAGES = \
 # care of which programs should actually be installed/uninstalled
 INSTALLED_PROGRAMS = \
 	$(CHICKEN_PROGRAM) $(CSI_PROGRAM) $(CHICKEN_PROFILE_PROGRAM) \
-	$(CSC_PROGRAM) $(CHICKEN_BUG_PROGRAM)
+	$(CSC_PROGRAM) $(CHICKEN_BUG_PROGRAM) $(CHICKEN_DO_PROGRAM)
 
 ifndef STATICBUILD
 INSTALLED_PROGRAMS += $(CHICKEN_STATUS_PROGRAM) \
@@ -284,6 +284,10 @@ endef
 $(eval $(call declare-program-from-object,$(CSI_STATIC_EXECUTABLE),csi))
 $(eval $(call declare-program-from-object,$(CHICKEN_BUG_PROGRAM)$(EXE),chicken-bug))
 
+# "chicken-do"
+
+$(CHICKEN_DO_PROGRAM): $(SRCDIR)chicken-do.c
+	$(C_COMPILER) $(C_COMPILER_OPTIONS) $< -o $@
 
 # scripts
 
@@ -916,6 +920,7 @@ clean:
 	  $(CHICKEN_UNINSTALL_PROGRAM)$(EXE) \
 	  $(CHICKEN_STATUS_PROGRAM)$(EXE) \
 	  $(CHICKEN_BUG_PROGRAM)$(EXE) *$(O) \
+	  $(CHICKEN_DO_PROGRAM)$(EXE) \
 	  $(LIBCHICKEN_SO_FILE) \
 	  $(PRIMARY_LIBCHICKEN) \
 	  lib$(PROGRAM_PREFIX)chicken$(PROGRAM_SUFFIX)$(A) \
Trap