trc support for makefile_cc
authorThomas Walker Lynch <thomas.lynch@reasoningtechnology.com>
Mon, 1 Apr 2019 11:05:17 +0000 (13:05 +0200)
committerThomas Walker Lynch <thomas.lynch@reasoningtechnology.com>
Mon, 1 Apr 2019 11:05:17 +0000 (13:05 +0200)
38 files changed:
makefile
module/da/src/da.lib.c
module/da/src/da.lib.h
module/da/test/results [deleted file]
module/da/test/src/test_da.lib.c
module/da/test/try/passed.transcript [new file with mode: 0644]
module/db/0_makefile [deleted file]
module/db/0_makefile-flags [deleted file]
module/db/1_doc/return-from-transaction.txt [deleted file]
module/db/dbprintf.lib.c [deleted file]
module/db/include/db.h [new file with mode: 0644]
module/db/lib/libda.a [new file with mode: 0644]
module/db/lib/libdb.a [new file with mode: 0644]
module/db/makefile [new file with mode: 0644]
module/db/makefile-flags [new file with mode: 0644]
module/db/src/db.lib.c [new file with mode: 0644]
module/db/src/db.lib.h [new file with mode: 0644]
module/dispatch/makefile-flags
module/dispatch/src/dispatch.lib.c [deleted file]
module/dispatch/trc/dispatch.trc.c [new file with mode: 0644]
module/share/include/da.h
module/share/lib/libda.a
module/tranche/makefile
module/tranche/makefile-flags
module/tranche/src/tranche-make.cli.c
module/tranche/src/tranche-target.cli.c
module/tranche/src/tranche.cli.c
module/tranche/src/tranche.lib.c
module/tranche/src/tranche.lib.h
module/tranche/test/try/test2.sh
module/tranche/test/try/test2stdout.dat.expected [deleted file]
module/tranche/test/try/test5.sh [new file with mode: 0644]
tool/bin/@System.solv [new file with mode: 0644]
tool/bin/tranche
tool/bin/tranche-make
tool/bin/tranche-target
tool/lib/makefile-cc
tool/lib/makefile-trc [deleted file]

index c7a88ed..af4d046 100755 (executable)
--- a/makefile
+++ b/makefile
@@ -5,7 +5,7 @@
 #    | grep -v deprecated | grep -v doc | sort -u | sed ':a;N;$!ba;s/\n/ /g' \
 #)
 
-MAKEABLE= module/da module/da/test module/tranche
+MAKEABLE= module/da module/da/test module/tranche module/dispatch
 
 .PHONY: all info clean dist-clean
 
index f09412d..18abb99 100644 (file)
@@ -10,9 +10,7 @@ Dynamic Array
 #include<string.h>
 
 //--------------------------------------------------------------------------------
