Automatic xification of dependencies using a pipe to receive dependencies from xifyfi...
authorNick Downing <downing.nick@gmail.com>
Sat, 21 Jan 2017 17:50:16 +0000 (04:50 +1100)
committerNick Downing <downing.nick@gmail.com>
Sat, 21 Jan 2017 17:50:16 +0000 (04:50 +1100)
.gitignore
lib/libx_c/Makefile
test/Makefile
xify/cc.c
xify/xifyfilt.c

index 87aeb91..83a041d 100644 (file)
@@ -1,4 +1,3 @@
-.xify
 *.a
 *.nocomm
 *.o
@@ -8,7 +7,7 @@
 *.temp.c
 *.usedby
 *.uses
-cross
+.xify
 cproto-4.6/Makefile
 cproto-4.6/config.cache
 cproto-4.6/config.h
@@ -18,23 +17,36 @@ cproto-4.6/cproto
 cproto-4.6/lex.yy.c
 cproto-4.6/stamp-h
 cproto-4.6/y.tab.c
-lib/libx_c.pre
+cross
 lib/libx_c.post
+lib/libx_c.pre
 lib/libx_c/*.temp
 lib/libx_c/compat-4.1/compat-4.1lib
+lib/libx_c/compat-4.1/compat-4.1lib_p
 lib/libx_c/compat-sys5/compat-sys5lib
+lib/libx_c/compat-sys5/compat-sys5lib_p
 lib/libx_c/gen/genlib
+lib/libx_c/gen/genlib_p
 lib/libx_c/inet/inetlib
+lib/libx_c/inet/inetlib_p
 lib/libx_c/linux/gen/genlib
+lib/libx_c/linux/gen/genlib_p
 lib/libx_c/linux/linuxlib
+lib/libx_c/linux/linuxlib_p
 lib/libx_c/linux/sys/syslib
+lib/libx_c/linux/sys/syslib_p
 lib/libx_c/net/named/hostlib
+lib/libx_c/net/named/hostlib_p
 lib/libx_c/net/netlib
+lib/libx_c/net/netlib_p
 lib/libx_c/ns/nslib
-lib/libx_c/pre.patch.bak
+lib/libx_c/ns/nslib_p
 lib/libx_c/post.patch.bak
+lib/libx_c/pre.patch.bak
 lib/libx_c/stdio/stdiolib
+lib/libx_c/stdio/stdiolib_p
 lib/libx_c/sys/syslib
+lib/libx_c/sys/syslib_p
 lib/libx_c/xx*
 test/hello
 test/hello.txt
index 786be14..6a0e455 100644 (file)
@@ -94,19 +94,19 @@ install-headers:
        ln -s a.out.h nlist.h; \
        ln -s sys/signal.h signal.h; \
        ln -s sys/syslog.h syslog.h
-       for i in `find . -name '*.h' -print`; \
-       do \
-               mkdir -p ${DESTDIR}/usr/include/.xify/`dirname $$i`; \
-               ${ROOT}/cross/lib/xify $$i ${DESTDIR}/usr/include/.xify/`dirname $$i`/x_`basename $$i`; \
-       done
-       cd ${DESTDIR}/usr/include/.xify; \
-       ln -s vax machine; \
-       ln -s machine/x_frame.h x_frame.h; \
-       ln -s sys/x_errno.h x_errno.h; \
-       ln -s sys/x_file.h x_fcntl.h; \
-       ln -s x_a.out.h x_nlist.h; \
-       ln -s sys/x_signal.h x_signal.h; \
-       ln -s sys/x_syslog.h x_syslog.h
+#      for i in `find . -name '*.h' -print`; \
+#      do \
+#              mkdir -p ${DESTDIR}/usr/include/.xify/`dirname $$i`; \
+#              ${ROOT}/cross/lib/xify $$i ${DESTDIR}/usr/include/.xify/`dirname $$i`/x_`basename $$i`; \
+#      done
+#      cd ${DESTDIR}/usr/include/.xify; \
+#      ln -s vax machine; \
+#      ln -s machine/x_frame.h x_frame.h; \
+#      ln -s sys/x_errno.h x_errno.h; \
+#      ln -s sys/x_file.h x_fcntl.h; \
+#      ln -s x_a.out.h x_nlist.h; \
+#      ln -s sys/x_signal.h x_signal.h; \
+#      ln -s sys/x_syslog.h x_syslog.h
 
 install:
        ${INSTALL} libc.a ${DESTDIR}/lib/libc.a
index e7fb58d..8c03f91 100644 (file)
@@ -1,6 +1,6 @@
 ROOT=..
 CC=FAKEROOT=${ROOT}/cross ${ROOT}/cross/bin/cc
-CFLAGS=-g -Dvax
+CFLAGS=-d -g -Dvax
 
 hello: hello.o
        ${CC} ${CFLAGS} -o $@ hello.o
index 2f05f4c..59db51a 100644 (file)
--- a/xify/cc.c
+++ b/xify/cc.c
@@ -53,10 +53,40 @@ char        *npassname;
 int    nc, nl, np, nxo, na;
 
 #ifdef XIFY
-char   **ilist;
-int    ni;
-
-/*char in_path[BUFSIZ];*/
+/* When we run "xify" as a child process, it will output to us on stderr a */
+/* list of dependencies as it encounters them. We receive this list via a */
+/* pipe, and as each dependency is received, we search the include path for */
+/* it, using special rules for "file.h" vs <file.h>, and then check if the */
+/* resolved path is already encountered (xified, or queued for xification). */
+/* If so, we ignore it. Otherwise we queue it. When we queue it, we save two */
+/* further pieces of information. If the path stem came from the include */
+/* path (other than being a relative path from a current file), and the */
+/* remaining path contained at least one directory, we have to "mkdir" the */
+/* path stem plus "/.xify". This is because the "-Idirectory" passed to to */
+/* gcc must exist, even if it is empty. This can occur if the remaining path */
+/* contains ".." elements. So, the first piece of information is which path */
+/* stem was used, or -1 if no extra "mkdir" is necessary (noting that we */
+/* will also "mkdir" the directory containing the xified source). It'd be */
+/* fine to "mkdir" the path stem at the time of queueing, or to "mkdir" all */
+/* path stems whether anything is found through them or not, but this way is */
+/* more consistent if we get an error and abort with things still enqueued. */
+/* The second piece of information is the mtime, so that we do not have to */
+/* "stat" it again when it comes to the head of the queue. When it comes to */
+/* the head of the queue we check for a previous xification of the same file */
+/* left in ".xify" underneath the directory containing the file, since this */
+/* will occur a lot for system includes and if not stale it saves much work. */
+
+#define IN_QUEUE_SIZE 0x100 /* fix this later and make it dynamic */
+
+struct {
+       char *path;
+       struct timespec mtime;
+       int mkdir;
+} in_queue[IN_QUEUE_SIZE];
+int in_queue_head;
+int in_queue_tail;
+
+char   in_path[BUFSIZ];
 char   out_path[BUFSIZ];
 #endif
 
