Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!pilchuck!amc!stan From: stan@amc.UUCP (Stan Tazuma) Newsgroups: comp.sources.bugs Subject: Re: ID cross-ref programs fix Message-ID: <543@amc.UUCP> Date: Fri, 30-Oct-87 22:23:56 EST Article-I.D.: amc.543 Posted: Fri Oct 30 22:23:56 1987 Date-Received: Thu, 5-Nov-87 00:08:21 EST References: <854@cadre.dsl.PITTSBURGH.EDU> <99@piring.cwi.nl> Reply-To: stan@amc.UUCP (Stan Tazuma) Organization: Applied Microsystems Corp., Redmond, WA. Lines: 265 Summary: more fixes In article <99@piring.cwi.nl> guido@cwi.nl (Guido van Rossum) writes: >the ID file is a directory higher up in the hierarchy -- spanPath ends >up appending an infinite series of "../" to a buffer. > >I can't offer a fix -- I must say I don't understand exactly what the >code is doing there, and maybe neither is the author, or the problem >which the patch was supposed to fix wouldn't have occurred. Undoing the >patch was enough for me. I spent some time on it and I think I've got the proper fix for the slash problem. First, do not use the previous slash fix posted by Jack Nelson (the mods to paths.c/skipJunk()). Instead, put the following lines at the beginning of paths.c/spanPath() (right after the declarations). if (arg[0] == '/') { /* don't need to span full pathnames */ strcpy(pathBuf, arg); return(pathBuf); } The code is complicated because of an attempt to handle different situations involving the location of the ID database, and of where the files specified in the database are actually located. There is code to search for the ID database. Depending on where it finds it, it prefixes one or more "../" strings in front of file names. The fix by Jack Nelson does cause an infinite loop, but not normally in the loop which prefixes "../" (at least for my tests). It looped in the "for (;;)" loop because a leading '/' causes argLength to be 0, which makes the strnequ(...) (alias strncmp()) to act as though the strings matched, when in fact they were different. --------------------------------------------- For a usable version of the id package, install the above change, plus the fixes posted by Tim Walters (opening files) and Ian Donaldson (fix for eid to prevent ^C from killing it). The package works quite well now and my thanks go to the author, Greg Mcgary. Following are some possibly interesting and/or useful enhancements that I also use. They probably depend on your having 4.[23]bsd or equivalent (Ultrix), including Sun OS 3.4 (maybe any of 3.x). ============================================= Greg apparently didn't see much need for full pathnames, hence the fact the original code didn't support it. However, consider setting up a database for many local files, but also wanting identifiers in system include files in the database. Normally you might run mkid with the following args: mkid *.[ch] But that doesn't account for the system include files. Here's a script which will pull those in also (it depends on your cc(1) supporting the -M option, which generates makefile dependency lines). ---------------mkflist--------------cut here #! /bin/sh # script for listing all the include files for the specified source # files. Also lists the specified source files. # This was written for use with the id system (mkid). # Note: "cc -M" might not work everywhere. # -- Stan Tazuma 10/30/87 if test $# = 0 then echo "Usage: $0 [ cc args ] source-files ..." echo Examples: echo " $0 *.c" echo " $0 -I. *.c" echo " mkid \`$0 *.c\`" exit 1 fi cc -M $@ | sed -e 's/.*: //' -e 's;^\./;;' | sort | uniq # The one below lists all the local .h files first, then all the full # pathname'd include files, then all the .c files. The one above # inter-mingles the local .h and .c files. # cc -M $@ | sed 's/.*: //' | sort | uniq | sed 's;^\./;;' ---------------end of mkflist--------------cut here ================================================================== Another subject. The ID database uses a (partly) binary format. This makes it byte-order dependent. In a networked (NFS) environment this is a problem. Yes one could re-build the database when needed, but when just browsing you wouldn't want to do that. Here's a solution which works in a Sun/VAX environment. It depends on the assumption that the only byte order dependent part of the database is in the idhead struct which gets written at the beginning of the database. A byte for byte comparison of Sun and VAX databases showed the differences were confined here. Here are the relevant changes. (My files have a bunch of RCS stuff in them, which I deleted from below. The line numbers below will vary from the original source. Hopefully the context is sufficient.) ------id.h changes--------------- RCS file: id.h,v retrieving revision 1.1 retrieving revision 1.3 diff -c -r1.1 -r1.3 *** /tmp/,RCSt1022558 Fri Oct 30 18:35:00 1987 --- /tmp/,RCSt2022558 Fri Oct 30 18:35:02 1987 *************** *** 1,13 **** --- 1,35 ---- #define IDFILE "ID" + #define COMMON_FILE_FORMAT /* use an ID file which is the same on + * a VAX or a SUN (and other similar + * architectures) */ + struct idhead { char idh_magic[2]; /* magic number */ #define IDH_MAGIC "\311\304" /* magic-number ("ID" with hi bits) */ short idh_vers; /* id-file version number */ + #if ! defined(COMMON_FILE_FORMAT) #define IDH_VERS 2 /* current version */ + #else + #define IDH_VERS 3 /* to prevent destruction of existing + * databases */ + #endif int idh_argc; /* # of args for mkid update */ int idh_pthc; /* # of paths for mkid update */ int idh_namc; /* # of identifiers */ ------init.c changes--------------- RCS file: init.c,v retrieving revision 1.1 retrieving revision 1.2 diff -c -r1.1 -r1.2 *** /tmp/,RCSt1022489 Fri Oct 30 18:26:21 1987 --- /tmp/,RCSt2022489 Fri Oct 30 18:26:22 1987 *************** *** 22,27 **** --- 29,37 ---- fseek(idFILE, 0L, 0); fread(idhp, sizeof(struct idhead), 1, idFILE); + #ifdef COMMON_FILE_FORMAT + massage_in(idhp); + #endif if (!strnequ(idhp->idh_magic, IDH_MAGIC, sizeof(idhp->idh_magic))) { fprintf(stderr, "%s: Not an id file: `%s'\n", MyName, idFile); exit(1); ------mkid.c changes--------------- RCS file: mkid.c,v retrieving revision 1.1 retrieving revision 1.2 diff -c -r1.1 -r1.2 *** /tmp/,RCSt1022500 Fri Oct 30 18:28:01 1987 --- /tmp/,RCSt2022500 Fri Oct 30 18:28:02 1987 *************** *** 378,384 **** --- 385,402 ---- strncpy(idh.idh_magic, IDH_MAGIC, sizeof(idh.idh_magic)); idh.idh_vers = IDH_VERS; fseek(idFILE, 0L, 0); + #ifdef COMMON_FILE_FORMAT + { + struct idhead midh; + extern void massage_out(); + + midh = idh; + massage_out(&midh); + fwrite(&midh, sizeof(struct idhead), 1, idFILE); + } + #else fwrite(&idh, sizeof(struct idhead), 1, idFILE); + #endif fclose(idFILE); } *************** *** 413,418 **** --- 431,439 ---- } idModTime = statBuf.st_mtime; fread(&idh, sizeof(struct idhead), 1, idFILE); + #ifdef COMMON_FILE_FORMAT + massage_in(&idh); + #endif if (!strnequ(idh.idh_magic, IDH_MAGIC, sizeof(idh.idh_magic))) { fprintf(stderr, "%s: Not an id file: `%s'\n", MyName, idFile); exit(1); *************** *** 478,483 **** --- 499,507 ---- if ((idFILE = fopen(idFile, "r")) == NULL) filerr("open", idFile); fread(&idh, sizeof(struct idhead), 1, idFILE); + #ifdef COMMON_FILE_FORMAT + massage_in(&idh); + #endif entry = malloc(idh.idh_bsiz); ---end of diffs------------------------------------------------------------ Also needed is massage.c: ----------------------cut here---------------- #include "id.h" #ifdef COMMON_FILE_FORMAT /* next two are for htons(), etc. defines */ #include #include /* * Convert the idhead structure to a common format, in preparation for * writing to a file for storage. * The established "network" order is used (as defined in 4.[23]bsd Unix). */ void massage_out(idh) register struct idhead *idh; { idh->idh_vers = (short) htons(idh->idh_vers); idh->idh_argc = (int) htonl(idh->idh_argc); idh->idh_pthc = (int) htonl(idh->idh_pthc); idh->idh_namc = (int) htonl(idh->idh_namc); idh->idh_vecc = (int) htonl(idh->idh_vecc); idh->idh_bsiz = (int) htonl(idh->idh_bsiz); idh->idh_argo = (long) htonl(idh->idh_argo); idh->idh_namo = (long) htonl(idh->idh_namo); idh->idh_endo = (long) htonl(idh->idh_endo); return; } /* * Convert the idhead structure to a common format, after reading the * structure from a file (which is assumed to be using the common * file format). * The established "network" order is used (as defined in 4.[23]bsd Unix). */ void massage_in(idh) register struct idhead *idh; { idh->idh_vers = (short) ntohs(idh->idh_vers); idh->idh_argc = (int) ntohl(idh->idh_argc); idh->idh_pthc = (int) ntohl(idh->idh_pthc); idh->idh_namc = (int) ntohl(idh->idh_namc); idh->idh_vecc = (int) ntohl(idh->idh_vecc); idh->idh_bsiz = (int) ntohl(idh->idh_bsiz); idh->idh_argo = (long) ntohl(idh->idh_argo); idh->idh_namo = (long) ntohl(idh->idh_namo); idh->idh_endo = (long) ntohl(idh->idh_endo); return; } #endif COMMON_FILE_FORMAT ---------------------------------cut here-------------------- To the makefile, add "massage.o" to the list of OFILES. You should also add the output of "cc -M -I. *.c" to the end of the makefile. That way make will notice that when a header file changes the corresponding source files will be re-built. Another change I would make to the source is to use #include "...." for local (in current directory) include files rather than #include <...>. That way -I. wouldn't have to used (in the makefile and with mkflist). For those who don't have htons(), etc., those are used to convert to/from a "network" byte order. They are normally just used in programs dealing with networking. The "network" byte order is that of 680x0's. Stan Tazuma Applied Microsystems Corp. ...uw-beaver!tikal!amc!stan