From: stephan b. <sg...@us...> - 2004-12-22 19:04:37
|
Update of /cvsroot/pclasses/pclasses2/toc/bin In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6599/bin Added Files: atsign_parse ccdv.c cleanup_vars create_makefile_stubs.sh getMakefileVar install-sh makedist Makefile mkdep.c relativePathToSharedMakefile removeDupeArgs tocCreateMakefileStubs Log Message: egg --- NEW FILE: Makefile --- include toc.make DIST_FILES += atsign_parse \ ccdv.c \ cleanup_vars \ getMakefileVar \ install-sh \ makedist \ mkdep.c \ relativePathToSharedMakefile \ removeDupeArgs CLEAN_FILES += mkdep --- NEW FILE: cleanup_vars --- #!/usr/bin/perl # reads in a list of KEY=VAL lines and removes all but the last-set # entries. Intended for use with cleaning up toc-exported variables. @IN = reverse <>; %gots = (); @out = (); foreach $l (@IN) { chomp $l; next unless $l =~ m|^\s*(\S+)\s*=\s*(.*)|; $key = $1; $val = $2; next if $gots{$key}; $gots{$key} = 1; push( @out, $l ); # print $l."\n"; } print join("\n", reverse @out),"\n"; --- NEW FILE: tocCreateMakefileStubs --- #!/bin/sh # climbs down $1 and generates makefile stubs for use with toc trees. # It refuses to overwrite existing files, instead doing nothing # for dirs which already contain a Makefile # # Usage: $0 [path: defaults to $PWD] dir=${1-${PWD}} for d in $(find $dir -type d); do mf=$d/Makefile if test -f $mf; then echo "WARNING: $mf exist! Skipping!" 1>&2 continue fi cd $d > /dev/null SUB= for sub in *; do test -d "$sub" || continue sub=${sub#./} echo "SUBDIRS += $sub" >> $mf done >> $mf echo "include toc.make" >> $mf echo "Created $mf" 1>&2 cd - > /dev/null done --- NEW FILE: makedist --- #!/usr/bin/perl # # A mind-numbingly stupid distribution tarball creator. # # todo: add some wildcard support to the file lists. # # st...@s1... # # Note that is implicitely filters out some file names, # to simplify use of the toc client-side install code. $verbose = 0; $dieonerror = 1; $USAGE = "usage: $0 input_list_file release_name"; $DISTFILES_LIST = $ARGV[0] || die $USAGE; $basename = $ARGV[1] || die $USAGE; $TARBALL = $basename; $basename =~ s|\.tar$||; $TARBALL .= ".tar" unless $TARBALL =~ m|\.tar$|; execcmd( "rm -fr $basename" ) if -d $basename; execcmd( "mkdir $basename" ); open DLIST, "<$DISTFILES_LIST" || die "Cannot open dist files list, $DISTFILES_LIST!"; @list = <DLIST>; # print @list; close DLIST; @thelist = (); foreach $l (@list) { next if $l =~ /^#/; next if $l =~ m|^(.*/)?toc.q?make$|; next if $l =~ m|\.o$|; next if $l =~ m|/?CVS/?|; chomp( $l ); next unless $l =~ /\w/; next if $l =~ m|~$|; $l =~ s/^\s+//; if( (! -f $l) && (! -d $l) ) { stderr( "WARNING: [$l] not found!" ); exit 1 if $dieonerror; } push( @thelist, $l ); } $tarfileslist = ".tar.tmp"; open TARLIST, ">$tarfileslist"; print TARLIST join( "\n", @thelist ); #print STDOUT "thelist=",join( "\n", @thelist ),"\n"; print "File count: ".@thelist."\n" if $verbose; $tarargs = "--files-from=$tarfileslist --exclude=CVS"; execcmd( "tar cf - $tarargs | tar xf - -C \"$basename\"" ); # ^^^^ got that? it's simpler than cp'ing the list of files to their proper subdirs. :) $md5 = `which md5sum 2>/dev/null`; if( $md5 ) { $md5file = "$basename/md5.sums.$basename"; print STDERR "Generating md5 sums: $md5file\n"; # execcmd( "cd $basename; for x in \$(find . -type f); do md5sum \$x >> MD5SUMS.$basename; done" ); execcmd( "for x in \$(cat $tarfileslist); do md5sum \$x; done > $md5file" ) } else { print STDERR "Warning: no md5sum binary found, so not including md5 info.\n"; } execcmd( "rm $tarfileslist" ); execcmd( "tar cf \"$TARBALL\" \"$basename\"" ); execcmd( "rm -fr \"$basename\"" ); # print "Tarball: ".`ls -la $TARBALL`."\n"; print "Tarball: $TARBALL\n" if $verbose; exit 0; sub stderr() { $msg = shift; print STDERR $msg."\n"; } sub execcmd() { $cmd = shift; print $cmd."\n" if $verbose; `$cmd`; } --- NEW FILE: atsign_parse --- #!/usr/bin/perl # ( ^^^^ when run with -n it tries to read in files named after the args. e.g. foo=bar) # # Takes command-line args in the format: # # foo=bar [include:bar=infile] [shell:foobar=shellcmd]... # # and parses stdin, replacing @foo@ with bar. # # All output goes to stdout. # # Intended to be used as a simple parser for Makefile.in-type files. # # Special keys type: # # include:KEY=filename # # Will try to read the file VAL and import it in place of @KEY@. # # shell:KEY=shellcmd # # Will replace KEY with the output of shellcmd. # # The shell: and include: substitutions happen ONE time, # before the input stream is ever read, and not every time # the corresponding @token@ is replaced. # # Optional arguments: # # [-f filename] will read in that file. It must be in the form # KEY=VALUE, with one key/value per line. # # [-c] will enable "cleanup mode". Any @TOKENS@ in the input stream # which were not explicitely assigned values will be parsed out # of the output. Without this option, the raw @TOKEN@ would go # into the output. # # License: public domain # author: stephan <sg...@us...> # CVS Revision: $Revision: 1.1 $ BEGIN { $STRIP_LEADING_DASHES = 1; # if set to 1 then --foo=bar is same as foo=bar $op_cleanup = 0; # strip un-parsed @TOKENS@ from the input. if( ! @ARGV ) { print "Usage: $0 foo=bar [bar=foobar] [argN=valN]...\n"; exit 1; } @args = (); ############################################################ collect args... for( $i = 0; $i < @ARGV; $i++ ) { $a = $ARGV[$i]; if( $a eq "-f" ) { $fn = $ARGV[++$i]; open( INFILE, $fn ) || die "Could not open input file [$fn]."; @foo = <INFILE>; foreach $f (@foo) { chomp($f); push( @args, $f ); } close INFILE; next; } if( $a eq "-c" ) { $op_cleanup = 1; next; } push( @args, $a ); } #print join( "\n", @args )."\n"; %args = (); foreach $a ( @args ) { ############################################################ parse out KEY=VAL pairs next unless $a =~ m|([^=]+)\s*=\s*(.*)|; $key = $1; $val = $2; if( $STRIP_LEADING_DASHES ) { $key =~ s/^-+//; } #print STDERR ": [$key]=[$val]\n"; ############################################################ include:FOO=BAR if( $key =~ m|^include:(.+)| ) { $key = $1; open INFILE, "<$val" or die "Cannot open file '$val', as requested by \@include:$key@!"; @foo = <INFILE>; close INFILE; $val = join( "", @foo ); } ############################################################ shell:FOO=BAR if( $key =~ m|^shell:(.+)| ) { $key = $1; $val = `$val`; } $args{$key} = $val; } } # /BEGIN while( <STDIN> ) { $loop = true; while( $loop ) { # loop over line until we can replace no more @tokens@ $cp = $_; foreach $k (keys(%args)) { $v = $args{$k}; next unless $_ =~ s|\@$k\@|$v|g; # print STDERR "replacing $k --> $v\n"; } $loop = 0 if $cp eq $_; } if( $op_cleanup ) { # parse out undefined @tokens@ while( $_ =~ s|\@\S+\@||g ) {} } print; } exit 0; --- NEW FILE: relativePathToSharedMakefile --- #!/usr/bin/perl # Makes relative paths in the contexts of build trees. $shared_makefile = "toc_shared.make.at"; # Usages: # $0 [$shared_makefile_filename] [/starting/point/path] # If $shared_makefile_filename is given, then that name is used instead # of '$shared_makefile'. If a path is given, that is assumed to be our # starting point (it normally assumes $PWD as the starting point). # # It climbs up from the starting point and stops when it finds a # file named '$shared_makefile' (or the name given as the first argument). It # prints a relative path from the starting dir to that path, or no output if # '$shared_makefile' is not found. # # stephan - st...@s1... $configure = $shared_makefile; $topdir = "/"; if( @ARGV == 0 ) { $mode = "findtop"; $subdir = $ENV{'PWD'}; } if( @ARGV == 1 ) { $mode = "findtop"; if( -d $ARGV[0] ) { $subdir = $ARGV[0]; $subdir =~ s!/$!!; } else { $subdir = $ENV{'PWD'}; $configure = $ARGV[0]; } } if( @ARGV == 2 ) { $mode = "twoargs"; $configure = $ARGV[0]; $subdir = $ARGV[1]; } if( ! $mode || $ARGV[0] =~ /-(help|h|\?)/ ) { $usage = "Usages:\n$0 [configure_filename] [/path/to/some/code/project/subdir\n"; print $usage."\n"; exit 1; } if( $subdir !~ m|/| ) { # print "$0: Sorry, but i'm under-featured: i cannot handle relative paths as input!\n"; # print "Try \$PWD/$subdir instead?\n"; $subdir = $ENV{'PWD'}."/".$subdir; # exit 1; } $subdir =~ s|/\./|/|g; # clean up the mess i caused with the above tip :/ # print "$mode: $topdir $subdir\n"; $curdir = $subdir; $relpath = "./"; while( $curdir && $curdir !~ m|^$topdir$| ) { $conf = $curdir."/".$configure; #print "conf=$conf\n"; if( -f $conf ) { last; break; } #print "curdir=[$curdir]\n"; $relpath .= "../"; $curdir =~ s|(.*)/[^/]+$|$1|; } if( ! $curdir ) { $relpath = ""; } #print "relpath=[$relpath]"; $relpath =~ s!/$!!; print $relpath; --- NEW FILE: ccdv.c --- /* ccdv.c * * Copyright (C) 2002-2003, by Mike Gleason, NcFTP Software. * All Rights Reserved. * * Licensed under the GNU Public License. */ #include <unistd.h> #include <sys/types.h> #include <sys/time.h> #include <sys/wait.h> #include <fcntl.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <errno.h> #define SETCOLOR_SUCCESS (gANSIEscapes ? "\033\1331;32m" : "") #define SETCOLOR_FAILURE (gANSIEscapes ? "\033\1331;31m" : "") #define SETCOLOR_WARNING (gANSIEscapes ? "\033\1331;33m" : "") #define SETCOLOR_NORMAL (gANSIEscapes ? "\033\1330;39m" : "") #define TEXT_BLOCK_SIZE 8192 #define INDENT 2 #define TERMS "vt100:vt102:vt220:vt320:xterm:xterm-color:ansi:linux:scoterm:scoansi:dtterm:cons25:cygwin" size_t gNBufUsed = 0, gNBufAllocated = 0; char *gBuf = NULL; int gCCPID; char gAction[64] = ""; char gTarget[64] = ""; char gAr[32] = ""; char gArLibraryTarget[64] = ""; int gDumpCmdArgs = 0; char gArgsStr[800]; int gColumns = 80; int gANSIEscapes = 0; int gExitStatus = 95; static void DumpFormattedOutput(void) { char *cp; char spaces[8 + 1] = " "; char *saved; int curcol; int i; curcol = 0; saved = NULL; for (cp = gBuf + ((gDumpCmdArgs == 0) ? strlen(gArgsStr) : 0); ; cp++) { if (*cp == '\0') { if (saved != NULL) { cp = saved; saved = NULL; } else break; } if (*cp == '\r') continue; if (*cp == '\t') { saved = cp + 1; cp = spaces + 8 - (8 - ((curcol - INDENT - 1) % 8)); } if (curcol == 0) { for (i = INDENT; --i >= 0; ) putchar(' '); curcol = INDENT; } putchar(*cp); if (++curcol == (gColumns - 1)) { putchar('\n'); curcol = 0; } else if (*cp == '\n') curcol = 0; } free(gBuf); } /* DumpFormattedOutput */ /* Difftime(), only for timeval structures. */ static void TimeValSubtract(struct timeval *tdiff, struct timeval *t1, struct timeval *t0) { tdiff->tv_sec = t1->tv_sec - t0->tv_sec; tdiff->tv_usec = t1->tv_usec - t0->tv_usec; if (tdiff->tv_usec < 0) { tdiff->tv_sec--; tdiff->tv_usec += 1000000; } } /* TimeValSubtract */ static void Wait(void) { int pid2, status; do { status = 0; pid2 = (int) waitpid(gCCPID, &status, 0); } while (((pid2 >= 0) && (! WIFEXITED(status))) || ((pid2 < 0) && (errno == EINTR))); if (WIFEXITED(status)) gExitStatus = WEXITSTATUS(status); } /* Wait */ static int SlurpProgress(int fd) { char s1[71]; char *newbuf; int nready; size_t ntoread; ssize_t nread; struct timeval now, tnext, tleft; fd_set ss; fd_set ss2; const char *trail = "/-\\|", *trailcp; trailcp = trail; snprintf(s1, sizeof(s1), "%s%s%s... ", gAction, gTarget[0] ? " " : "", gTarget); printf("\r%-70s%-9s", s1, ""); fflush(stdout); gettimeofday(&now, NULL); tnext = now; tnext.tv_sec++; tleft.tv_sec = 1; tleft.tv_usec = 0; FD_ZERO(&ss2); FD_SET(fd, &ss2); for(;;) { if (gNBufUsed == (gNBufAllocated - 1)) { if ((newbuf = (char *) realloc(gBuf, gNBufAllocated + TEXT_BLOCK_SIZE)) == NULL) { perror("ccdv: realloc"); return (-1); } gNBufAllocated += TEXT_BLOCK_SIZE; gBuf = newbuf; } for (;;) { ss = ss2; nready = select(fd + 1, &ss, NULL, NULL, &tleft); if (nready == 1) break; if (nready < 0) { if (errno != EINTR) { perror("ccdv: select"); return (-1); } continue; } gettimeofday(&now, NULL); if ((now.tv_sec > tnext.tv_sec) || ((now.tv_sec == tnext.tv_sec) && (now.tv_usec >= tnext.tv_usec))) { tnext = now; tnext.tv_sec++; tleft.tv_sec = 1; tleft.tv_usec = 0; printf("\r%-71s%c%-7s", s1, *trailcp, ""); fflush(stdout); if (*++trailcp == '\0') trailcp = trail; } else { TimeValSubtract(&tleft, &tnext, &now); } } ntoread = (gNBufAllocated - gNBufUsed - 1); nread = read(fd, gBuf + gNBufUsed, ntoread); if (nread < 0) { if (errno == EINTR) continue; perror("ccdv: read"); return (-1); } else if (nread == 0) { break; } gNBufUsed += nread; gBuf[gNBufUsed] = '\0'; } snprintf(s1, sizeof(s1), "%s%s%s: ", gAction, gTarget[0] ? " " : "", gTarget); Wait(); if (gExitStatus == 0) { printf("\r%-70s", s1); printf("[%s%s%s]", ((gNBufUsed - strlen(gArgsStr)) < 4) ? SETCOLOR_SUCCESS : SETCOLOR_WARNING, "OK", SETCOLOR_NORMAL); printf("%-5s\n", " "); } else { printf("\r%-70s", s1); printf("[%s%s%s]", SETCOLOR_FAILURE, "ERROR", SETCOLOR_NORMAL); printf("%-2s\n", " "); gDumpCmdArgs = 1; /* print cmd when there are errors */ } fflush(stdout); return (0); } /* SlurpProgress */ static int SlurpAll(int fd) { char *newbuf; size_t ntoread; ssize_t nread; printf("%s%s%s.\n", gAction, gTarget[0] ? " " : "", gTarget); fflush(stdout); for(;;) { if (gNBufUsed == (gNBufAllocated - 1)) { if ((newbuf = (char *) realloc(gBuf, gNBufAllocated + TEXT_BLOCK_SIZE)) == NULL) { perror("ccdv: realloc"); return (-1); } gNBufAllocated += TEXT_BLOCK_SIZE; gBuf = newbuf; } ntoread = (gNBufAllocated - gNBufUsed - 1); nread = read(fd, gBuf + gNBufUsed, ntoread); if (nread < 0) { if (errno == EINTR) continue; perror("ccdv: read"); return (-1); } else if (nread == 0) { break; } gNBufUsed += nread; gBuf[gNBufUsed] = '\0'; } Wait(); gDumpCmdArgs = (gExitStatus != 0); /* print cmd when there are errors */ return (0); } /* SlurpAll */ static const char * Basename(const char *path) { const char *cp; cp = strrchr(path, '/'); if (cp == NULL) return (path); return (cp + 1); } /* Basename */ static const char * Extension(const char *path) { const char *cp = path; cp = strrchr(path, '.'); if (cp == NULL) return (""); return (cp); } /* Extension */ static void Usage(void) { fprintf(stderr, "Usage: ccdv /path/to/cc CFLAGS...\n\n"); fprintf(stderr, "I wrote this to reduce the deluge Make output to make finding actual problems\n"); fprintf(stderr, "easier. It is intended to be invoked from Makefiles, like this. Instead of:\n\n"); fprintf(stderr, "\t.c.o:\n"); fprintf(stderr, "\t\t$(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n"); fprintf(stderr, "\nRewrite your rule so it looks like:\n\n"); fprintf(stderr, "\t.c.o:\n"); fprintf(stderr, "\t\t@ccdv $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n\n"); fprintf(stderr, "ccdv 1.1.0 is Free under the GNU Public License. Enjoy!\n"); fprintf(stderr, " -- Mike Gleason, NcFTP Software <http://www.ncftp.com>\n"); exit(96); } /* Usage */ int main(int argc, char **argv) { int pipe1[2]; int devnull; char emerg[256]; int fd; int nread; int i; int cc = 0, pch = 0; const char *quote; if (argc < 2) Usage(); snprintf(gAction, sizeof(gAction), "Running %s", Basename(argv[1])); memset(gArgsStr, 0, sizeof(gArgsStr)); for (i = 1; i < argc; i++) { quote = (strchr(argv[i], ' ') != NULL) ? "\"" : ""; snprintf(gArgsStr + strlen(gArgsStr), sizeof(gArgsStr) - strlen(gArgsStr), "%s%s%s%s%s", (i == 1) ? "" : " ", quote, argv[i], quote, (i == (argc - 1)) ? "\n" : ""); if ((strcmp(argv[i], "-o") == 0) && ((i + 1) < argc)) { if (strcasecmp(Extension(argv[i + 1]), ".o") != 0) { strcpy(gAction, "Linking"); snprintf(gTarget, sizeof(gTarget), "%s", Basename(argv[i + 1])); } } else if (strchr("-+/", (int) argv[i][0]) != NULL) { continue; } else if (strncasecmp(Extension(argv[i]), ".c", 2) == 0) { cc++; snprintf(gTarget, sizeof(gTarget), "%s", Basename(argv[i])); } else if ((strncasecmp(Extension(argv[i]), ".h", 2) == 0) && (cc == 0)) { pch++; snprintf(gTarget, sizeof(gTarget), "%s", Basename(argv[i])); } else if ((i == 1) && (strcmp(Basename(argv[i]), "ar") == 0)) { snprintf(gAr, sizeof(gAr), "%s", Basename(argv[i])); } else if ((gArLibraryTarget[0] == '\0') && (strcasecmp(Extension(argv[i]), ".a") == 0)) { snprintf(gArLibraryTarget, sizeof(gArLibraryTarget), "%s", Basename(argv[i])); } } if ((gAr[0] != '\0') && (gArLibraryTarget[0] != '\0')) { strcpy(gAction, "Creating library"); snprintf(gTarget, sizeof(gTarget), "%s", gArLibraryTarget); } else if (pch > 0) { strcpy(gAction, "Precompiling"); } else if (cc > 0) { strcpy(gAction, "Compiling"); } if (pipe(pipe1) < 0) { perror("ccdv: pipe"); exit(97); } (void) close(0); devnull = open("/dev/null", O_RDWR, 00666); if ((devnull != 0) && (dup2(devnull, 0) == 0)) close(devnull); gCCPID = (int) fork(); if (gCCPID < 0) { (void) close(pipe1[0]); (void) close(pipe1[1]); perror("ccdv: fork"); exit(98); } else if (gCCPID == 0) { /* Child */ (void) close(pipe1[0]); /* close read end */ if (pipe1[1] != 1) { /* use write end on stdout */ (void) dup2(pipe1[1], 1); (void) close(pipe1[1]); } (void) dup2(1, 2); /* use write end on stderr */ execvp(argv[1], argv + 1); perror(argv[1]); exit(99); } /* parent */ (void) close(pipe1[1]); /* close write end */ fd = pipe1[0]; /* use read end */ gColumns = (getenv("COLUMNS") != NULL) ? atoi(getenv("COLUMNS")) : 80; gANSIEscapes = (getenv("TERM") != NULL) && (strstr(TERMS, getenv("TERM")) != NULL); gBuf = (char *) malloc(TEXT_BLOCK_SIZE); if (gBuf == NULL) goto panic; gNBufUsed = 0; gNBufAllocated = TEXT_BLOCK_SIZE; if (strlen(gArgsStr) < (gNBufAllocated - 1)) { strcpy(gBuf, gArgsStr); gNBufUsed = strlen(gArgsStr); } if (isatty(1)) { if (SlurpProgress(fd) < 0) goto panic; } else { if (SlurpAll(fd) < 0) goto panic; } DumpFormattedOutput(); exit(gExitStatus); panic: gDumpCmdArgs = 1; /* print cmd when there are errors */ DumpFormattedOutput(); while ((nread = read(fd, emerg, (size_t) sizeof(emerg))) > 0) (void) write(2, emerg, (size_t) nread); Wait(); exit(gExitStatus); } /* main */ /* eof ccdv.c */ --- NEW FILE: install-sh --- #!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$cpprog" # note: changed from mvprog by stephan chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi # cygwin workaround: added by st...@wa... for use with toc. if [ -f "$src".exe ] ; then src="$src.exe" dst_suffix=".exe" echo CYGWIN WORKAROUND: src=$src fi if [ x"$dir_arg" != x ]; then dst="$src" src="" if [ -d $dst ]; then instcmd=: chmodcmd="" else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f "$src" -o -d "$src" ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename "$src"` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi # cygwin workaround: if [ x"$dst_suffix" != x ]; then dst="$dst$dst_suffix" echo "CYGWIN WORKAROUND? dst=$dst" fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd "$src" $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 --- NEW FILE: removeDupeArgs --- #!/usr/bin/perl # Expects a list of command-line arguments, from which it removes any # duplicates after the first instance of any given entry. # Intended to be used to clean up INCLUDES and LDADD-like entries. # # Example: # $0 a b c b b c d e a # would print: # a b c d e %cache = (); @args = (); while( @ARGV ) { $a = $ARGV[0]; shift; next if $cache{$a}; $cache{$a} = 1; push( @args, $a ); } foreach $a (@args) { print $a," "; } print "\n"; --- NEW FILE: create_makefile_stubs.sh --- #!/bin/sh # # Generate stub Makefiles for toc. # # Usage: see help text, below dirs= x_help= while test x != "x$1" ; do arg="$1" shift case "$arg" in -?|--help|-help) x_help=1 ;; *) test -d $arg && dirs="$dirs $arg" ;; esac done # test x1 = "x$x_help" && { cat <<EOF $0: Creates stub files for a toc environment by looking at the contents of a directory. Usage: $0 dir1 [... dirN] dir1 defaults to ., which should be the \$(top_srcdir) of a project tree. For each dir it creates dir/Makefile.suggestion, containing guesses at what toc-related content might be useful in the corresponding Makefile. If called without any options then it acts RECURSIVELY on ".". It does not act recursively if called with directory arguments. This behaviour is arguable, but seems to be reasonable for the use-cases to-date (all 1.5 of them ;). EOF exit 0 } stderr () { # sends $@ to stderr echo "#" "$@" 1>&2 } slashify () { # converts file lists into a format which is more useful to Makefile maintainers. # usage: echo list | slashify perl -ne 's|\n| |g;s|\s+$||;s|\s+|%|g;s|%$|\n|;s|%| \\\n\t|g; print $_,"\n";' } ######################################################################## # check_make_XXX() conventions: # # $1 is the directory name, but they don't really need it. A chdir is # done before processing each dir, so all tests can safely assume pwd # is the directory they are responsible for checking. # # They "should" follow the naming convention check_make_XXX so they # can easily be handled in a loop using only their XXX parts. ######################################################################## ######################################################################## check_make_flexes () { # hanles *.flex echo "############## FLEXES:" export flext=flex local flexes="$(ls *.${flext} 2>/dev/null)" test x"$flexes" != "$flexes" && { stderr "Adding FLEXES" echo "# WARNING: FLEXES stuff only works for C++-based flexers" echo -n "FLEXES = " echo $flexes | sed s/\.${flext}//g echo "FLEXES_ARGS = -+ -p" for f in $flexes; do base=${f%%.${flext}} echo "${base}_FLEXES_ARGS = -P${base}" done echo -n "OBJECTS += " echo $flexes | sed s/\.${flext}/.${flext}.o/g echo "include \$(TOC_MAKESDIR)/flex.make" echo "# Run target FLEXES to process these." echo "# REMINDER: add the generated C++ files to your SOURCES, if needed." echo "############## /FLEXES" } } ######################################################################## check_make_c () { # checks for c/c++-related stuff local headers="$(ls *.h *.hpp 2>/dev/null )" test -n "$headers" && { stderr "Adding HEADERS" echo -n "HEADERS = "; echo $headers | slashify echo "DIST_FILES += \$(HEADERS)" echo "INSTALL_PACKAGE_HEADERS += \$(HEADERS)" echo } local sources="$(ls *.c *.cpp *.c++ *.C *.cxx 2>/dev/null )" test -n "$sources" && { stderr "Adding SOURCES" echo -n "SOURCES = "; echo $sources | slashify echo "DIST_FILES += \$(SOURCES)" echo -n "OBJECTS = " echo $sources | perl -pe 's|(\S+)\.\w+\s|$1.o |g' | slashify echo echo "CLEAN_FILES += \$(OBJECTS)" cat <<EOF build_libs = 0 ifeq (1,\$(build_libs)) STATIC_LIBS = thislib thislib_a_OBJECTS = \$(OBJECTS) thislib_so_OBJECTS = \$(thislib_a_OBJECTS) # thislib_so_VERSION = \$(PACKAGE_VERSION) include \$(TOC_MAKESDIR)/SHARED_LIBS.make include \$(TOC_MAKESDIR)/STATIC_LIBS.make # Run targets STATIC_LIBS and SHARED_LIBS build these. endif build_bins = 0 ifeq (1,\$(build_bins)) BIN_PROGRAMS = thisbin thisbin_bin_OBJECTS = \$(OBJECTS) include \$(TOC_MAKESDIR)/BIN_PROGRAMS.make INSTALL_BINS += \$(BIN_PROGRAMS) # Run target BIN_PROGRAMS to build these. endif EOF } #end SOURCES (and friends) } # end check_make_c ######################################################################## check_make_extra_dist () { # Add some common filenames/patterns to DIST_FILES local xtra= # reminder: toc adds Makefile to DIST_FILES by default, because it's ALWAYS needed. for x in README LICENSE NEWS ChangeLog \ *.at *.qmake \ *.sh *.pl \ *.bat \ *.txt *.TXT *.xml *.lyx \ ; do expr "$x" : '\*' >/dev/null && continue # unexpanded wildcard test -e $x || continue xtra="$xtra $x" done test -z "$xtra" && return stderr "Adding extra DIST_FILES." echo -n "DIST_FILES += " echo $xtra | slashify } ######################################################################## check_make_subdirs () { # add subdirs to SUBDIRS local ls="$(ls -d *)" test -z "$ls" && return local subs= for i in $ls; do test -d $i || continue; test "CVS" = "$i" && continue stderr "Adding SUBDIR $i" subs="$subs $i" done test -n "$subs" && echo "SUBDIRS = $subs" } # checks for existing Makefile check_make_makefile () { true } ############################################################################## # main app driver goes here: test x = "x$dirs" && { dirs="$(find . -type d | sed -e '/\/CVS/d')" } test x = "x$dirs" && { echo "Error: no subdirectories found!" exit 1 } timestamp=$(date) for d in $dirs; do cd $d >/dev/null || { err=$? echo "Error: could not cd to $d" exit $err } out=Makefile.suggestion stderr "Creating $d/$out" { cat <<EOF ################################################### # AUTO-GENERATED guess at a toc-aware Makefile, # based off of the contents of directory: # $d # Created by $0 # $timestamp # It must be tweaked to suit your needs. ################################################### include toc.make EOF for func in subdirs extra_dist flexes c ; do check_make_${func} $d done cat <<EOF all: ################################################### # end auto-generated rules ################################################### EOF } > $out cd - > /dev/null done ######################################################################## # the end ######################################################################## --- NEW FILE: mkdep.c --- /* * Originally by Linus Torvalds. * Smart CONFIG_* processing by Werner Almesberger, Michael Chastain. * * Usage: mkdep cflags -- file ... * * Read source files and output makefile dependency lines for them. * I make simple dependency lines for #include <*.h> and #include "*.h". * I also find instances of CONFIG_FOO and generate dependencies * like include/config/foo.h. * * 1 August 1999, Michael Elizabeth Chastain, <me...@sh...> * - Keith Owens reported a bug in smart config processing. There used * to be an optimization for "#define CONFIG_FOO ... #ifdef CONFIG_FOO", * so that the file would not depend on CONFIG_FOO because the file defines * this symbol itself. But this optimization is bogus! Consider this code: * "#if 0 \n #define CONFIG_FOO \n #endif ... #ifdef CONFIG_FOO". Here * the definition is inactivated, but I still used it. It turns out this * actually happens a few times in the kernel source. The simple way to * fix this problem is to remove this particular optimization. * * 2.3.99-pre1, Andrew Morton <an...@uo...> * - Changed so that 'filename.o' depends upon 'filename.[cS]'. This is so that * missing source files are noticed, rather than silently ignored. * * 2.4.2-pre3, Keith Owens <ka...@oc...> * - Accept cflags followed by '--' followed by filenames. mkdep extracts -I * options from cflags and looks in the specified directories as well as the * defaults. Only -I is supported, no attempt is made to handle -idirafter, * -isystem, -I- etc. * * Aug 2003: stephan beal <st...@s1...> * - removed HPATH requirement for use in the toc project (toc.sourceforge.net) * * Aug 2003: rusty <bo...@us...> * Other changes for use in toc/libfunUtil: * - Add support for C++ file extensions .cc, .C, .c++, .cxx, .cpp. * (Previously, this was doing "a" right thing, by making foo.c++ depend on * the headers #included by foo.c++, with a "touch foo.c++" rule which * would then cause the .o file to be out of date, but "the" right thing is * for foo.o to depend on the headers #included by foo.c++. I guess there * aren't many C++ files in the Linux kernel tree, ha ha.) * * Dec 2003: st...@s1... * Changes for toc.sourceforge.net: * - removed the default 'touch' behaviour to avoid collissions with targets * generated via toc. * * 20 Aug 2004: st...@s1... * - Removed unused hpath from main(). WTF does gcc NOW start to * complain about that!?!?!? * - Added some parens to keep gcc from bitching (again... why now? * Been compiling w/o complaint for over a year). * * */ #include <ctype.h> #include <fcntl.h> #include <limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/fcntl.h> #include <sys/mman.h> #include <sys/stat.h> #include <sys/types.h> /** TOC_MODE enables: - to 'touch'ing of targets, to avoid overriding rules defined elsewhere in toc. */ #define TOC_MODE 1 char __depname[512] = "\n\t@touch "; #define depname (__depname+9) int hasdep; struct path_struct { int len; char *buffer; }; struct path_struct *path_array; int paths; /* Current input file */ static const char *g_filename; /* * This records all the configuration options seen. * In perl this would be a hash, but here it's a long string * of values separated by newlines. This is simple and * extremely fast. */ char * str_config = NULL; int size_config = 0; int len_config = 0; static void do_depname(void) { if (!hasdep) { hasdep = 1; //printf( "depname=%s, g_filename=%s", depname, g_filename ); printf("%s:", depname); if (g_filename) printf(" %s", g_filename); } } /* * Grow the configuration string to a desired length. * Usually the first growth is plenty. */ void grow_config(int len) { while (len_config + len > size_config) { if (size_config == 0) size_config = 2048; str_config = realloc(str_config, size_config *= 2); if (str_config == NULL) { perror("malloc config"); exit(1); } } } /* * Lookup a value in the configuration string. */ int is_defined_config(const char * name, int len) { const char * pconfig; const char * plast = str_config + len_config - len; for ( pconfig = str_config + 1; pconfig < plast; pconfig++ ) { if (pconfig[ -1] == '\n' && pconfig[len] == '\n' && !memcmp(pconfig, name, len)) return 1; } return 0; } /* * Add a new value to the configuration string. */ void define_config(const char * name, int len) { grow_config(len + 1); memcpy(str_config+len_config, name, len); len_config += len; str_config[len_config++] = '\n'; } /* * Clear the set of configuration strings. */ void clear_config(void) { len_config = 0; define_config("", 0); } /* * This records all the precious .h filenames. No need for a hash, * it's a long string of values enclosed in tab and newline. */ char * str_precious = NULL; int size_precious = 0; int len_precious = 0; /* * Grow the precious string to a desired length. * Usually the first growth is plenty. */ void grow_precious(int len) { while (len_precious + len > size_precious) { if (size_precious == 0) size_precious = 2048; str_precious = realloc(str_precious, size_precious *= 2); if (str_precious == NULL) { perror("malloc"); exit(1); } } } /* * Add a new value to the precious string. */ void define_precious(const char * filename) { int len = strlen(filename); grow_precious(len + 4); *(str_precious+len_precious++) = '\t'; memcpy(str_precious+len_precious, filename, len); len_precious += len; memcpy(str_precious+len_precious, " \\\n", 3); len_precious += 3; } /* * Handle an #include line. */ void handle_include(int start, const char * name, int len) { struct path_struct *path; int i; if (len == 14 && !memcmp(name, "linux/config.h", len)) return; if (len >= 7 && !memcmp(name, "config/", 7)) define_config(name+7, len-7-2); for (i = start, path = path_array+start; i < paths; ++i, ++path) { memcpy(path->buffer+path->len, name, len); path->buffer[path->len+len] = '\0'; if (access(path->buffer, F_OK) == 0) { do_depname(); printf(" \\\n %s", path->buffer); return; } } } /* * Add a path to the list of include paths. */ void add_path(const char * name) { struct path_struct *path; char resolved_path[PATH_MAX+1]; const char *name2; if (strcmp(name, ".")) { name2 = realpath(name, resolved_path); if (!name2) { fprintf(stderr, "realpath(%s) failed, %m\n", name); exit(1); } } else { name2 = ""; } path_array = realloc(path_array, (++paths)*sizeof(*path_array)); if (!path_array) { fprintf(stderr, "cannot expand path_arry\n"); exit(1); } path = path_array+paths-1; path->len = strlen(name2); path->buffer = malloc(path->len+1+256+1); if (!path->buffer) { fprintf(stderr, "cannot allocate path buffer\n"); exit(1); } strcpy(path->buffer, name2); if (path->len && *(path->buffer+path->len-1) != '/') { *(path->buffer+path->len) = '/'; *(path->buffer+(++(path->len))) = '\0'; } } /* * Record the use of a CONFIG_* word. */ void use_config(const char * name, int len) { char *pc; int i; pc = path_array[paths-1].buffer + path_array[paths-1].len; memcpy(pc, "config/", 7); pc += 7; for (i = 0; i < len; i++) { char c = name[i]; if (isupper((int)c)) c = tolower((int)c); if (c == '_') c = '/'; pc[i] = c; } pc[len] = '\0'; if (is_defined_config(pc, len)) return; define_config(pc, len); do_depname(); printf(" \\\n $(wildcard %s.h)", path_array[paths-1].buffer); } /* * Macros for stunningly fast map-based character access. * __buf is a register which holds the current word of the input. * Thus, there is one memory access per sizeof(unsigned long) characters. */ #if defined(__alpha__) || defined(__i386__) || defined(__ia64__) || defined(__x86_64__) || defined(__MIPSEL__) \ || defined(__arm__) #define LE_MACHINE #endif #ifdef LE_MACHINE #define next_byte(x) (x >>= 8) #define current ((unsigned char) __buf) #else #define next_byte(x) (x <<= 8) #define current (__buf >> 8*(sizeof(unsigned long)-1)) #endif #define GETNEXT { \ next_byte(__buf); \ if ((unsigned long) next % sizeof(unsigned long) == 0) { \ if (next >= end) \ break; \ __buf = * (unsigned long *) next; \ } \ next++; \ } /* * State machine macros. */ #define CASE(c,label) if (current == c) goto label #define NOTCASE(c,label) if (current != c) goto label /* * Yet another state machine speedup. */ #define MAX2(a,b) ((a)>(b)?(a):(b)) #define MIN2(a,b) ((a)<(b)?(a):(b)) #define MAX5(a,b,c,d,e) (MAX2(a,MAX2(b,MAX2(c,MAX2(d,e))))) #define MIN5(a,b,c,d,e) (MIN2(a,MIN2(b,MIN2(c,MIN2(d,e))))) /* * The state machine looks for (approximately) these Perl regular expressions: * * m|\/\*.*?\*\/| * m|\/\/.*| * m|'.*?'| * m|".*?"| * m|#\s*include\s*"(.*?)"| * m|#\s*include\s*<(.*?>"| * m|#\s*(?define|undef)\s*CONFIG_(\w*)| * m|(?!\w)CONFIG_| * * About 98% of the CPU time is spent here, and most of that is in * the 'start' paragraph. Because the current characters are * in a register, the start loop usually eats 4 or 8 characters * per memory read. The MAX5 and MIN5 tests dispose of most * input characters with 1 or 2 comparisons. */ void state_machine(const char * map, const char * end) { const char * next = map; const char * map_dot; unsigned long __buf = 0; for (;;) { start: GETNEXT __start: if (current > MAX5('/','\'','"','#','C')) goto start; if (current < MIN5('/','\'','"','#','C')) goto start; CASE('/', slash); CASE('\'', squote); CASE('"', dquote); CASE('#', pound); CASE('C', cee); goto start; /* // */ slash_slash: GETNEXT CASE('\n', start); NOTCASE('\\', slash_slash); GETNEXT goto slash_slash; /* / */ slash: GETNEXT CASE('/', slash_slash); NOTCASE('*', __start); slash_star_dot_star: GETNEXT __slash_star_dot_star: NOTCASE('*', slash_star_dot_star); GETNEXT NOTCASE('/', __slash_star_dot_star); goto start; /* '.*?' */ squote: GETNEXT CASE('\'', start); NOTCASE('\\', squote); GETNEXT goto squote; /* ".*?" */ dquote: GETNEXT CASE('"', start); NOTCASE('\\', dquote); GETNEXT goto dquote; /* #\s* */ pound: GETNEXT CASE(' ', pound); CASE('\t', pound); CASE('i', pound_i); CASE('d', pound_d); CASE('u', pound_u); goto __start; /* #\s*i */ pound_i: GETNEXT NOTCASE('n', __start); GETNEXT NOTCASE('c', __start); GETNEXT NOTCASE('l', __start); GETNEXT NOTCASE('u', __start); GETNEXT NOTCASE('d', __start); GETNEXT NOTCASE('e', __start); goto pound_include; /* #\s*include\s* */ pound_include: GETNEXT CASE(' ', pound_include); CASE('\t', pound_include); map_dot = next; CASE('"', pound_include_dquote); CASE('<', pound_include_langle); goto __start; /* #\s*include\s*"(.*)" */ pound_include_dquote: GETNEXT CASE('\n', start); NOTCASE('"', pound_include_dquote); handle_include(0, map_dot, next - map_dot - 1); goto start; /* #\s*include\s*<(.*)> */ pound_include_langle: GETNEXT CASE('\n', start); NOTCASE('>', pound_include_langle); handle_include(1, map_dot, next - map_dot - 1); goto start; /* #\s*d */ pound_d: GETNEXT NOTCASE('e', __start); GETNEXT NOTCASE('f', __start); GETNEXT NOTCASE('i', __start); GETNEXT NOTCASE('n', __start); GETNEXT NOTCASE('e', __start); goto pound_define_undef; /* #\s*u */ pound_u: GETNEXT NOTCASE('n', __start); GETNEXT NOTCASE('d', __start); GETNEXT NOTCASE('e', __start); GETNEXT NOTCASE('f', __start); goto pound_define_undef; /* * #\s*(define|undef)\s*CONFIG_(\w*) * * this does not define the word, because it could be inside another * conditional (#if 0). But I do parse the word so that this instance * does not count as a use. -- mec */ pound_define_undef: GETNEXT CASE(' ', pound_define_undef); CASE('\t', pound_define_undef); NOTCASE('C', __start); GETNEXT NOTCASE('O', __start); GETNEXT NOTCASE('N', __start); GETNEXT NOTCASE('F', __start); GETNEXT NOTCASE('I', __start); GETNEXT NOTCASE('G', __start); GETNEXT NOTCASE('_', __start); map_dot = next; pound_define_undef_CONFIG_word: GETNEXT if (isalnum(current) || current == '_') goto pound_define_undef_CONFIG_word; goto __start; /* \<CONFIG_(\w*) */ cee: if (next >= map+2 && (isalnum((int)next[-2]) || next[-2] == '_')) goto start; GETNEXT NOTCASE('O', __start); GETNEXT NOTCASE('N', __start); GETNEXT NOTCASE('F', __start); GETNEXT NOTCASE('I', __start); GETNEXT NOTCASE('G', __start); GETNEXT NOTCASE('_', __start); map_dot = next; cee_CONFIG_word: GETNEXT if (isalnum(current) || current == '_') goto cee_CONFIG_word; use_config(map_dot, next - map_dot - 1); goto __start; } } /* * Generate dependencies for one file. */ void do_depend(const char * filename, const char * command) { int mapsize; int pagesizem1 = getpagesize()-1; int fd; struct stat st; char * map; fd = open(filename, O_RDONLY); if (fd < 0) { perror(filename); return; } fstat(fd, &st); if (st.st_size == 0) { fprintf(stderr,"%s is empty\n",filename); close(fd); return; } mapsize = st.st_size; mapsize = (mapsize+pagesizem1) & ~pagesizem1; map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0); if ((long) map == -1) { perror("mkdep: mmap"); close(fd); return; } if ((unsigned long) map % sizeof(unsigned long) != 0) { fprintf(stderr, "do_depend: map not aligned\n"); exit(1); } hasdep = 0; clear_config(); state_machine(map, map+st.st_size); if (hasdep) { puts(command); if (*command) define_precious(filename); } munmap(map, mapsize); close(fd); } /* * Generate dependencies for all files. */ int main(int argc, char **argv) { int len; add_path("."); /* for #include "..." */ while (++argv, --argc > 0) { if (strncmp(*argv, "-I", 2) == 0) { if (*((*argv)+2) ) { add_path((*argv)+2); } else { ++argv; --argc; } } else if (strcmp(*argv, "--") == 0) { break; } } while (--argc > 0) { const char * filename = *++argv; #if TOC_MODE const char * command = ""; #else const char * command = __depname; #endif g_filename = 0; len = strlen(filename); memcpy(depname, filename, len+1); if (len > 2 && filename[len-2] == '.') { if (filename[len-1] == 'c' || filename[len-1] == 'S' || filename[len-1] == 'C') { depname[len-1] = 'o'; g_filename = filename; command = ""; } } else if (len > 3 && filename[len-3] == '.') { if (filename[len-2] == 'c' && filename[len-1] == 'c') { depname[len-2] = 'o'; depname[len-1] = '\0'; g_filename = filename; command = ""; } } else if (len > 4 && filename[len-4] == '.') { if ( filename[len-3] == 'c' && // check for c++/cxx/cpp ( (filename[len-2] == '+' && filename[len-1] == '+') || (filename[len-2] == 'x' && filename[len-1] == 'x') || (filename[len-2] == 'p' && filename[len-1] == 'p') ) ) { depname[len-3] = 'o'; depname[len-2] = '\0'; g_filename = filename; command = ""; } } do_depend(filename, command); } if (len_precious) { *(str_precious+len_precious) = '\0'; printf(".PRECIOUS:%s\n", str_precious); } return 0; } --- NEW FILE: getMakefileVar --- #!/usr/bin/perl # tries to parse out a value of a var from a Makefile # it does no var expansion, nor file inclusion, nor # anything fancy. One potential use is pulling out # vars from qmake-generated makefiles so they can # be used in more maintainable ways in other places. $var = $ARGV[0]; die "Usage: $0 VARNAME [makefile]" unless $var; $mf = $ARGV[1] || "Makefile"; die "Cannot find $mf!" unless -f $mf; open( INFILE, "<$mf" ) or die "Cannot open $mf!"; while( INFILE && ($line !~ m|^$var|) ) { $line = <INFILE>; if( eof INFILE ) { $line = 0; last; } } if( ! $line ) { exit 127; } $theval = $line; $theval =~ s|^.*=\s*||; #print ">>>theval=$theval\n"; while( $theval =~ m|\\$| ) { $theval =~ s|\\||g; #print ">>>theval=$theval\n"; #print "val=$thevalue"; $line = <INFILE>; chomp( $line ); $theval .= $line; last unless $line =~ m|\\$|; } $theval =~ s| \\\s*| |mg; $theval =~ s/\s+/ /mg; $theval =~ s/^\s+//mg; $theval =~ s/\s+$//mg; close( INFILE ); exit 1 if ! $theval; print $theval."\n"; |