From 8e676caf4b0a2a08cdbb951f6010423c994bbe9a Mon Sep 17 00:00:00 2001 From: leitner Date: Mon, 20 Jan 2025 19:03:05 +0000 Subject: [PATCH] add tool to generate dependencies (not in production yet) --- GNUmakefile | 10 +- compile_commands.json.tmpl | 1 + n.c | 458 +++++++++++++++++++++++++++++++++++++ t.c | 5 +- 4 files changed, 471 insertions(+), 3 deletions(-) create mode 100644 n.c diff --git a/GNUmakefile b/GNUmakefile index bf12a59..769c84d 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -1199,7 +1199,7 @@ haveip6.h haven2i.h havesl.h haveinline.h iopause.h select.h \ havekqueue.h haveepoll.h libepoll havesigio.h havebsdsf.h havesendfile.h \ havescope.h havedevpoll.h dep libsocket havealloca.h haveuint128.h \ entities.h ent havepread.h haveaccept4.h *.gcda *.gcno \ -compile_commands.json json +compile_commands.json json n undep rm -rf libowfat INCLUDES=buffer.h byte.h fmt.h ip4.h ip6.h mmap.h scan.h socket.h str.h stralloc.h \ @@ -1372,7 +1372,7 @@ iob_send.o scan_ip6if.o: havealloca.h #cutstart dep: haveip6.h haven2i.h havesl.h haveinline.h iopause.h select.h haveepoll.h havekqueue.h havedevpoll.h havescope.h havesigio.h havebsdsf.h havesendfile.h havealloca.h haveuint128.h entities.h havepread.h haveaccept4.h - $(CC) -I. -MM `ls */*.c | grep -v test` t.c | sed -e 's@ \./@ @g' > dep + $(CC) -I. -MM `ls */*.c | grep -v test/ | grep -v examples/` t.c | sed -e 's@ \./@ @g' > dep libdep: for i in $(LIBS); do (echo -n $$i|tr a-z A-Z|sed 's/.A$$/_OBJS=/'; echo $${i%.a}/*.c|sed -e 's@[^/]*/\([^.]*\)\.c@\1.o @g'); done > libdep @@ -1437,3 +1437,9 @@ check2: haveuint128.h haveinline.h entities.h check: haveuint128.h haveinline.h $(TESTS) +.PHONY: dep2 +dep2: n + ./n | sort > dep2 + +dep3: undep dep + ./undep < dep | sort > dep3 diff --git a/compile_commands.json.tmpl b/compile_commands.json.tmpl index bca70e6..28ed72f 100644 --- a/compile_commands.json.tmpl +++ b/compile_commands.json.tmpl @@ -489,6 +489,7 @@ { "directory": "@", "file": "io/iom_abort.c", "output": "iom_abort.o", "arguments": [ "clang", "-c", "io/iom_abort.c", "-I." ]}, { "directory": "@", "file": "io/iom_add.c", "output": "iom_add.o", "arguments": [ "clang", "-c", "io/iom_add.c", "-I." ]}, { "directory": "@", "file": "io/iom_init.c", "output": "iom_init.o", "arguments": [ "clang", "-c", "io/iom_init.c", "-I." ]}, +{ "directory": "@", "file": "io/iom_requeue.c", "output": "iom_requeue.o", "arguments": [ "clang", "-c", "io/iom_requeue.c", "-I." ]}, { "directory": "@", "file": "io/iom_wait.c", "output": "iom_wait.o", "arguments": [ "clang", "-c", "io/iom_wait.c", "-I." ]}, { "directory": "@", "file": "cdb/cdb.c", "output": "cdb.o", "arguments": [ "clang", "-c", "cdb/cdb.c", "-I." ]}, { "directory": "@", "file": "cdb/cdb_hash.c", "output": "cdb_hash.o", "arguments": [ "clang", "-c", "cdb/cdb_hash.c", "-I." ]}, diff --git a/n.c b/n.c new file mode 100644 index 0000000..467ea51 --- /dev/null +++ b/n.c @@ -0,0 +1,458 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +#include "fmt.h" +#include "fmt/fmt_strm_internal.c" +#include "fmt/fmt_str.c" +#include "mmap/mmap_read.c" +#include "mmap/mmap_unmap.c" +#include "open/open_read.c" +#include "open/open_trunc.c" + +// this program is a dependency generator +// we have two kinds of dependencies, libdep and dep +// libdep: "TAI_OBJS=tai_add.o tai_now.o tai_pack.o tai_sub.o tai_uint.o tai_unpack.o" +// dep: "tai_add.o: tai/tai_add.c tai.h libowfat/uint64.h" +// we will open *.h and */*.c, looking for #include directives + +// a holds pointers to filenames in a line for libdep +size_t al; // allocated and length for a +char* a[1024]; // array of pointers to strings for libdep + +// buf holds the current line for libdep; used by objdup, flushlibdep +size_t bl; // allocated and length for buf +char buf[8196]; // will assert if not enough, increase size then + +// curlibbuf holds the name of the library, used by flushlibdep +const char* curlib; +char curlibbuf[256]; + +// libs holds an array of the libdep strings for each library +char* libs[64]; // will assert if not enough, increase size then +size_t nl; // index of next free slot in libs + +// For qsort +static int scmp(const void* a,const void* b) { + return strcmp(*(char**)a,*(char**)b)>0; +} + +// Are we still working on the same library? Used by addlibdep +// If not we need to flush the string we have been building and make a new one +static bool samelib(const char* s) { + return s == curlib; +} + +// Add current libcur_dep plus \n to libdep, and reset libdep_cur +static void flushlibdep(const char* libname) { + if (curlibbuf[0]) { // we were working on a library + size_t i; + // curlibbuf is "byte", make it "BYTE" instead + for (i=0; curlibbuf[i]>='a' && curlibbuf[i]<='z'; ++i) + curlibbuf[i]-=32; + + // sort all the file names alphabetically + qsort(a,al,sizeof(a[0]),scmp); + + // count bytes needed for all file names + size_t n=0; + // don't worry about integer overflows since all fit into global buf + for (i=0; i3 && x[-2]=='.' && x[-1]=='h') { + // bounds check + if (headermapuse>=sizeof(headermap)/sizeof(headermap[0])) { + write(2,"increase size of headermap in n.c!\n",35); + exit(1); + } + // add entry + headermap[headermapuse++]=strdup(s); + } else { + // make sure we don't exceed MAPLEN + if (mapuse>=MAPLEN) { + write(2,"increase MAPLEN in n.c!\n",24); + exit(1); + } + // add entry to list + map[mapuse++]=strdup(s); + } +} + +// Look for filename s in the map of dependencies +// Return pointer to map entry or NULL +static const char* finddep(const char* s,size_t l,const char** ret) { + size_t i; + const char** m=map; + size_t ml=mapuse; + if (l>3 && s[l-2]=='.' && s[l-1]=='h') { + // we put the headers in a separate list so we don't have to work so + // much here + m=headermap; + ml=headermapuse; + // if we are looking for "libowfat/byte.h", redirect to "byte.h" + if (l>10 && !memcmp(s,"libowfat/",9)) { + s+=9; + l-=9; + } + } + // the strings in the map look like this: + // "byte_copy.o: byte/byte_copy.c byte.h libowfat/compiler.h" + // so to find a file, we look for ':' as a separator + for (i=0; ibase=malloc(4096); + if (sb->base==0) { + perror("malloc"); + exit(111); + } + sb->l=0; + sb->a=4096; +} + +// add s to stringbag (returns offset relative to sb->base) +static size_t addstring(struct stringbag* sb,const char* s,size_t l) { + assert(l<=127); + if (!sb->base) init_stringbag(sb); + size_t i; + for (i=0; il; i+=sb->base[i]+1) { + if (sb->base[i] == (int)l && !memcmp(sb->base+i+1,s,l)) { + // found! + return i; + } + } + if (sb->l+l+2 > sb->a) { + sb->a += 4096; + char* x = realloc(sb->base, sb->a); + if (!x) { + perror("realloc"); + exit(111); + } + sb->base = x; + } + sb->base[i]=l; + memcpy(sb->base+i+1, s, l+1); + sb->l = i+1+l; + return i; +} + +// reset stringbag to empty for reuse +static void resetbag(struct stringbag* sb) { + sb->l=0; +} + +// taken from str/str_chr.c +size_t str_chr(const char *in, char needle) { + size_t i; + for (i=0; in[i] && in[i]!=needle; ++i) ; + return i; +} + +static void followdep(struct stringbag* sb, const char* s) { + // "uint64_pack.o: uint/uint64_pack.c uint64.h uint32.h" + + const char* c=strchr(s,':'); + if (!c || c[1]!=' ') return; // either not found or no dependencies + c+=2; // c = "uint/uint64_pack.c uint64.h uint32.h" + while (*c && *c!=' ') { + size_t n=str_chr(c,' '); + size_t prev=sb->l; + size_t ofs=addstring(sb,c,n); + if (ofs>=prev) { // was not the bag, need to recurse into it + const char* x; + if (finddep(c,n,&x)) + followdep(sb,x); + } + c += n + (c[n]==' '); + } + +} + +static void dumpdep(const char* s) { + static struct stringbag sb; + if (!sb.base) init_stringbag(&sb); + + followdep(&sb,s); + + size_t i; + i=str_chr(s,' '); + printf("%.*s",(int)i,s); + for (i=0; id); // empty filename!? + + int header=0; + + // filename ends with .c, but we want .o + if (c-d>2 && !strcmp(c-2,".h")) { + // it's a header file, we don't need to change .c to .o + header=1; + } else { + --c; + assert(c+extlen+5 < d+sizeof(d)); + c=stpcpy(c,objext); + } + c=stpcpy(c,": "); + + if (header) { + --c; // prevent " " + } else { + assert(c+strlen(pn)+5 < d+sizeof(d)); + c=stpcpy(c,pn); + } + + while (l) { + if (*s == '#') { + if (l>sizeof("#ifdef UNITTEST") && !memcmp(s,"#ifdef UNITTEST",15)) { + // we only care until #ifdef UNITTEST + break; + } + if (l>9 && !memcmp(s,"#include ",9)) { + // I never put spaces between # and ifdef + if (s[9]=='"') { + const char* f=s+10; + size_t i; + for (i=0; f+i + if (i>9 && !memcmp(f,"libowfat/",9)) { + assert(c+i+5 < d+sizeof(d)); + *c=' '; + c=memcpy(c+1,f,i)+i; + } + } + } + } + const char* n=memchr(s,'\n',l); + if (!n) break; // this was the last line + ++n; + l-=(n-s); + s=n; + } + *c=0; + adddepstolist(d); +// *c='\n'; +// write(1,d,c-d+1); +} + +// fn is byte/byte_copy.c, f is byte_copy.c (both can be the same) +static void adddeps(const char* fn, const char* f) { + size_t l; + const char* x=mmap_read(fn,&l); + if (x) { + find_deps(fn,f,x,l); + mmap_unmap(x,l); + } +} + +static void addlibdep(const char* p,size_t plen,const char* f) { + // if p is "byte", libdep_cur should start with BYTE_OBJS + // if it does, append f to libdep_cur + // if it doesn't, append libdep_cur to libdep, set up libdep_cur + size_t flen; + if (plen>255 || (flen=strlen(f))>255) return; + if (samelib(p)) { + a[al++]=objdup(f,flen); + } else { + flushlibdep(p); + a[0]=objdup(f,flen); + al=1; + } + + adddeps(fmt_strm_alloca(p,"/",f),f); +} + +int main() { + DIR* D=opendir("."); + assert(D); + struct dirent* d; + while ((d=readdir(D))) { + // we are interested in *.h and */*.c + if (d->d_type==DT_REG) { // *.h + const char* dot=strrchr(d->d_name,'.'); + if (dot && !strcmp(dot,".h")) { + adddeps(d->d_name,d->d_name); + } + } else if (d->d_name[0]!='.' && d->d_type==DT_DIR && + strcmp(d->d_name,"test") && + strcmp(d->d_name,"examples")) { + size_t n=strlen(d->d_name); + DIR* DS=opendir(d->d_name); + if (DS) { + struct dirent* ds; + while ((ds=readdir(DS))) { + const char* dot=strrchr(ds->d_name,'.'); + if (dot && !strcmp(dot,".c")) { + addlibdep(d->d_name,n,ds->d_name); +// printf("%s/%s\n",d->d_name,ds->d_name); + } + } + closedir(DS); + } + } + } + closedir(D); + flushlibdep(NULL); + + // libs now as a list of lines for the file + // sort them alphabetically + qsort(libs,nl,sizeof(libs[0]),scmp); + // save string lengths in ll + size_t ll[sizeof(libs)/sizeof(libs[0])]; + size_t i,n; + // count total bytes + for (i=n=0; i #include "compiletimeassert.h" #include "parse.h" +#include "clamp.h" #include "CAS.h" @@ -75,6 +76,8 @@ int main(int argc,char* argv[]) { (void)argc; (void)argv; + printf("%zu\n",clamp_hdrarray(10,10,10)); // expect 110 +#if 0 int64 pfd[2]; size_t i; io_socketpair(pfd); @@ -143,7 +146,7 @@ int main(int argc,char* argv[]) { } } } - +#endif #if 0 char buf[10]; buf[fmt_cescape(buf,"\003foo\xc0",5)]=0;