include.c

Go to the documentation of this file.
00001 /* $XConsortium: include.c /main/20 1996/12/04 10:11:18 swick $ */
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 
00030 #include "def.h"
00031 
00032 #ifdef __SUNPRO_C
00033 extern int lstat();
00034 #endif
00035 
00036 extern struct inclist inclist[ MAXFILES ],
00037             *inclistp;
00038 extern char *includedirs[ ];
00039 extern char *notdotdot[ ];
00040 extern boolean show_where_not;
00041 extern boolean warn_multiple;
00042 
00043 
00044 boolean
00045 isdot(p)
00046 register char *p;
00047 {
00048    if (p && *p++ == '.' && *p++ == '\0')
00049       return(TRUE);
00050    return(FALSE);
00051 }
00052 
00053 boolean
00054 isdotdot(p)
00055 register char *p;
00056 {
00057    if (p && *p++ == '.' && *p++ == '.' && *p++ == '\0')
00058       return(TRUE);
00059    return(FALSE);
00060 }
00061 
00062 boolean
00063 issymbolic(dir, component)
00064 register char *dir, *component;
00065 {
00066 #ifdef S_IFLNK
00067    struct stat st;
00068    char buf[ BUFSIZ ], **pp;
00069 
00070    sprintf(buf, "%s%s%s", dir, *dir ? "/" : "", component);
00071    for (pp = notdotdot; *pp; pp++)
00072       if (strcmp(*pp, buf) == 0)
00073          return (TRUE);
00074    if (lstat(buf, &st) == 0
00075          && (st.st_mode & S_IFMT) == S_IFLNK) {
00076       *pp++ = copy(buf);
00077       if (pp >= &notdotdot[ MAXDIRS ])
00078          fatalerr("out of .. dirs, increase MAXDIRS\n");
00079       return(TRUE);
00080    }
00081 #else
00082    if (dir && component) { }  /* use arguments */
00083 #endif
00084    return(FALSE);
00085 }
00086 
00087 /*
00088  * Occasionally, pathnames are created that look like .../x/../y
00089  * Any of the 'x/..' sequences within the name can be eliminated.
00090  * (but only if 'x' is not a symbolic link!!)
00091  */
00092 void
00093 remove_dotdot(path)
00094 char *path;
00095 {
00096    register char *end, *from, *to, **cp;
00097    char  *components[ MAXFILES ],
00098    newpath[ BUFSIZ ];
00099    boolean  component_copied;
00100 
00101    /*
00102     * slice path up into components.
00103     */
00104    to = newpath;
00105    if (*path == '/')
00106       *to++ = '/';
00107    *to = '\0';
00108    cp = components;
00109    for (from = end = path; *end; end++)
00110       if (*end == '/') {
00111          while (*end == '/')
00112             *end++ = '\0';
00113          if (*from)
00114             *cp++ = from;
00115          from = end;
00116       }
00117    *cp++ = from;
00118    *cp = NULL;
00119 
00120    /*
00121     * Recursively remove all 'x/..' component pairs.
00122     */
00123    cp = components;
00124    while (*cp) {
00125       if (!isdot(*cp) && !isdotdot(*cp) && isdotdot(*(cp + 1))
00126             && !issymbolic(newpath, *cp)) {
00127          char **fp = cp + 2;
00128          char **tp = cp;
00129 
00130          do
00131             *tp++ = *fp; /* move all the pointers down */
00132          while (*fp++);
00133          if (cp != components)
00134             cp--; /* go back and check for nested ".." */
00135       } else {
00136          cp++;
00137       }
00138    }
00139    /*
00140     * Concatenate the remaining path elements.
00141     */
00142    cp = components;
00143    component_copied = FALSE;
00144    while (*cp) {
00145       if (component_copied)
00146          *to++ = '/';
00147       component_copied = TRUE;
00148       for (from = *cp; *from;)
00149          *to++ = *from++;
00150       *to = '\0';
00151       cp++;
00152    }
00153    *to++ = '\0';
00154 
00155    /*
00156     * copy the reconstituted path back to our pointer.
00157     */
00158    strcpy(path, newpath);
00159 }
00160 
00161 /*
00162  * Add an include file to the list of those included by 'file'.
00163  */
00164 struct inclist *newinclude(newfile, incstring)
00165          register char *newfile, *incstring;
00166 {
00167    register struct inclist *ip;
00168 
00169    /*
00170     * First, put this file on the global list of include files.
00171     */
00172    ip = inclistp++;
00173    if (inclistp == inclist + MAXFILES - 1)
00174       fatalerr("out of space: increase MAXFILES\n");
00175    ip->i_file = copy(newfile);
00176 
00177    if (incstring == NULL)
00178       ip->i_incstring = ip->i_file;
00179    else
00180       ip->i_incstring = copy(incstring);
00181 
00182    return(ip);
00183 }
00184 
00185 void
00186 included_by(ip, newfile)
00187 register struct inclist *ip, *newfile;
00188 {
00189    register int i;
00190 
00191    if (ip == NULL)
00192       return;
00193    /*
00194     * Put this include file (newfile) on the list of files included
00195     * by 'file'.  If 'file' is NULL, then it is not an include
00196     * file itself (i.e. was probably mentioned on the command line).
00197     * If it is already on the list, don't stick it on again.
00198     */
00199    if (ip->i_list == NULL) {
00200       ip->i_list = (struct inclist **)
00201                    malloc(sizeof(struct inclist *) * ++ip->i_listlen);
00202       ip->i_merged = (boolean *)
00203                      malloc(sizeof(boolean) * ip->i_listlen);
00204    } else {
00205       for (i = 0; i < ip->i_listlen; i++)
00206          if (ip->i_list[ i ] == newfile) {
00207             i = strlen(newfile->i_file);
00208             if (!(ip->i_flags & INCLUDED_SYM) &&
00209                   !(i > 2 &&
00210                     newfile->i_file[i-1] == 'c' &&
00211                     newfile->i_file[i-2] == '.')) {
00212                /* only bitch if ip has */
00213                /* no #include SYMBOL lines  */
00214                /* and is not a .c file */
00215                if (warn_multiple) {
00216                   warning("%s includes %s more than once!\n",
00217                           ip->i_file, newfile->i_file);
00218                   warning1("Already have\n");
00219                   for (i = 0; i < ip->i_listlen; i++)
00220                      warning1("\t%s\n", ip->i_list[i]->i_file);
00221                }
00222             }
00223             return;
00224          }
00225       ip->i_list = (struct inclist **) realloc(ip->i_list,
00226                    sizeof(struct inclist *) * ++ip->i_listlen);
00227       ip->i_merged = (boolean *)
00228                      realloc(ip->i_merged, sizeof(boolean) * ip->i_listlen);
00229    }
00230    ip->i_list[ ip->i_listlen-1 ] = newfile;
00231    ip->i_merged[ ip->i_listlen-1 ] = FALSE;
00232 }
00233 
00234 void
00235 inc_clean()
00236 {
00237    register struct inclist *ip;
00238 
00239    for (ip = inclist; ip < inclistp; ip++) {
00240       ip->i_flags &= ~MARKED;
00241       ip->i_flags &= ~SEARCHED;
00242       undefine_all(ip);
00243    }
00244 }
00245 
00246 struct inclist *inc_path(char *file, char *include, boolean dot) {
00247    static char path[ BUFSIZ ];
00248    register char  **pp, *p;
00249    register struct inclist *ip;
00250    struct stat st;
00251    boolean found = FALSE;
00252 
00253    /*
00254     * Check all previously found include files for a path that
00255     * has already been expanded.
00256     */
00257    for (ip = inclist; ip->i_file; ip++)
00258       if ((strcmp(ip->i_incstring, include) == 0) &&
00259             !(ip->i_flags & INCLUDED_SYM)) {
00260          found = TRUE;
00261          break;
00262       }
00263 
00264    /*
00265     * If the path was surrounded by "" or is an absolute path,
00266     * then check the exact path provided.
00267     */
00268    if (!found && (dot || *include == '/')) {
00269 #ifdef _WIN32
00270       if (stat(include, &st) == 0 && (st.st_mode & S_IFREG)) {
00271 #else
00272       if (stat(include, &st) == 0 && S_ISREG(st.st_mode)) {
00273 #endif
00274          ip = newinclude(include, include);
00275          found = TRUE;
00276       } else if (show_where_not)
00277          warning1("\tnot in %s\n", include);
00278    }
00279 
00280    /*
00281     * If the path was surrounded by "" see if this include file is in the
00282     * directory of the file being parsed.
00283     */
00284    if (!found && dot) {
00285       for (p = file + strlen(file); p > file; p--)
00286          if (*p == '/')
00287             break;
00288       if (p == file) {
00289          strncpy(path, include, sizeof(path) - 1);
00290          path[sizeof(path)-1] = '\0';
00291       } else {
00292          strncpy(path, file, (p - file) + 1);
00293          path[(p-file) + 1] = '\0';
00294          strncpy(path + (p - file) + 1, include, sizeof(path) - (p - file + 1));
00295       }
00296       remove_dotdot(path);
00297 #ifdef _WIN32
00298       if (stat(path, &st) == 0 && (st.st_mode & S_IFREG)) {
00299 #else
00300       if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) {
00301 #endif
00302          ip = newinclude(path, include);
00303          found = TRUE;
00304       } else if (show_where_not)
00305          warning1("\tnot in %s\n", path);
00306    }
00307 
00308    /*
00309     * Check the include directories specified. (standard include dir
00310     * should be at the end.)
00311     */
00312    if (!found)
00313       for (pp = includedirs; *pp; pp++) {
00314          if (strlen(*pp) + strlen(include) + 2 > sizeof(path)) {
00315             warning1("\t%s/%s too long\n", *pp, include);
00316             continue;
00317          }
00318          sprintf(path, "%s/%s", *pp, include);
00319          remove_dotdot(path);
00320 #ifdef _WIN32
00321          if (stat(path, &st) == 0 && (st.st_mode & S_IFREG)) {
00322 #else
00323          if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) {
00324 #endif
00325             ip = newinclude(path, include);
00326             found = TRUE;
00327             break;
00328          } else if (show_where_not)
00329             warning1("\tnot in %s\n", path);
00330       }
00331 
00332    if (!found)
00333       ip = NULL;
00334    return(ip);
00335 }

Generated on Tue Jul 5 14:10:17 2011 for ROOT_528-00b_version by  doxygen 1.5.1