@@ -77,8 +107,8 @@ void error __P((char *s, char *x));
 int getsuf __P((char as[]));
 char *setsuf __P((char *as, int ch));
 #ifdef XIFY
-int xify_include __P((char *in_name));
-int xify_file __P((char *in_name, struct stat *in_statbuf));
+int xify_include __P((char *in_name, char *prev_name));
+int xify_file __P((char *in_name, struct timespec *in_mtime));
 #endif
 int callsys __P((char *f, char **v));
 int nodup __P((char **l, char *os));
@@ -272,7 +302,6 @@ int main(argc, argv) int argc; char **argv; {
                        if (plist[i][2] == '/')
                                plist[i] = strspl("-I", strspl(t, plist[i] + 2));
        }
-       ilist = (char **)calloc(0x100, sizeof (char **));
 #else
        if (pflag==0)
                sprintf(tmp0, "/tmp/ctm%05.5d", getpid());
@@ -296,13 +325,26 @@ int main(argc, argv) int argc; char **argv; {
                                error("not found: %s", clist[i]);
                                goto nogood;
                        }
-                       if (xify_file(clist[i], &statbuf)) {
-                       nogood:
-                               cflag++;
-                               eflag++;
-                               continue;
-                       }
+                       if (xify_file(clist[i], &statbuf.st_mtim))
+                               goto nogood;
                        clist[i] = savestr(out_path);
