include.cpp

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

Generated on Thu Nov 20 04:28:44 2008 for HOOPLE Libraries by  doxygen 1.5.1