-// generic
-// We manipulate pointers to a smallest addressable unit. The sizeof operator
-// returns counts in these addressable units. Sizeof(char) is defined to be 1.
+// allocation
 
 void da_alloc(Da *dap, size_t element_size){
   dap->element_size = element_size;
@@ -36,7 +34,6 @@ size_t da_length(Da *dap){
   return (dap->end - dap->base)/dap->element_size;
 }
 
-
 void da_rebase(Da *dap, char *old_base, void *pta){
   char **pt = (char **)pta;
   size_t offset = *pt - old_base;
@@ -58,16 +55,20 @@ char *da_expand(Da *dap){
   return old_base;
 }
 
-// true when pt has run off the end of the area currently allocated for the array
-bool da_endq(Da *dap, void *pt){
-  return (char *)pt >= dap->end;
-}
-
-// true when pt has run off the end of the area allocated for the array
+// true when end has run off the allocated area
 bool da_boundq(Da *dap){
   return dap->end >= dap->base + dap->size;
 }
 
+//--------------------------------------------------------------------------------
+// putting/taking items
+
+char *da_index(Da *dap, size_t i){
+  size_t offset = i * dap->element_size;
+  char *pt = dap->base + offset;
+  return pt;
+}
+
 void da_push(Da *dap, void *element){
   if( dap->end >= dap->base + dap->size ) da_expand(dap);
   memcpy(dap->end, element, dap->element_size);
@@ -83,32 +84,12 @@ bool da_pop(Da *dap, void *element){
   return flag;
 }
 
-void da_cat(Da *dap0, Da *dap1){
-  if(dap1->base == dap1->end) return;
-  size_t dap0_size = dap0->end - dap0->base;
-  size_t dap1_size = dap1->end - dap1->base; // size of the active portion
-  dap0->end += dap1_size;
-  while( dap0->end >= dap0->base + dap0->size ) da_expand(dap0);
-  memcpy(dap0->base + dap0_size, dap1->base, dap1_size);
-}
-
-// If dap0 has had a terminatating zero added, that must be popped off before
-// the call.  Similarly if a terminating zero is desired, it should be pushed
-// after the call.
-void da_push_string(Da *dap0, char *string){
-  if(!*string) return;
-  size_t dap0_size = dap0->end - dap0->base;
-  size_t string_size = strlen(string);
-  dap0->end += string_size;
-  while( dap0->end >= dap0->base + dap0->size ) da_expand(dap0);
-  memcpy(dap0->base + dap0_size, string, string_size);
-}
-
+//--------------------------------------------------------------------------------
+// iteration
 
-char *da_index(Da *dap, size_t i){
-  size_t offset = i * dap->element_size;
-  char *pt = dap->base + offset;
-  return pt;
+// true when pt has run off the end
+bool da_endq(Da *dap, void *pt){
+  return (char *)pt >= dap->end;
 }
 
 // passed in f(element_pt, arg_pt)
@@ -122,41 +103,98 @@ void da_map(Da *dap, void f(void *, void *), void *closure){
   }
 }
 
-// da_lists are sometimes used as resource managers
+//--------------------------------------------------------------------------------
+// da being used as a resource manager
+
+
+// elements were malloced, now they will all be freed
 static void da_free_element(void *pt, void *closure){
   free(*(char **)pt); // free does not care about the pointer type
 }
-
 void da_free_elements(Da *dap){
   da_map(dap, da_free_element, NULL);
   da_rewind(dap);
 }
 
+//--------------------------------------------------------------------------------
+// da is an array of integers
+
+// would like to pass in the printf format to make a general print
+// but can't get *pt on the stack for the printf call .. hmmm
+void da_ints_print(Da *dap, char *sep){
+  char *pt = dap->base; // char * because it points to a byte in the array
+  if( pt < dap->end ){
+    printf("%u", *(int *)pt);
+    pt += dap->element_size;
+    while( pt < dap->end ){
+      printf("%s%u", sep, *(int *)pt);
+      pt += dap->element_size;
+    }}}
+
+
+//--------------------------------------------------------------------------------
+// da is an array of strings
+
 // for the case of an array of strings
-void da_strings_puts(Da *dap){
+void da_strings_print(Da *dap, char *sep){
   char *pt = dap->base; // char * because it points to a byte in the array
-  while( pt < dap->end ){
-    puts(*(char **)pt);
-  pt += dap->element_size;
+  if( pt < dap->end ){
+    fputs(*(char **)pt, stdout);
+    pt += dap->element_size;
+    while( pt < dap->end ){
+      fputs(sep,stdout);
+      fputs(*(char **)pt,stdout);
+      pt += dap->element_size;
+    }}}
+
+// da is an array of strings, true if the test string is in the array
+// might be better to iterate instead of using a map ... 
+typedef struct {
+  char *string;
+  bool found;
+} da_strings_exists_closure;
+static void string_equal(void *sp, void *closure){
+  char *string_element = *(char **)sp;
+  da_strings_exists_closure *ss = (da_strings_exists_closure *)closure;
+  if( ss->found ) return;
+  ss->found = !strcmp(string_element, ss->string);
+  return;
+}
+bool da_strings_exists(Da *string_arrp, char *test_string){
+  da_strings_exists_closure sec;
+  sec.string = test_string;
+  sec.found = false;
+  da_map(string_arrp, string_equal, &sec);
+  return sec.found;
+}
+
+void da_strings_set_insert(Da *string_arrp, char *proffered_string, void destruct(void *)){
+  if( da_strings_exists( string_arrp, proffered_string)){ // then throw it away, we don't need it
+    if(destruct)destruct(proffered_string);
+    return;
   }
+  da_push(string_arrp, &proffered_string);
 }
 
-// would like to pass in the printf format to make a general print
-// but can't get *pt on the stack for the printf call .. hmmm
-void da_ints_print(Da *dap){
-  char *pt = dap->base;
-  while( pt < dap->end ){
-    printf("%u\n", *(int *)pt);
-  pt += dap->element_size;
+// union
+void da_strings_set_union(Da *string_arrp, Da *proffered_string_arrp, void destruct(void *)){
+  char *pt = proffered_string_arrp->base;
+  while( pt < proffered_string_arrp->end ){
+    da_strings_set_insert(string_arrp, *(char **)pt, destruct);
+  pt += proffered_string_arrp->element_size;
   }
+  return;
 }
 
 
+//--------------------------------------------------------------------------------
+// the da itself is a string
+
 // Puts text from a line into buffer *dap. Does not push EOF or '\n' into the
 // buffer.  Returns the old_base so that external pointers can be rebased.
 // It is possible that the the base hasn't changed. Use feof(FILE *stream) to
 // test for EOF;
-char *da_fgets(Da *dap, FILE *file){
+char *da_string_input(Da *dap, FILE *file){
   char *old_base = dap->base;
   int c = fgetc(file);
   while( c != EOF && c != '\n' ){
@@ -167,3 +205,32 @@ char *da_fgets(Da *dap, FILE *file){
   da_push(dap, &terminator);
   return old_base;
 }
+
+void da_string_push(Da *dap0, char *string){
+  if(!*string) return;
+  size_t dap0_size = dap0->end - dap0->base;
+  size_t string_size = strlen(string);
+  dap0->end += string_size;
+  while( dap0->end >= dap0->base + dap0->size ) da_expand(dap0);
+  memcpy(dap0->base + dap0_size, string, string_size);
+}
+
+
+//--------------------------------------------------------------------------------
+// list operations
+
+// If dap0 has had a terminatating zero added, that must be popped off before
+// the call.  Similarly if a terminating zero is desired, it should be pushed
+// after the call.
+
+// appends contents of dap1 onto dap0
+void da_cat(Da *dap0, Da *dap1){
+  if(dap1->base == dap1->end) return;
+  size_t dap0_size = dap0->end - dap0->base;
+  size_t dap1_size = dap1->end - dap1->base; // size of the active portion
+  dap0->end += dap1_size;
+  while( dap0->end >= dap0->base + dap0->size ) da_expand(dap0);
+  memcpy(dap0->base + dap0_size, dap1->base, dap1_size);
+}
+
+
index 3188011..518e72c 100644 (file)
@@ -14,25 +14,37 @@ typedef struct Da{
 #define RETURN(dap, r)                      \
   { da_map(dap, da_free, NULL); return r; }
 
+
 void da_alloc(Da *dap, size_t element_size);
 void da_free(Da *dap);
 void da_rewind(Da *dap);
 bool da_emptyq(Da *dap);
 size_t da_length(Da *dap);
-char *da_expand(Da *dap);
 void da_rebase(Da *dap, char *old_base, void *pta);
-bool da_endq(Da *dap, void *pt);
+char *da_expand(Da *dap);
 bool da_boundq(Da *dap);
+
+char *da_index(Da *dap, size_t i);
 void da_push(Da *dap, void *element);
 bool da_pop(Da *dap, void *element);
-void da_cat(Da *dap_base, Da *dap_cat);
-void da_push_string(Da *dap0, char *string);
-char *da_index(Da *dap, size_t i);
+
+bool da_endq(Da *dap, void *pt);
 void da_map(Da *dap, void f(void *, void *), void *closure);
+
 void da_free_elements(Da *dap);
-void da_strings_puts(Da *dap);
-void da_ints_print(Da *dap);
-char *da_fgets(Da *dap, FILE *fd);
+
+void da_ints_print(Da *dap, char *sep);
+
+void da_strings_print(Da *dap, char *sep);
+bool da_strings_exists(Da *string_arrp, char *test_string);
+void da_strings_set_insert(Da *string_arrp, char *proffered_string, void destruct(void *));
+void da_strings_set_union(Da *string_arrp, Da *proffered_string_arrp, void destruct(void *));
+
+
+char *da_string_input(Da *dap, FILE *file);
+void da_string_push(Da *dap0, char *string);
+
+void da_cat(Da *dap_base, Da *dap_cat);
 
 #endif
 
diff --git a/module/da/test/results b/module/da/test/results
deleted file mode 100644 (file)
index 9e59b33..0000000
+++ /dev/null
@@ -1 +0,0 @@
-passed all 4 tests
index f16be66..12f06d2 100644 (file)
@@ -84,19 +84,19 @@ bool test_da_2(){
   Da da;
   da_alloc(&da, sizeof(char));
 
-  da_fgets(&da, file);
+  da_string_input(&da, file);
   bool f0 = !strcmp(da.base, "this is a test");
 
   char *old_base;
   da_pop(&da, NULL); // pop the prior null terminator
   char *s1 = da.end;
-  old_base = da_fgets(&da,file);
+  old_base = da_string_input(&da,file);
   da_rebase(&da, old_base, &s1);
   bool f1 = !strcmp(s1, "ends without a newline");
   
   da_pop(&da, NULL); // pop the prior null terminator
   char *s2 = da.end;
-  old_base = da_fgets(&da,file);
+  old_base = da_string_input(&da,file);
   da_rebase(&da, old_base, &s2);
   bool f2 = !strcmp(s2, "(setq mode-require-final-newline nil)");
 
diff --git a/module/da/test/try/passed.transcript b/module/da/test/try/passed.transcript
new file mode 100644 (file)
index 0000000..d75d376
--- /dev/null
@@ -0,0 +1,5 @@
+2019-03-31T20:08:48Z
+morpheus@manorhouse§~/subu_land/subu/module/da/test/exec§
+> ./test_da
+passed all 5 tests
+
diff --git a/module/db/0_makefile b/module/db/0_makefile
deleted file mode 100644 (file)
index f0708ef..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-# src/0_makefile
-
-SHELL=/bin/bash
-
--include 0_makefile_flags
-
-SUID_TOOL=$(TOOLSDIR)/bin/setuid_root.sh
-MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tools/lib/makefile-cc
-
-SOURCES=$(wildcard *.c)
-HFILES=$(wildcard *.h)
-
-all: version deps lib execs
-
-version:
-       $(MAKE) $@
-       @echo "SUID_TOOL: " $(SUID_TOOL)
-
-deps:
-       makeheaders $(SOURCES) $(HFILES)
-       sed -i '/^ *int *main *(.*)/d' *.h
-       $(MAKE) $@
-
-execs:
-       $(MAKE) $@
-       @echo "-> $(SUID_TOOL) $(EXECSDIR)/subu-mk-0 $(EXECSDIR)/subu-rm-0 $(EXECSDIR)/subu-bind-all"
-       cat $(SUID_TOOL)
-       @echo -n "Are you sure? [y/N] " && read ans && [ $${ans:-N} == y ]
-       sudo $(SUID_TOOL) $(EXECSDIR)/subu-mk-0 $(EXECSDIR)/subu-rm-0 $(EXECSDIR)/subu-bind-all
-
-clean:
-       $(MAKE) $@
-       for i in $(HFILES); do rm $$i; done
-
-%::
-       $(MAKE) $@
-
-
-
-
diff --git a/module/db/0_makefile-flags b/module/db/0_makefile-flags
deleted file mode 100644 (file)
index d4df01f..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-
-# some versions of Linux need a -e option others complain if there is a -e .. and it isn't the binary for echo ..
-ECHO= echo
-#ECHO= echo -e
-
-# directories used by this makefile, these could all be set to dot for
-# the simplest source directory structure
-
-#LIDBIR, EXECSDIR, HDIR hold the make results that might later be shared
-#$(PWD) is the directory that make was called from, this is already build in
-#set to dot to use the same directory as the source code
-#leave blank to ommit
-DEPRDIR=1_deprecated
-DOCDIR=1_doc
-EXECSDIR=1_execs
-HDIR=1_headers
-LIBDIR=1_lib
-TESTDIR=1_tests
-TMPDIR=1_tmp
-TOOLSDIR=$(realpath $(PROJECT_SUBU)/tools)
-TRYDIR=1_try
-
-
-# compiler and flags
-CC=gcc
-CFLAGS=-std=gnu11 -fPIC -I. -ggdb -Werror -DDEBUG -DDEBUGDB 
-#CFLAGS=-std=gnu11 -fPIC -I. -Werror
-LINKFLAGS=-L1_lib -lsubu -lsqlite3
-
-LIBFILE=$(LIBDIR)/libsubu.a
-
diff --git a/module/db/1_doc/return-from-transaction.txt b/module/db/1_doc/return-from-transaction.txt
deleted file mode 100644 (file)
index b7f8cbb..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-
-1.
-  This sql:
-
-    char *sql = 
-      "BEGIN TRANSACTION;"
-      "UPDATE Key_Int SET value = value + 1 WHERE key = 'max_subu_number';"
-      "SELECT value FROM Key_Int WHERE key = 'max_subu_number';"
-      "COMMIT;"
-      ;
-
-  with sqlite_exec, the call back is called with the data from the select.
-
-  with sqlite_prepare_v2, sqlite_step just returns SQLITE_DONE, and we never
-  get to see our data from the select.
diff --git a/module/db/dbprintf.lib.c b/module/db/dbprintf.lib.c
deleted file mode 100644 (file)
index d9d236b..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-
-#include "dbprintf.lib.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-
-int dbprintf(const char *format, ...){
-  va_list args;
-  va_start(args,format);  
-  int ret = vfprintf(stdout, format, args);
-  fflush(stdout);
-  va_end(args);
-  return ret;
-}
diff --git a/module/db/include/db.h b/module/db/include/db.h
new file mode 100644 (file)
index 0000000..7563eea
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef DB_LIB_H
+#define DB_LIB_H
+
+int dbprintf(const char *format, ...);
+
+#endif
diff --git a/module/db/lib/libda.a b/module/db/lib/libda.a
new file mode 100644 (file)
index 0000000..c6e819f
Binary files /dev/null and b/module/db/lib/libda.a differ
diff --git a/module/db/lib/libdb.a b/module/db/lib/libdb.a
new file mode 100644 (file)
index 0000000..bf6ce01
Binary files /dev/null and b/module/db/lib/libdb.a differ
diff --git a/module/db/makefile b/module/db/makefile
new file mode 100644 (file)
index 0000000..167b997
--- /dev/null
@@ -0,0 +1,23 @@
+# da/makefile
+
+
+SHELL=/bin/bash
+MAKE=/usr/bin/make --no-print-directory -f $(PROJECT_SUBU)/tool/lib/makefile-cc
+#MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tool/lib/makefile-cc
+
+-include makefile-flags
+
+.PHONY: all
+all: version dep lib exec
+
+.PHONY: lib
+lib:
+       $(MAKE) $@
+       cp src/db.lib.h include/db.h
+
+%::
+       $(MAKE) $@
+
+
+
+
diff --git a/module/db/makefile-flags b/module/db/makefile-flags
new file mode 100644 (file)
index 0000000..f37c595
--- /dev/null
@@ -0,0 +1,18 @@
+
+MODULE=db
+
+# some versions of Linux need a -e option others complain if there is a -e .. and it isn't the binary for echo ..
+ECHO= echo
+#ECHO= echo -e
+
+# directories used by this makefile, these could all be set to dot for
+# the simplest source directory structure
+
+# compiler and flags
+C=gcc
+CFLAGS=-std=gnu11 -fPIC -I. -ggdb -Werror -DDEBUG -DDEBUGDB 
+#CFLAGS=-std=gnu11 -fPIC -I. -Werror
+LINKFLAGS=-Llib -ldb
+
+
+
diff --git a/module/db/src/db.lib.c b/module/db/src/db.lib.c
new file mode 100644 (file)
index 0000000..8e6fe5d
--- /dev/null
@@ -0,0 +1,14 @@
+
+#include "db.lib.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+int dbprintf(const char *format, ...){
+  va_list args;
+  va_start(args,format);  
+  int ret = vfprintf(stdout, format, args);
+  fflush(stdout);
+  va_end(args);
+  return ret;
+}
diff --git a/module/db/src/db.lib.h b/module/db/src/db.lib.h
new file mode 100644 (file)
index 0000000..7563eea
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef DB_LIB_H
+#define DB_LIB_H
+
+int dbprintf(const char *format, ...);
+
+#endif
index 48cadc2..eb127fc 100644 (file)
@@ -1,4 +1,6 @@
 
+MODULE=dispatch
+
 # some versions of Linux need a -e option others complain if there is a -e .. and it isn't the binary for echo ..
 ECHO= echo
 #ECHO= echo -e
@@ -13,8 +15,9 @@ CFLAGS=-std=gnu11 -fPIC -I. -ggdb -Werror -DDEBUG -DDEBUGDB
 
 LINKFLAGS=-L1_lib -lda 
 
-MODULE=dispatch
+SRCDIR=tmp
+TRCDIR=trc
 
-MAKE=/usr/bin/make --no-print-directory -f $(PROJECT_SUBU)/tools/lib/makefile_trc
-#MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tools/lib/makefile_trc
+MAKE=/usr/bin/make --no-print-directory -f $(PROJECT_SUBU)/tool/lib/makefile-cc
+#MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tool/lib/makefile-cc
 
diff --git a/module/dispatch/src/dispatch.lib.c b/module/dispatch/src/dispatch.lib.c
deleted file mode 100644 (file)
index e34d020..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-#tranche tmp/dispatch.trc.c
-
-#tranche include/dispatch.h
-/*
-  Runs a command or function as its own process.
-
-  The return status integer from command or function must be greater than ERR_DISPATCH.
-  In the case of dispatch_exec, we only have a promise from the user to not dispatch
-  non compliant commands.
-
-*/
-#ifndef DISPATCH_LIB_H
-#define DISPATCH_LIB_H
-#include <sys/types.h>
-#include <unistd.h>
-
-#define ERR_DISPATCH -1024
-#define ERR_DISPATCH_NEGATIVE_RETURN_STATUS -1024
-#define ERR_DISPATCH_F_FORK -1025
-#define ERR_DISPATCH_F_SETEUID -1026
-#define ERR_DISPATCH_F_SETEGID -1027
-#define ERR_DISPATCH_NULL_EXECUTABLE -1028
-#define ERR_DISPATCH_EXEC -1029
-
-// currently both dispatcher and dispatchee strings are statically allocated
-struct dispatch_ctx{
-  char *dispatcher; // name of the dispatch function ("dispatch_f", "dispatch_f_euid_egid", etc.)
-  char *dispatchee; // name of the function being dispatched
-  int err; // error code as listed below, or status returned from dispatchee
-};
-#tranche-end
-
-#include "dispatch.h"
-
-// we need the declaration for uid_t etc.
-// without this #define execvpe is undefined
-#define _GNU_SOURCE   
-
-#include <wait.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-
-#tranche include/dispatch.h
-void dispatch_f_mess(char *fname, int err, char *dispatchee);
-#tranche-end
-void dispatch_f_mess(char *fname, int err, char *dispatchee){
-  if(err == 0) return;
-  fprintf(stderr, "%s: ", fname); // if fprintf gets an error, errno will be overwritten
-  if(err > ERR_DISPATCH){
-    fprintf(stderr, "dispatchee \"%s\" returned the error %d\n", dispatchee, err);
-    return;
-  }
-  switch(err){
-  case ERR_DISPATCH_NEGATIVE_RETURN_STATUS:
-    fprintf(stderr, " dispatchee \"%s\" returned a negative status.", dispatchee);
-    break;
-  case ERR_DISPATCH_F_FORK:
-  case ERR_DISPATCH_F_SETEUID:
-  case ERR_DISPATCH_F_SETEGID:
-    fputc(' ', stderr);
-    perror(dispatchee);
-    break;
-  case ERR_DISPATCH_NULL_EXECUTABLE:
-    fprintf(stderr, " executable was not specified");
-    break;
-  case ERR_DISPATCH_EXEC:
-    // exec is running in another process when it fails, so we can't see the errno value it set
-    fprintf(stderr, " exec of \"%s\" failed", dispatchee);
-    break;
-  default:
-    fprintf(stderr, " returned undefined status when dispatching \"%s\"", dispatchee);
-  }
-  fputc('\n', stderr);
-}
-
-//--------------------------------------------------------------------------------
-// interface call point, dispatch a function
-#tranche include/dispatch.h
-int dispatch_f(char *fname, int (*f)(void *arg), void *f_arg);
-#tranche-end
-int dispatch_f(char *fname, int (*f)(void *arg), void *f_arg){
-  #ifdef DEBUG
-  dbprintf("%s %s\n", "dispatch_f", fname);
-  #endif
-  pid_t pid = fork();
-  if( pid == -1 ) return ERR_DISPATCH_F_FORK; // something went wrong and we are still in the parent process
-  if( pid == 0 ){ // we are the child
-    int status = (*f)(f_arg); // we require that f return a zero or positive value
-    if( status < ERR_DISPATCH ) status = ERR_DISPATCH_NEGATIVE_RETURN_STATUS;
-    exit(status);
-  }else{ // we are the parent
-    int err;
-    waitpid(pid, &err, 0);
-    return err;
-  }
-}
-
-//--------------------------------------------------------------------------------
-// interface call point, dispatch a function with a given euid/egid
-// of course this will only work if our euid is root in the first place
-#tranche include/dispatch.h
-int dispatch_f_euid_egid(char *fname, int (*f)(void *arg), void *f_arg, uid_t euid, gid_t egid);
-#tranche-end
-int dispatch_f_euid_egid(char *fname, int (*f)(void *arg), void *f_arg, uid_t euid, gid_t egid){
-  #ifdef DEBUG
-  dbprintf("%s %s as euid:%u egid:%u\n", "dispatch_f_euid_egid", fname, euid, egid);
-  #endif
-  pid_t pid = fork();
-  if( pid == -1 ) return ERR_DISPATCH_F_FORK;
-  if( pid == 0 ){ // we are the child
-    int status;
-    if( seteuid(euid) == -1 )
-      status = ERR_DISPATCH_F_SETEUID;
-    else if( setegid(egid) == -1 )
-      status = ERR_DISPATCH_F_SETEGID;
-    else{
-      status = (*f)(f_arg);
-      if( status <= ERR_DISPATCH ) status = ERR_DISPATCH_NEGATIVE_RETURN_STATUS;
-      exit(status);
-    }
-  }else{ // we are the parent
-    uint err;
-    waitpid(pid, &err, 0);
-    return err;
-  }
-}
-
-//--------------------------------------------------------------------------------
-// interface call point, dispatch a executable
-#tranche include/dispatch.h
-int dispatch_exec(char **argv, char **envp);
-#tranche-end
-int dispatch_exec(char **argv, char **envp){
-  char *command;
-  {
-    if( !argv || !argv[0] ) return ERR_DISPATCH_NULL_EXECUTABLE;
-    #ifdef DEBUG
-      dbprintf("dispatch_exec:");
-      char **apt = argv;
-      while( *apt ){
-        dbprintf(" %s",*apt);
-        apt++;
-      }
-      dbprintf("\n");
-    #endif
-    command = argv[0];
-  }
-  pid_t pid = fork();
-  if( pid == -1 ) return ERR_DISPATCH_F_FORK; // something went wrong and we are still in the parent process
-  if( pid == 0 ){ // we are the child
-    execvpe(command, argv, envp); // exec will only return if it has an error
-    #ifdef DEBUG
-    dbprintf("dispatch_exec: exec returned, perror message:");
-    perror("dispatch_exec"); // our only chance to print this message, as this is the child process
-    #endif
-    fflush(stdout);
-    exit(ERR_DISPATCH_EXEC); 
-  }else{ // we are the parent
-    int err;
-    waitpid(pid, &err, 0);
-    return err;
-  }
-}
-
-#tranche-end
diff --git a/module/dispatch/trc/dispatch.trc.c b/module/dispatch/trc/dispatch.trc.c
new file mode 100644 (file)
index 0000000..3b594a7
--- /dev/null
@@ -0,0 +1,166 @@
+#tranche dispatch.lib.c
+
+#tranche dispatch.lib.h
+/*
+  Runs a command or function as its own process.
+
+  The return status integer from command or function must be greater than ERR_DISPATCH.
+  In the case of dispatch_exec, we only have a promise from the user to not dispatch
+  non compliant commands.
+
+*/
+#ifndef DISPATCH_LIB_H
+#define DISPATCH_LIB_H
+#include <sys/types.h>
+#include <unistd.h>
+
+#define ERR_DISPATCH -1024
+#define ERR_DISPATCH_NEGATIVE_RETURN_STATUS -1024
+#define ERR_DISPATCH_F_FORK -1025
+#define ERR_DISPATCH_F_SETEUID -1026
+#define ERR_DISPATCH_F_SETEGID -1027
+#define ERR_DISPATCH_NULL_EXECUTABLE -1028
+#define ERR_DISPATCH_EXEC -1029
+
+// currently both dispatcher and dispatchee strings are statically allocated
+struct dispatch_ctx{
+  char *dispatcher; // name of the dispatch function ("dispatch_f", "dispatch_f_euid_egid", etc.)
+  char *dispatchee; // name of the function being dispatched
+  int err; // error code as listed below, or status returned from dispatchee
+};
+#tranche-end
+
+#include "dispatch.h"
+
+// we need the declaration for uid_t etc.
+// without this #define execvpe is undefined
+#define _GNU_SOURCE   
+
+#include <wait.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#tranche dispatch.lib.h
+void dispatch_f_mess(char *fname, int err, char *dispatchee);
+#tranche-end
+void dispatch_f_mess(char *fname, int err, char *dispatchee){
+  if(err == 0) return;
+  fprintf(stderr, "%s: ", fname); // if fprintf gets an error, errno will be overwritten
+  if(err > ERR_DISPATCH){
+    fprintf(stderr, "dispatchee \"%s\" returned the error %d\n", dispatchee, err);
+    return;
+  }
+  switch(err){
+  case ERR_DISPATCH_NEGATIVE_RETURN_STATUS:
+    fprintf(stderr, " dispatchee \"%s\" returned a negative status.", dispatchee);
+    break;
+  case ERR_DISPATCH_F_FORK:
+  case ERR_DISPATCH_F_SETEUID:
+  case ERR_DISPATCH_F_SETEGID:
+    fputc(' ', stderr);
+    perror(dispatchee);
+    break;
+  case ERR_DISPATCH_NULL_EXECUTABLE:
+    fprintf(stderr, " executable was not specified");
+    break;
+  case ERR_DISPATCH_EXEC:
+    // exec is running in another process when it fails, so we can't see the errno value it set
+    fprintf(stderr, " exec of \"%s\" failed", dispatchee);
+    break;
+  default:
+    fprintf(stderr, " returned undefined status when dispatching \"%s\"", dispatchee);
+  }
+  fputc('\n', stderr);
+}
+
+//--------------------------------------------------------------------------------
+// interface call point, dispatch a function
+#tranche dispatch.lib.h
+int dispatch_f(char *fname, int (*f)(void *arg), void *f_arg);
+#tranche-end
+int dispatch_f(char *fname, int (*f)(void *arg), void *f_arg){
+  #ifdef DEBUG
+  dbprintf("%s %s\n", "dispatch_f", fname);
+  #endif
+  pid_t pid = fork();
+  if( pid == -1 ) return ERR_DISPATCH_F_FORK; // something went wrong and we are still in the parent process
+  if( pid == 0 ){ // we are the child
+    int status = (*f)(f_arg); // we require that f return a zero or positive value
+    if( status < ERR_DISPATCH ) status = ERR_DISPATCH_NEGATIVE_RETURN_STATUS;
+    exit(status);
+  }else{ // we are the parent
+    int err;
+    waitpid(pid, &err, 0);
+    return err;
+  }
+}
+
+//--------------------------------------------------------------------------------
+// interface call point, dispatch a function with a given euid/egid
+// of course this will only work if our euid is root in the first place
+#tranche dispatch.lib.h
+int dispatch_f_euid_egid(char *fname, int (*f)(void *arg), void *f_arg, uid_t euid, gid_t egid);
+#tranche-end
+int dispatch_f_euid_egid(char *fname, int (*f)(void *arg), void *f_arg, uid_t euid, gid_t egid){
+  #ifdef DEBUG
+  dbprintf("%s %s as euid:%u egid:%u\n", "dispatch_f_euid_egid", fname, euid, egid);
+  #endif
+  pid_t pid = fork();
+  if( pid == -1 ) return ERR_DISPATCH_F_FORK;
+  if( pid == 0 ){ // we are the child
+    int status;
+    if( seteuid(euid) == -1 )
+      status = ERR_DISPATCH_F_SETEUID;
+    else if( setegid(egid) == -1 )
+      status = ERR_DISPATCH_F_SETEGID;
+    else{
+      status = (*f)(f_arg);
+      if( status <= ERR_DISPATCH ) status = ERR_DISPATCH_NEGATIVE_RETURN_STATUS;
+      exit(status);
+    }
+  }else{ // we are the parent
+    uint err;
+    waitpid(pid, &err, 0);
+    return err;
+  }
+}
+
+//--------------------------------------------------------------------------------
+// interface call point, dispatch a executable
+#tranche dispatch.lib.h
+int dispatch_exec(char **argv, char **envp);
+#tranche-end
+int dispatch_exec(char **argv, char **envp){
+  char *command;
+  {
+    if( !argv || !argv[0] ) return ERR_DISPATCH_NULL_EXECUTABLE;
+    #ifdef DEBUG
+      dbprintf("dispatch_exec:");
+      char **apt = argv;
+      while( *apt ){
+        dbprintf(" %s",*apt);
+        apt++;
+      }
+      dbprintf("\n");
+    #endif
+    command = argv[0];
+  }
+  pid_t pid = fork();
+  if( pid == -1 ) return ERR_DISPATCH_F_FORK; // something went wrong and we are still in the parent process
+  if( pid == 0 ){ // we are the child
+    execvpe(command, argv, envp); // exec will only return if it has an error
+    #ifdef DEBUG
+    dbprintf("dispatch_exec: exec returned, perror message:");
+    perror("dispatch_exec"); // our only chance to print this message, as this is the child process
+    #endif
+    fflush(stdout);
+    exit(ERR_DISPATCH_EXEC); 
+  }else{ // we are the parent
+    int err;
+    waitpid(pid, &err, 0);
+    return err;
+  }
+}
+
+#tranche-end
index 3188011..518e72c 100644 (file)
@@ -14,25 +14,37 @@ typedef struct Da{
 #define RETURN(dap, r)                      \
   { da_map(dap, da_free, NULL); return r; }
 
+
 void da_alloc(Da *dap, size_t element_size);
 void da_free(Da *dap);
 void da_rewind(Da *dap);
 bool da_emptyq(Da *dap);
 size_t da_length(Da *dap);
-char *da_expand(Da *dap);
 void da_rebase(Da *dap, char *old_base, void *pta);
-bool da_endq(Da *dap, void *pt);
+char *da_expand(Da *dap);
 bool da_boundq(Da *dap);
+
+char *da_index(Da *dap, size_t i);
 void da_push(Da *dap, void *element);
 bool da_pop(Da *dap, void *element);
-void da_cat(Da *dap_base, Da *dap_cat);
-void da_push_string(Da *dap0, char *string);
-char *da_index(Da *dap, size_t i);
+
+bool da_endq(Da *dap, void *pt);
 void da_map(Da *dap, void f(void *, void *), void *closure);
+
 void da_free_elements(Da *dap);
-void da_strings_puts(Da *dap);
-void da_ints_print(Da *dap);
-char *da_fgets(Da *dap, FILE *fd);
+
+void da_ints_print(Da *dap, char *sep);
+
+void da_strings_print(Da *dap, char *sep);
+bool da_strings_exists(Da *string_arrp, char *test_string);
+void da_strings_set_insert(Da *string_arrp, char *proffered_string, void destruct(void *));
+void da_strings_set_union(Da *string_arrp, Da *proffered_string_arrp, void destruct(void *));
+
+
+char *da_string_input(Da *dap, FILE *file);
+void da_string_push(Da *dap0, char *string);
+
+void da_cat(Da *dap_base, Da *dap_cat);
 
 #endif
 
index 595690a..a3da46e 100644 (file)
Binary files a/module/share/lib/libda.a and b/module/share/lib/libda.a differ
index 651e98b..18f8fc7 100644 (file)
@@ -17,7 +17,7 @@ exec:
        $(MAKE) $@
 
 share:
-       if [ ! -z "$(wildcard $(EXECDIR)/*)" ]; then cp $(EXECDIR)/* $(PROJECT_SUBU)/tool/bin; fi
+       if [ -d $(EXECDIR) ]; then if [ ! -z "$(wildcard $(EXECDIR)/*)" ]; then cp $(EXECDIR)/* $(PROJECT_SUBU)/tool/bin; fi; fi
 
 %::
        $(MAKE) $@
index bb0340e..cd54223 100644 (file)
@@ -6,6 +6,7 @@ ECHO= echo
 
 # directories used by this makefile, these could all be set to dot for
 # the simplest source directory structure
+EXECDIR=exec
 
 C=gcc
 CFLAGS=-std=gnu11 -fPIC -I. -I../share/include -ggdb -Werror -DDEBUG -DDEBUGDB 
index 5faf31f..bfe9d9b 100644 (file)
@@ -38,31 +38,36 @@ user does not want this behavior, give a value of "." for -sdir.
 
 int main(int argc, char **argv, char **envp){
 
-  char *src_file_path = 0;
+  int err = 0;
   char *sname = 0;
   char *tdir = 0;  
   char *mfile_path = 0; 
-
+  Da args; // we will queue the non option args here
+  Da *argsp = &args; // collection of the non-option non-option-value args
+  da_alloc(argsp, sizeof(char *));
   { // argument parse
-    Da args; // we will queue the non option args here
-    Da *argsp = &args;
-    da_alloc(argsp, sizeof(char *));
-
-    int err_cnt = 0;
-    char **pt = argv;
+    char **pt = argv + 1; // skip the command name
     char *option;
     char *value; // currently all our tranche options have exactly one value
     while(*pt){
       if( **pt == '-' ){
         option = *pt + 1;
+
+        // options that take no values:
         if(!*option){
           fprintf(stderr, "Currently there is no lone '-' option.\n");
-          err_cnt++;
+          err |= TRANCHE_ERR_ARG_PARSE;
           goto endif;
         }
+        if( !strcmp(option, "h") || !strcmp(option, "help") ){
+          err |= TRANCHE_ERR_HELP; // this will force the usage message, though it will also return an error
+          goto endif;
+        }
+
+        // options that take one value:
         pt++; if(!*pt || **pt == '-'){
           fprintf(stderr, "Missing value for option %s.\n", option);
-          err_cnt++;
+          err |= TRANCHE_ERR_ARG_PARSE;
           if(!*pt) break; // then nothing more to parse
           goto endif;
         }
@@ -73,6 +78,7 @@ int main(int argc, char **argv, char **envp){
         }
         if( !strcmp(option, "tdir") ){
           tdir = value;
+          path_trim_slashes(tdir);
           goto endif;
         }
         if( !strcmp(option, "sname") ){
@@ -80,72 +86,69 @@ int main(int argc, char **argv, char **envp){
           goto endif;
         }
         fprintf(stderr, "Unrecognized option %s.", option);
-        err_cnt++;
+        err |= TRANCHE_ERR_ARG_PARSE;
         goto endif;
       }
       // else clause
       da_push(argsp, pt);
     endif:
-    pt++;
+      pt++;
     }
-    int args_cnt = da_length(argsp);
-    if(args_cnt > 1) src_file_path = *(char **)da_index(argsp, 1);
-
-    // arg contracts
-    if(args_cnt > 2){
-      fprintf(stderr, "too many args\n");
-      err_cnt++;
-    }
-    if(!src_file_path && !sname){
-      fprintf(stderr, "must specify at least one of a src_file_path or an sname\n");
-      err_cnt++;
+    if(da_emptyq(argsp) && !sname){
+      fprintf(stderr, "Must be given at least one source name argument or an sname option\n");
+      err |= TRANCHE_ERR_SNAME;
     }
-    if(err_cnt > 0){
-      fprintf(stderr, "usage: %s [<src_file_path>] [-sname <sname>] [-tdir <dir>] [-mfile <mfile_path>]\n", argv[0]);
-      return TRANCHE_ERR_ARG_PARSE;
+    if(err){
+      fprintf(stderr, "usage: %s [<src_file_path>].. [-sname <sname>] [-tdir <dir>]\n", argv[0]);
+      return err;
     }
-    da_free(argsp); // this only frees the array itself, not the things it points to
-
   }// end of argument parse
  
-  FILE *src_file;
+  // open the output file
   int mfile_fd;
-  { //source and mfile open
-    if(!src_file_path)
-      src_file = stdin;
-    else
-      src_file = fopen(src_file_path, "r");
-
+  {
     if(mfile_path)
       mfile_fd = open(mfile_path, O_WRONLY | O_APPEND | O_CREAT, 0666);
     else
       mfile_fd = STDOUT_FILENO;
 
-    int err = 0;
-    if(!src_file){
-      fprintf(stderr,"could not open tranche source file %s\n", src_file_path);
-      err+= TRANCHE_ERR_SRC_OPEN;
-    }
     if(mfile_fd == -1){
       fprintf(stderr, "Could not open the dep file %s\n", mfile_path);
-      err+= TRANCHE_ERR_DST_OPEN;
+      err |= TRANCHE_ERR_DST_OPEN;
     }
-    if(err) return err;
   }
 
-  if(sname)src_file_path = sname;
-  path_trim_slashes(tdir);
-  tranche_make(src_file, src_file_path,  mfile_fd, tdir);
+  // The arguments are source file paths, but we process each one only once.
+  Da src_arr;
+  Da *src_arrp = &src_arr;
+  da_alloc(src_arrp, sizeof(char *));
+  da_strings_set_union(src_arrp, argsp, NULL); // NULL destructor
+  da_free(argsp);
 
-  { // deallocate resources instead of just existing, so as to catch any errors
-    int err_cnt = 0;
-    if(src_file != stdin)
-      if( fclose(src_file) ){perror(NULL); err_cnt++;}
-    if(mfile_fd != STDOUT_FILENO)
-      if( close(mfile_fd) == -1 ){perror(NULL); err_cnt++;}
-    if( err_cnt )
-      return TRANCHE_ERR_FCLOSE;
-    else
-      return 0;
+  char *src_file_path;
+  FILE *src_file;
+  if(da_emptyq(src_arrp))
+    tranche_make(stdin, sname,  mfile_fd, tdir);
+  else{
+    char *pt = src_arrp->base;
+    while( pt < src_arrp->end ){
+      src_file_path = *(char **)pt;
+      src_file = fopen(src_file_path, "r");
+      if(!src_file){
+        fprintf(stderr,"Could not open source file %s.\n", src_file_path);
+        err |= TRANCHE_ERR_SRC_OPEN;
+      }else{
+        tranche_make(src_file, src_file_path,  mfile_fd, tdir);
+        if( fclose(src_file) == -1 ){perror(NULL); err |= TRANCHE_ERR_FCLOSE;}
+      }
+    pt += src_arrp->element_size;
+    }
+  }
+  da_free(src_arrp);
+
+  if(mfile_fd != STDOUT_FILENO && close(mfile_fd) == -1 ){
+    perror(NULL); 
+    err |= TRANCHE_ERR_FCLOSE;
   }
+  return err;
 }
index b579e88..c216534 100644 (file)
@@ -9,6 +9,7 @@ between blank lines being sent and text being sent to stdout.
   
 #include <stdio.h>
 #include <unistd.h>
+#include <string.h>
 #include <da.h>
 #include "tranche.lib.h"
 
@@ -17,27 +18,94 @@ between blank lines being sent and text being sent to stdout.
 
 
 int main(int argc, char **argv, char **envp){
-  if(argc != 2){
-    fprintf(stderr, "usage: %s <source>\n",argv[0]);
-    return ERR_ARGC;
-  }
-  char *src_file_name = argv[1];
-
-  int dep_fd;
-  FILE *src_file = fopen(src_file_name, "r");
-  unsigned int err = 0;
-  if(!src_file){
-    fprintf(stderr,"could not open tranche source file %s\n", src_file_name);
-    err+= ERR_SRC_OPEN;
-  }
-  if(err) return err;
 
+  int err = 0;
+  char *sep = 0;
+  Da args; // we will queue the non option args here
+  Da *argsp = &args; // collection of the non-option non-option-value args
+  da_alloc(argsp, sizeof(char *));
+  { // argument parse
+    char **pt = argv + 1; // skip the command name
+    char *option;
+    char *value; // currently all our tranche options have exactly one value
+    while(*pt){
+      if( **pt == '-' ){
+        option = *pt + 1;
+
+        // options that take no values:
+        if(!*option){
+          fprintf(stderr, "Currently there is no lone '-' option.\n");
+          err |= TRANCHE_ERR_ARG_PARSE;
+          goto endif;
+        }
+        if( !strcmp(option, "h") || !strcmp(option, "help") ){
+          err |= TRANCHE_ERR_HELP; // this will force the usage message, though it will also return an error
+          goto endif;
+        }
+
+        // options that take one value:
+        pt++; if(!*pt || **pt == '-'){
+          fprintf(stderr, "Missing value for option %s.\n", option);
+          err |= TRANCHE_ERR_ARG_PARSE;
+          if(!*pt) break; // then nothing more to parse
+          goto endif;
+        }
+        value = *pt;
+        if( !strcmp(option, "sep") ){
+          sep = value;
+          goto endif;
+        }
+        fprintf(stderr, "Unrecognized option %s.", option);
+        err |= TRANCHE_ERR_ARG_PARSE;
+        goto endif;
+      }
+      // else clause
+      da_push(argsp, pt);
+    endif:
+    pt++;
+    }
+    if(!sep)sep = "\n";
+    if(err){
+      fprintf(stderr, "usage: %s [<src_file_path>].. [-sep <sep>]\n", argv[0]);
+      return err;
+    }
+  }// end of argument parse
+
+  // The arguments are source file paths, but we process each one only once.
+  Da src_arr;
+  Da *src_arrp = &src_arr;
+  da_alloc(src_arrp, sizeof(char *));
+  da_strings_set_union(src_arrp, argsp, NULL); // NULL destructor
+  da_free(argsp);
+
+  // a list of unique targets
   Da target_arr;
   Da *target_arrp = &target_arr;
   da_alloc(target_arrp, sizeof(char *));
-  tranche_target(src_file, target_arrp);
-  da_strings_puts(target_arrp);
+
+  uint err_cnt = 0;
+  char *src_file_path;
+  FILE *src_file;
+  if(da_emptyq(src_arrp))
+    tranche_target(stdin, target_arrp);
+  else{
+    char *pt = src_arrp->base;
+    while( pt < src_arrp->end ){
+      src_file_path = *(char **)pt;
+      src_file = fopen(src_file_path, "r");
+      if(!src_file){
+        fprintf(stderr,"Could not open source file %s.\n", src_file_path);
+        err |= TRANCHE_ERR_SRC_OPEN;
+      }else{
+        tranche_target(src_file, target_arrp);
+        if( fclose(src_file) == -1 ){perror(NULL); err |= TRANCHE_ERR_FCLOSE;}
+      }
+    pt += src_arrp->element_size;
+    }
+  }
+  da_free(src_arrp);
+  da_strings_print(target_arrp, sep);
   da_free_elements(target_arrp);
-  fclose(src_file);
-  return 0;
+  da_free(target_arrp);
+  return err;
 }
index a0fe798..597a191 100644 (file)
@@ -19,7 +19,6 @@ the tranche output files before running tranche a second time.
 .. currently tranche_send will probably mess up if the user nests a tranche to
 the same file as one already open in the containing tranche ..
 
-.. should allow multiple source file args
 */
   
 #include <stdio.h>
@@ -29,29 +28,35 @@ the same file as one already open in the containing tranche ..
 #include "tranche.lib.h"
 
 int main(int argc, char **argv, char **envp){
-  char *src_file_path = 0;
-  char *tdir = 0;  
 
+  int err = 0;
+  char *tdir = 0;  
+  Da args; // we will queue the non option args here
+  Da *argsp = &args; // collection of the non-option non-option-value args
+  da_alloc(argsp, sizeof(char *));
   { // argument parse
-    Da args; // we will queue the non option args here
-    Da *argsp = &args;
-    da_alloc(argsp, sizeof(char *));
-
-    int err_cnt = 0;
-    char **pt = argv;
+    char **pt = argv + 1; // skip the command name
     char *option;
     char *value; // currently all our tranche options have exactly one value
     while(*pt){
       if( **pt == '-' ){
         option = *pt + 1;
+
+        // options that take no values:
         if(!*option){
           fprintf(stderr, "Currently there is no lone '-' option.\n");
-          err_cnt++;
+          err |= TRANCHE_ERR_ARG_PARSE;
+          goto endif;
+        }
+        if( !strcmp(option, "h") || !strcmp(option, "help") ){
+          err |= TRANCHE_ERR_HELP; // this will force the usage message, though it will also return an error
           goto endif;
         }
+
+        // options that take one value:
         pt++; if(!*pt || **pt == '-'){
           fprintf(stderr, "Missing value for option %s.\n", option);
-          err_cnt++;
+          err |= TRANCHE_ERR_ARG_PARSE;
           if(!*pt) break; // then nothing more to parse
           goto endif;
         }
@@ -61,7 +66,7 @@ int main(int argc, char **argv, char **envp){
           goto endif;
         }
         fprintf(stderr, "Unrecognized option %s.", option);
-        err_cnt++;
+        err |= TRANCHE_ERR_ARG_PARSE;
         goto endif;
       }
       // else clause
@@ -69,46 +74,46 @@ int main(int argc, char **argv, char **envp){
     endif:
     pt++;
     }
-    int args_cnt = da_length(argsp);
-    if(args_cnt > 1) src_file_path = *(char **)da_index(argsp, 1);
-
-    // arg contracts
-    if(args_cnt > 2){
-      fprintf(stderr, "too many arguments\n");
-      err_cnt++;
-    }
-    if(err_cnt > 0){
-      fprintf(stderr, "usage: %s [<src_file_path>] [-tdir <dir>]\n", argv[0]);
-      return TRANCHE_ERR_ARG_PARSE;
+    if(err){
+      fprintf(stderr, "usage: %s [<src_file_path>].. [-tdir <dir>]\n", argv[0]);
+      return err;
     }
-    da_free(argsp); // this only frees the array itself, not the things it points to
-
   }// end of argument parse
 
-  FILE *src_file;
-  { //source and mfile open
-    if(!src_file_path)
-      src_file = stdin;
-    else
-      src_file = fopen(src_file_path, "r");
-
-    int err = 0;
-    if(!src_file){
-      fprintf(stderr,"could not open tranche source file %s\n", src_file_path);
-      err+= TRANCHE_ERR_SRC_OPEN;
-    }
-    if(err) return err;
-  }
-
   Da targets;
-  da_alloc(&targets, sizeof(int));
+  Da *target_arrp = &targets;
+  da_alloc(target_arrp, sizeof(int));
   int fd = STDOUT_FILENO;
-  da_push(&targets, &fd);
+  da_push(target_arrp, &fd);
   if(tdir)chdir(tdir);
 
-  tranche_send(src_file, &targets);
+  Da src_arr;
+  Da *src_arrp = &src_arr;
+  da_alloc(src_arrp, sizeof(char *));
+  da_strings_set_union(src_arrp, argsp, NULL);
+  da_free(argsp);
+
+  char *src_file_path;
+  FILE *src_file;
+  if(da_emptyq(src_arrp))
+    tranche_send(stdin, target_arrp);
+  else{
+    char *pt = src_arrp->base;
+    while( pt < src_arrp->end ){
+      src_file_path = *(char **)pt;
+      src_file = fopen(src_file_path, "r");
+      if(!src_file){
+        fprintf(stderr,"Could not open source file %s.\n", src_file_path);
+        err |= TRANCHE_ERR_SRC_OPEN;
+      }else{
+        tranche_send(src_file, target_arrp);
+        if( fclose(src_file) == -1 ){perror(NULL); err |= TRANCHE_ERR_FCLOSE;}
+      }
+    pt += src_arrp->element_size;
+    }
+  }
 
-  da_free(&targets);
-  fclose(src_file);
-  return 0;
+  da_free(target_arrp);
+  da_free(src_arrp);
+  return err;
 }
index aad290a..412e950 100644 (file)
@@ -95,7 +95,7 @@ int tranche_send(FILE *src, Da *arg_fdap){
   da_alloc(&fda, sizeof(int));
 
   while( !feof(src) ){
-    da_fgets(&line, src);
+    da_string_input(&line, src);
     if( is_tranche_end(line.base) ) break;
     pt = is_tranche_begin(line.base);
     if(pt){ // then this line is the start of a nested tranche block
@@ -122,47 +122,6 @@ int tranche_send(FILE *src, Da *arg_fdap){
 //--------------------------------------------------------------------------------
 // returns a list of unique target file names from a tranche source
 
-
-// return true if proffered test string is already in the strings array
-typedef struct {
-  char *string;
-  bool found;
-} string_state;
-static void string_equal(void *sp, void *closure){
-  char *string_element = *(char **)sp;
-  string_state *ss = (string_state *)closure;
-  if( ss->found ) return;
-  ss->found = !strcmp(string_element, ss->string);
-  return;
-}
-static bool exists(Da *string_arrp, char *test_string){
-  string_state ss;
-  ss.string = test_string;
-  ss.found = false;
-  da_map(string_arrp, string_equal, &ss);
-  return ss.found;
-}
-
-// only inserts the string if it is not already in the array
-static void insert_if_unique(Da *string_arrp, char *proffered_string){
-  if( exists( string_arrp, proffered_string)){ // then throw it away, we don't need it
-    free(proffered_string);
-    return;
-  }
-  da_push(string_arrp, &proffered_string);
-}
-
-// dissolves proffered array into the existing array
-static void combine_one(void *psp, void *closure){
-  char *proffered_string = *(char **)psp;
-  Da *string_arrp = (Da *)closure;
-  insert_if_unique(string_arrp, proffered_string);
-}
-static void combine(Da *string_arrp, Da *proffered_string_arrp){
-  da_map(proffered_string_arrp, combine_one, string_arrp);
-  return;
-}
-
 // make a list of the unique tranche target files found in src
 int tranche_target(FILE *src, Da *target_arrp){
   char *pt;
@@ -171,12 +130,12 @@ int tranche_target(FILE *src, Da *target_arrp){
   da_alloc(&line, sizeof(char));
   da_alloc(&file_name_arr, sizeof(char *));
   while( !feof(src) ){
-    da_fgets(&line, src);
+    da_string_input(&line, src);
     if( is_tranche_end(line.base) ) break;
     pt = is_tranche_begin(line.base);
     if(pt){ // then this line is the start of a nested tranche block
       parse_file_list(&file_name_arr, pt);
-      combine(target_arrp, &file_name_arr); // frees strings that are not inserted
+      da_strings_set_union(target_arrp, &file_name_arr, free);
       da_rewind(&file_name_arr);
       tranche_target(src, target_arrp);
     }
@@ -225,16 +184,16 @@ void tranche_make(FILE *src_file, char *src_name, int mfile_fd, char *tdir){
   char *pt = tap->base; // char * because it points to a byte in the array
   while( pt < tap->end ){
     if(tdir){
-      da_push_string(dlap, tdir);
+      da_string_push(dlap, tdir);
       da_push(dlap, &slash);
     }
-    da_push_string(dlap, *(char **)pt);
+    da_string_push(dlap, *(char **)pt);
     da_push(dlap, &sp);
   pt += tap->element_size;
   }
   da_push(dlap, &colon);
   da_push(dlap, &sp);
-  da_push_string(dlap, src_name);
+  da_string_push(dlap, src_name);
   da_push(dlap, &newline);
   write(mfile_fd, dlap->base, dlap->end - dlap->base);
   da_free_elements(tap);
@@ -243,10 +202,10 @@ void tranche_make(FILE *src_file, char *src_name, int mfile_fd, char *tdir){
   // output acction line ----------------------------------------
   da_rewind(dlap); // reuse the line buffer
   da_push(dlap, &tab);
-  da_push_string(dlap, "tranche $<");
+  da_string_push(dlap, "tranche $<");
   if(tdir){
-    da_push_string(dlap, " -tdir ");
-    da_push_string(dlap, tdir);
+    da_string_push(dlap, " -tdir ");
+    da_string_push(dlap, tdir);
   }
   da_push(dlap, &newline);
   da_push(dlap, &newline);
index c847765..d40c074 100644 (file)
@@ -5,6 +5,8 @@
 #define TRANCHE_ERR_SRC_OPEN 2
 #define TRANCHE_ERR_DST_OPEN 4
 #define TRANCHE_ERR_FCLOSE 8
+#define TRANCHE_ERR_HELP 16
+#define TRANCHE_ERR_SNAME 32
 
 void path_trim_slashes(char *path);
 int tranche_send(FILE *src, Da *arg_fds);
index 6ec2626..5959bbc 100644 (file)
@@ -3,6 +3,6 @@
 diff -q test2.c test2.c.expected
 diff -q test2.h test2.h.expected
 diff -q test2stdout.dat test2stdout.dat.expected
-rm test2.c test2.h
+rm test2.c test2.h test2stdout.dat.expected
 
 
diff --git a/module/tranche/test/try/test2stdout.dat.expected b/module/tranche/test/try/test2stdout.dat.expected
deleted file mode 100644 (file)
index 139597f..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/module/tranche/test/try/test5.sh b/module/tranche/test/try/test5.sh
new file mode 100644 (file)
index 0000000..284d01e
--- /dev/null
@@ -0,0 +1,13 @@
+./tranche test1.dat test2.trc.c
+
+diff -q test11.dat test11.dat.expected
+diff -q test12.dat test12.dat.expected
+diff -q test13.dat test13.dat.expected
+diff -q test14.dat test14.dat.expected
+diff -q test15.dat test15.dat.expected
+
+diff -q test2.c test2.c.expected
+diff -q test2.h test2.h.expected
+
+rm test11.dat test12.dat test13.dat test14.dat test15.dat
+rm test2.c test2.h
diff --git a/tool/bin/@System.solv b/tool/bin/@System.solv
new file mode 100644 (file)
index 0000000..1e89182
Binary files /dev/null and b/tool/bin/@System.solv differ
index 0682265..5489419 100755 (executable)
Binary files a/tool/bin/tranche and b/tool/bin/tranche differ
index 7c587c2..6ec278f 100755 (executable)
Binary files a/tool/bin/tranche-make and b/tool/bin/tranche-make differ
index 710e4c9..e315a2c 100755 (executable)
Binary files a/tool/bin/tranche-target and b/tool/bin/tranche-target differ
index d03d4e1..1265908 100755 (executable)
@@ -29,6 +29,10 @@ OBJECT_CLI= $(patsubst %, $(TMPDIR)/%.cli.o, $(C_BASE_CLI) $(CC_BASE_CLI))
 # executables are made from CLI sources
 EXEC= $(patsubst %, $(EXECDIR)/%, $(C_BASE_CLI) $(CC_BASE_CLI))
 
+# default directory seteup
+# For TRC projects define TRDIR (even if it is just '.'), and typically set SRCDIR to tmp
+#
+
 DEPRDIR=deprecated
 DOCDIR=doc
 EXECDIR=exec
@@ -39,8 +43,10 @@ SRCDIR=src
 TESTDIR=test
 TMPDIR=tmp
 TOOLDIR=$(realpath $(PROJECT_SUBU)/tool)
+TRCDIR=
 TRYDIR=try
 
+
 # a single space literal, for example if you wanted to subsitute commas to
 # spaces: $(subst $(space),;,$(string))
 blank :=
@@ -60,15 +66,25 @@ DEPFILE=$(TMPDIR)/makefile-cc.deps
 LIBFILE=$(LIBDIR)/lib$(MODULE).a
 INCFILE=$(INCDIR)/$(MODULE).h
 
+#--------------------------------------------------------------------------------
+# when local customizations set a TRCDIR, then these are the actual sources
+
+ifneq ($TRCDIR,)
+  TRCFILES= $(wildcard $(TRCDIR)/*.trc.c) $(wildcard $(TRCDIR)/*.trc.cc)
+else
+  TRCFILES=
+endif
+
+
 #--------------------------------------------------------------------------------
 # targets
 
 .PHONY: all
-all: version dep lib exec
+all: version
 
 .PHONY: version
 version:
-       @echo makefile version 4.0
+       @echo makefile version 5.0
        @echo "PWD: " $(PWD)
        @echo "MAKEFILE_LIST: " $(MAKEFILE_LIST)
        @echo "C: " $(C)
@@ -87,10 +103,13 @@ info:
        @echo "TESTDIR: " $(TESTDIR)
        @echo "TMPDIR: " $(TMPDIR)
        @echo "TOOLDIR: " $(TOOLDIR)
+       @echo "TRCDIR: " $(TRCDIR)
        @echo "TRYDIR: " $(TRYDIR)
        @echo "DEPFILE: " $(DEPFILE)
        @echo "LIBFILE: " $(LIBFILE)
        @echo "INCFILE: " $(INCFILE)
+       @echo "TRCFILES: " $(TRCFILES)
+       @echo "C_SOURCE_LIB: " $(C_SOURCE_LIB)
        @echo "C_SOURCE_LIB: " $(C_SOURCE_LIB)
        @echo "C_SOURCE_CLI: " $(C_SOURCE_CLI)
        @echo "CC_SOURCE_LIB: " $(CC_SOURCE_LIB)
@@ -104,43 +123,62 @@ info:
        @echo "EXEC: " $(EXEC)
 
 # should be safe to run this in an already setup or partially setup directory
+# gee looks like a candidate for a makefile function ..
 .PHONY: setup
 setup:
-       [ ! -e $(DEPRDIR) ] && mkdir $(DEPRDIR) || true
-       [ ! -e $(DOCDIR) ]  && mkdir $(DOCDIR)  || true
-       [ ! -e $(EXECDIR) ] && mkdir $(EXECDIR) || true
-       [ ! -e $(INCDIR) ]  && mkdir $(INCDIR)  || true
-       [ ! -e $(LIBDIR) ]  && mkdir $(LIBDIR)  || true
-       [ ! -e $(SRCDIR) ]  && mkdir $(SRCDIR)  || true
-       [ ! -e $(TESTDIR) ] && mkdir $(TESTDIR) || true
-       [ ! -e $(TMPDIR) ]  && mkdir $(TMPDIR)  || true
-       [ ! -e $(TRYDIR) ]  && mkdir $(TRYDIR)  || true
-
-#better to put the dependency generation into a loop on the source file and specify -MT for the target
-#also should be redirecting only stdout so stderr messages will be displayed >>1 depfile
+       [ ! -e $(DEPRDIR) ]  && mkdir $(DEPRDIR) || true
+       [ ! -e $(DOCDIR)  ]  && mkdir $(DOCDIR)  || true
+       [ ! -e $(EXECDIR) ]  && mkdir $(EXECDIR) || true
+       [ ! -e $(INCDIR)  ]  && mkdir $(INCDIR)  || true
+       [ ! -e $(LIBDIR)  ]  && mkdir $(LIBDIR)  || true
+       [ ! -e $(SRCDIR)  ]  && mkdir $(SRCDIR)  || true
+       [ ! -e $(TESTDIR) ]  && mkdir $(TESTDIR) || true
+       [ ! -e $(TMPDIR)  ]  && mkdir $(TMPDIR)  || true
+       [ ! -e $(TRCDIR)  ]  && mkdir $(TRCDIR)  || true
+       [ ! -e $(TRYDIR)  ]  && mkdir $(TRYDIR)  || true
+
+# gee this script could be better, particlarly in gathering the targets
+# it would be simplified if the tranche commands took multiple source arguments
+# if [ -e $(DEPFILE) ]; then rm $(DEPFILE); fi
+# if [ ! -z "$(TRCFILES)" ]; then\
+#   targets="";\
+#   for i in $(TRCFILES); do\
+#     tranche-make $$i -tdir $(SRCDIR) -mfile $(DEPFILE);\
+#     targets+=$$(tranche-target $$i);\
+#     targets+=" ";\
+#   done;\
+#   echo $$targets;\
+# fi    
+
+
 .PHONY: dep
-dep: 
-       @if [ -z "$(CC)" ]; then\
+dep:
+       if [ -e $(DEPFILE) ]; then rm $(DEPFILE); fi
+       if [ ! -z "$(TRCFILES)" ]; then\
+         tranche-make $(TRCFILES) -mfile $(DEPFILE);\
+         $(MAKE) $(shell tranche-targets $(TRCFILES) -sep " ");\
+       fi       
+       if [ -z "$(CC)" ]; then\
          if [ -z "$C()" ]; then\
            echo "No compiler specified";\
            exit 1;\
          else\
            echo "C compiler only deps" ;\
-           $(C) $(CFLAGS) -MM  $(C_SOURCE_LIB) $(C_SOURCE_CLI) | sed 's|^.*\.o|$(TMPDIR)/&|' > $(DEPFILE);\
+           $(C) $(CFLAGS) -MM  $(C_SOURCE_LIB) $(C_SOURCE_CLI) | sed 's|^.*\.o|$(TMPDIR)/&|' >> $(DEPFILE);\
            echo "deps for C linking";\
-           for i in $(C_BASE_CLI) ; do\
+           for i in $(C_BASE_CLI); do\
              $(ECHO) >> $(DEPFILE);\
              $(ECHO) "$(EXECDIR)/$$i : $(TMPDIR)/$$i.cli.o $(LIBFILE)" >> $(DEPFILE);\
              $(ECHO) " $(C) -o $(EXECDIR)/$$i $(TMPDIR)/$$i.cli.o $(LINKFLAGS)" >> $(DEPFILE);\
            done;\
          fi;\
        else\
-         $(CC) $(CCFLAGS) -MM  $(CC_SOURCE_LIB) $(CC_SOURCE_CLI) | sed 's|^.*\.o|$(TMPDIR)/&|' > $(DEPFILE);\
+         $(CC) $(CCFLAGS) -MM  $(CC_SOURCE_LIB) $(CC_SOURCE_CLI) | sed 's|^.*\.o|$(TMPDIR)/&|' >> $(DEPFILE);\
          if [ -z "$C()" ]; then\
            echo "CC compiler only deps" ;\
          else\
            echo "CC and C mixed compile deps" ;\
-           $(C) $(CFLAGS) -MM   $(C_SOURCE_LIB) $(C_SOURCE_CLI) | sed 's|^.*\.o|$(TMPDIR)/&|' > $(DEPFILE);\
+           $(C) $(CFLAGS) -MM   $(C_SOURCE_LIB) $(C_SOURCE_CLI) | sed 's|^.*\.o|$(TMPDIR)/&|' >> $(DEPFILE);\
          fi;\
          echo "deps for CC linking";\
          for i in $(CC_BASE_CLI) $(C_BASE_CLI) ; do\
diff --git a/tool/lib/makefile-trc b/tool/lib/makefile-trc
deleted file mode 100644 (file)
index 14b3c4f..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-
-# This makefile is usually called through a local makefile rather than directly.
-# The purpose of this makefile is to expand out the tranched C/CC sources, and
-# otherwise to fall through to makefile_cc.
-
-SHELL=/bin/bash
-
-TRCDIR=trc
-
-# these are the sources edited by the programmer
-TRC_FILE= $(wildcard $(TRCDIR)/*.trc.c) $(wildcard $(TRCDIR)/*.trc.cc)
-
--include makefile-flags
-
-MAKE=/usr/bin/make --no-print-directory -f $(PROJECT_SUBU)/tool/lib/makefile-cc
-#MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tool/lib/makefile-cc
-
-DEPFILE=$(TMPDIR)/makefile-trc.deps
-
-all: version deps lib execs
-
-.PHONY: all version deps lib exec
-all: version deps lib exec
-
-lib:
-       $(MAKE) $@
-
-exec:
-       $(MAKE) $@
-
-share:
-       if [ ! -z "$(wildcard $(EXECDIR)/*)" ]; then cp $(EXECDIR)/* $(PROJECT_SUBU)/tool/bin; fi
-
-%::
-       $(MAKE) $@
-
-dep: 
\ No newline at end of file