+
+                       while (in_queue_head < in_queue_tail) {
+                               if (
+                                       xify_file(
+                                               in_queue[in_queue_head].path,
+                                               &in_queue[in_queue_head].mtime
+                                       )
+                               )
+                                       goto nogood;
+                               if ( 
+                                       in_queue[in_queue_head].mkdir >= 0 &&
+                                       mkdir(plist[in_queue[in_queue_head].mkdir] + 2, 0777) &&
+                                       errno != EEXIST
+                               )
+                                       goto nogood;
+                               ++in_queue_head;
+                       }
                }
                av[0] = "gcc"; av[1] = "-o";
                na = 2;
@@ -331,6 +373,7 @@ int main(argc, argv) int argc; char **argv; {
                av[na++] = clist[i];
                av[na] = 0;
                if (callsys(gcc, av)) {
+               nogood:
                        cflag++;
                        eflag++;
                        continue;
@@ -513,9 +556,15 @@ char *setsuf(as, ch) char *as; int ch; {
 }
 
 #ifdef XIFY
-int xify_file(in_name, in_statbuf) char *in_name; struct stat *in_statbuf; {
+int xify_file(in_name, in_mtime) char *in_name; struct timespec *in_mtime; {
        int i;
        struct stat out_statbuf;
+       int t, status;
+       char **cpp;
+       int fds[3];
+       FILE *err_fp;
+       char err_line[BUFSIZ];
+       int e;
        /* note: out_path is an output parameter on success */
 
        for (i = strlen(in_name); i > 0 && in_name[i - 1] != '/'; --i)
@@ -525,9 +574,9 @@ int xify_file(in_name, in_statbuf) char *in_name; struct stat *in_statbuf; {
        strcat(out_path + i, in_name + i);
        if (
                stat(out_path, &out_statbuf) == 0 && (
-                       out_statbuf.st_mtim.tv_sec > in_statbuf->st_mtim.tv_sec || (
-                               out_statbuf.st_mtim.tv_sec == in_statbuf->st_mtim.tv_sec &&
-                               out_statbuf.st_mtim.tv_nsec >= in_statbuf->st_mtim.tv_nsec
+                       out_statbuf.st_mtim.tv_sec > in_mtime->tv_sec || (
+                               out_statbuf.st_mtim.tv_sec == in_mtime->tv_sec &&
+                               out_statbuf.st_mtim.tv_nsec >= in_mtime->tv_nsec
                        )
                )
                
@@ -542,7 +591,120 @@ int xify_file(in_name, in_statbuf) char *in_name; struct stat *in_statbuf; {
        out_path[i + 5] = '/';
 
        av[0] = "xify"; av[1] = in_name; av[2] = out_path; av[3] = 0;
-       return callsys(xify, av);
+       /*return callsys(xify, av);*/
+
+       if (debug) {
+               fprintf(stderr, "%s:", xify);
+               for (cpp = av; *cpp != 0; cpp++)
+                       fprintf(stderr, " %s", *cpp);
+               fprintf(stderr, "\n");
+       }
+       if (
+               pipe(fds) ||
+               (err_fp = fdopen(fds[0], "r")) == 0 ||
+               (fds[2] = dup(2)) == -1
+       ) {
+               fprintf(stderr, "Can't create pipe\n");
+               return (100);
+       }
+       dup2(fds[1], 2);
+       close(fds[1]);
+       t = vfork();
+       if (t == -1) {
+               printf("No more processes\n");
+               return (100);
+       }
+       if (t == 0) {
+               execv(xify, av);
+               printf("Can't find %s\n", xify);
+               fflush(stdout);
+               _exit(100);
+       }
+       dup2(fds[2], 2);
+       close(fds[2]);
+       while (fgets(err_line, BUFSIZ, err_fp))
+               if (err_line[0] == '"') {
+                       e = '"';
+                       goto include;
+               }
+               else if (err_line[0] == '<') {
+                       e = '>';
+               include:
+                       for (i = 1; err_line[i] != e; ++i) {
+                               if (err_line[i] == 0)
+                                       goto garbage;
+                       }
+                       err_line[i] = 0;
+                       if (xify_include(err_line + 1, err_line[0] == '"' ? in_name : 0))
+                               break;
+               }
+               else {
+               garbage:
+                       fprintf(stderr, "Garbage from filter\n");
+                       break;
+               }
+       fclose(err_fp);
+       while (t != wait(&status))
+               ;
+       if ((t=(status&0377)) != 0 && t!=14) {
+               if (t!=2) {
+                       printf("Fatal error in %s\n", xify);
+                       eflag = 8;
+               }
+               dexit();
+       }
+       return ((status>>8) & 0377);
+}
+
+int xify_include(in_name, prev_name) char *in_name; char *prev_name; {
+       int i, j;
+       struct stat statbuf;
+
+       if (prev_name) {
+               for (i = strlen(prev_name); i > 0 && prev_name[i - 1] != '/'; --i)
+                       ;
+               bcopy(prev_name, in_path, i);
+               strcpy(in_path + i, in_name);
+               if (stat(in_path, &statbuf) == 0) {
+                       i = -1;
+                       goto found_local;
+               }
+       }
+       for (int i = 0; i < np; ++i)
+               if (/*plist[i][0] == '-' &&*/ plist[i][1] == 'I') {
+                       j = strlen(plist[i] + 2) - 5; /* remove ".xify" */      
+                       bcopy(plist[i] + 2, in_path, j);
+                       strcpy(in_path + j, in_name);
+                       if (stat(in_path, &statbuf) == 0)
+                               goto found_system;
+               }
+       error("not found: %s\n", in_name);
+       return 1;
+
+found_system:
+       /* see if it requires extra mkdir */
+       for (; in_path[j]; ++j)
+               if (in_path[j] == '/')
+                       goto found_local;
+
+       /* it does not require extra mkdir */
+       i = -1;
+
+found_local:
+       for (j = 0; j < in_queue_tail; ++j)
+               if (strcmp(in_queue[j].path, in_path) == 0)
+                       return 0;
+
+       if (in_queue_tail >= IN_QUEUE_SIZE) {
+               error("in queue full: %s\n", in_path);
+               return 1;
+       }
+
+       in_queue[in_queue_tail].path = savestr(in_path);
+       in_queue[in_queue_tail].mtime = statbuf.st_mtim;
+       in_queue[in_queue_tail].mkdir = i;
+       ++in_queue_tail;
+       return 0;
 }
 #endif
 
index d09fe7c..4707e7c 100644 (file)
@@ -52,11 +52,13 @@ int main() {
               (l != 0 || m != 8 || memcmp(p, "stdarg.h", 8) != 0) /*&&
               (l != 0 || m != 9 || memcmp(p, "varargs.h", 9) != 0)*/
             ) {
-#if 0 /* just remove for now, since we are not doing anything with it yet */
               fwrite(p - 1, l + m + 2, 1, stderr); /* include <> or "" */
               fputc('\n', stderr);
-#endif
-              fwrite(p, l, 1, stdout);
+              if (l) {
+                fwrite("../", 3, 1, stdout);
+                fwrite(p, l, 1, stdout);
+                fwrite(".xify/", 6, 1, stdout);
+              }
               fwrite("x_", 2, 1, stdout);
               p = q;
               l = m;