Back to index

lightning-sunbird  0.9+nobinonly
include.c
Go to the documentation of this file.
00001 /* $Xorg: include.c,v 1.4 2001/02/09 02:03:16 xorgcvs Exp $ */
00002 /*
00003 
00004 Copyright (c) 1993, 1994, 1998 The Open Group
00005 
00006 Permission to use, copy, modify, distribute, and sell this software and its
00007 documentation for any purpose is hereby granted without fee, provided that
00008 the above copyright notice appear in all copies and that both that
00009 copyright notice and this permission notice appear in supporting
00010 documentation.
00011 
00012 The above copyright notice and this permission notice shall be included in
00013 all copies or substantial portions of the Software.
00014 
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
00018 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00019 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00020 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00021 
00022 Except as contained in this notice, the name of The Open Group shall not be
00023 used in advertising or otherwise to promote the sale, use or other dealings
00024 in this Software without prior written authorization from The Open Group.
00025 
00026 */
00027 /* $XFree86: xc/config/makedepend/include.c,v 3.7 2001/12/14 19:53:20 dawes Exp $ */
00028 
00029 
00030 #include "def.h"
00031 
00032 #ifdef _MSC_VER
00033 #include <windows.h>
00034 static int
00035 does_file_exist(char *file)
00036 {
00037   WIN32_FILE_ATTRIBUTE_DATA data;
00038   BOOL b = GetFileAttributesExA(file, GetFileExInfoStandard, &data);
00039   if (!b)
00040     return 0;
00041   return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
00042 }
00043 #else
00044 static int
00045 does_file_exist(char *file)
00046 {
00047   struct stat sb;
00048   return stat(file, &sb) == 0 && !S_ISDIR(sb.st_mode);
00049 }
00050 #endif
00051 
00052 extern struct inclist       inclist[ MAXFILES ],
00053                      *inclistp, *inclistnext;
00054 extern char   *includedirs[ ],
00055               **includedirsnext;
00056 extern char   *notdotdot[ ];
00057 extern boolean show_where_not;
00058 extern boolean warn_multiple;
00059 
00060 static boolean
00061 isdot(char *p)
00062 {
00063        if(p && *p++ == '.' && *p++ == '\0')
00064               return(TRUE);
00065        return(FALSE);
00066 }
00067 
00068 static boolean
00069 isdotdot(char *p)
00070 {
00071        if(p && *p++ == '.' && *p++ == '.' && *p++ == '\0')
00072               return(TRUE);
00073        return(FALSE);
00074 }
00075 
00076 static boolean
00077 issymbolic(char *dir, char *component)
00078 {
00079 #ifdef S_IFLNK
00080        struct stat   st;
00081        char   buf[ BUFSIZ ], **pp;
00082 
00083        sprintf(buf, "%s%s%s", dir, *dir ? "/" : "", component);
00084        for (pp=notdotdot; *pp; pp++)
00085               if (strcmp(*pp, buf) == 0)
00086                      return (TRUE);
00087        if (lstat(buf, &st) == 0
00088        && (st.st_mode & S_IFMT) == S_IFLNK) {
00089               *pp++ = copy(buf);
00090               if (pp >= &notdotdot[ MAXDIRS ])
00091                      fatalerr("out of .. dirs, increase MAXDIRS\n");
00092               return(TRUE);
00093        }
00094 #endif
00095        return(FALSE);
00096 }
00097 
00098 /*
00099  * Occasionally, pathnames are created that look like .../x/../y
00100  * Any of the 'x/..' sequences within the name can be eliminated.
00101  * (but only if 'x' is not a symbolic link!!)
00102  */
00103 static void
00104 remove_dotdot(char *path)
00105 {
00106        register char *end, *from, *to, **cp;
00107        char          *components[ MAXFILES ],
00108                      newpath[ BUFSIZ ];
00109        boolean              component_copied;
00110 
00111        /*
00112         * slice path up into components.
00113         */
00114        to = newpath;
00115        if (*path == '/')
00116               *to++ = '/';
00117        *to = '\0';
00118        cp = components;
00119        for (from=end=path; *end; end++)
00120               if (*end == '/') {
00121                      while (*end == '/')
00122                             *end++ = '\0';
00123                      if (*from)
00124                             *cp++ = from;
00125                      from = end;
00126               }
00127        *cp++ = from;
00128        *cp = NULL;
00129 
00130        /*
00131         * Recursively remove all 'x/..' component pairs.
00132         */
00133        cp = components;
00134        while(*cp) {
00135               if (!isdot(*cp) && !isdotdot(*cp) && isdotdot(*(cp+1))
00136                   && !issymbolic(newpath, *cp))
00137               {
00138                   char **fp = cp + 2;
00139                   char **tp = cp;
00140 
00141                   do 
00142                      *tp++ = *fp; /* move all the pointers down */
00143                   while (*fp++);
00144                   if (cp != components)
00145                      cp--;  /* go back and check for nested ".." */
00146               } else {
00147                   cp++;
00148               }
00149        }
00150        /*
00151         * Concatenate the remaining path elements.
00152         */
00153        cp = components;
00154        component_copied = FALSE;
00155        while(*cp) {
00156               if (component_copied)
00157                      *to++ = '/';
00158               component_copied = TRUE;
00159               for (from = *cp; *from; )
00160                      *to++ = *from++;
00161               *to = '\0';
00162               cp++;
00163        }
00164        *to++ = '\0';
00165 
00166        /*
00167         * copy the reconstituted path back to our pointer.
00168         */
00169        strcpy(path, newpath);
00170 }
00171 
00172 /*
00173  * Add an include file to the list of those included by 'file'.
00174  */
00175 struct inclist *
00176 newinclude(char *newfile, char *incstring)
00177 {
00178        register struct inclist     *ip;
00179 
00180        /*
00181         * First, put this file on the global list of include files.
00182         */
00183        ip = inclistp++;
00184        if (inclistp == inclist + MAXFILES - 1)
00185               fatalerr("out of space: increase MAXFILES\n");
00186        ip->i_file = copy(newfile);
00187 
00188        if (incstring == NULL)
00189               ip->i_incstring = ip->i_file;
00190        else
00191               ip->i_incstring = copy(incstring);
00192 
00193        inclistnext = inclistp;
00194        return(ip);
00195 }
00196 
00197 void
00198 included_by(struct inclist *ip, struct inclist *newfile)
00199 {
00200        register int i;
00201 
00202        if (ip == NULL)
00203               return;
00204        /*
00205         * Put this include file (newfile) on the list of files included
00206         * by 'file'.  If 'file' is NULL, then it is not an include
00207         * file itself (i.e. was probably mentioned on the command line).
00208         * If it is already on the list, don't stick it on again.
00209         */
00210        if (ip->i_list == NULL) {
00211               ip->i_list = (struct inclist **)
00212                      malloc(sizeof(struct inclist *) * ++ip->i_listlen);
00213               ip->i_merged = (boolean *)
00214                   malloc(sizeof(boolean) * ip->i_listlen);
00215        } else {
00216               for (i=0; i<ip->i_listlen; i++)
00217                      if (ip->i_list[ i ] == newfile) {
00218                          i = strlen(newfile->i_file);
00219                          if (!(ip->i_flags & INCLUDED_SYM) &&
00220                             !(i > 2 &&
00221                               newfile->i_file[i-1] == 'c' &&
00222                               newfile->i_file[i-2] == '.'))
00223                          {
00224                             /* only bitch if ip has */
00225                             /* no #include SYMBOL lines  */
00226                             /* and is not a .c file */
00227                             if (warn_multiple)
00228                             {
00229                                    warning("%s includes %s more than once!\n",
00230                                           ip->i_file, newfile->i_file);
00231                                    warning1("Already have\n");
00232                                    for (i=0; i<ip->i_listlen; i++)
00233                                           warning1("\t%s\n", ip->i_list[i]->i_file);
00234                             }
00235                          }
00236                          return;
00237                      }
00238               ip->i_list = (struct inclist **) realloc(ip->i_list,
00239                      sizeof(struct inclist *) * ++ip->i_listlen);
00240               ip->i_merged = (boolean *)
00241                   realloc(ip->i_merged, sizeof(boolean) * ip->i_listlen);
00242        }
00243        ip->i_list[ ip->i_listlen-1 ] = newfile;
00244        ip->i_merged[ ip->i_listlen-1 ] = FALSE;
00245 }
00246 
00247 void
00248 inc_clean (void)
00249 {
00250        register struct inclist *ip;
00251 
00252        for (ip = inclist; ip < inclistp; ip++) {
00253               ip->i_flags &= ~MARKED;
00254        }
00255 }
00256 
00257 struct inclist *
00258 inc_path(char *file, char *include, int type)
00259 {
00260        static char          path[ BUFSIZ ];
00261        register char        **pp, *p;
00262        register struct inclist     *ip;
00263 
00264        /*
00265         * Check all previously found include files for a path that
00266         * has already been expanded.
00267         */
00268        if ((type == INCLUDE) || (type == INCLUDEDOT))
00269               inclistnext = inclist;
00270        ip = inclistnext;
00271 
00272        for (; ip->i_file; ip++) {
00273               if ((strcmp(ip->i_incstring, include) == 0) &&
00274                   !(ip->i_flags & INCLUDED_SYM)) {
00275                      inclistnext = ip + 1;
00276                      return ip;
00277               }
00278        }
00279 
00280        if (inclistnext == inclist) {
00281               /*
00282                * If the path was surrounded by "" or is an absolute path,
00283                * then check the exact path provided.
00284                */
00285               if ((type == INCLUDEDOT) ||
00286                   (type == INCLUDENEXTDOT) ||
00287                   (*include == '/')) {
00288                      if (does_file_exist(include))
00289                             return newinclude(include, include);
00290                      if (show_where_not)
00291                             warning1("\tnot in %s\n", include);
00292               }
00293 
00294               /*
00295                * If the path was surrounded by "" see if this include file is
00296                * in the directory of the file being parsed.
00297                */
00298               if ((type == INCLUDEDOT) || (type == INCLUDENEXTDOT)) {
00299                      for (p=file+strlen(file); p>file; p--)
00300                             if (*p == '/')
00301                                    break;
00302                      if (p == file) {
00303                             strcpy(path, include);
00304                      } else {
00305                             strncpy(path, file, (p-file) + 1);
00306                             path[ (p-file) + 1 ] = '\0';
00307                             strcpy(path + (p-file) + 1, include);
00308                      }
00309                      remove_dotdot(path);
00310                      if (does_file_exist(path))
00311                             return newinclude(path, include);
00312                      if (show_where_not)
00313                             warning1("\tnot in %s\n", path);
00314               }
00315        }
00316 
00317        /*
00318         * Check the include directories specified.  Standard include dirs
00319         * should be at the end.
00320         */
00321        if ((type == INCLUDE) || (type == INCLUDEDOT))
00322               includedirsnext = includedirs;
00323        pp = includedirsnext;
00324 
00325        for (; *pp; pp++) {
00326               sprintf(path, "%s/%s", *pp, include);
00327               remove_dotdot(path);
00328               if (does_file_exist(path)) {
00329                      includedirsnext = pp + 1;
00330                      return newinclude(path, include);
00331               }
00332               if (show_where_not)
00333                      warning1("\tnot in %s\n", path);
00334        }
00335 
00336        return NULL;
00337 }