Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
333 dpurdie 1
/* $XConsortium: include.c /main/18 1995/12/08 18:26:35 gildea $ */
2
/*
3
 
4
Copyright (c) 1993, 1994  X Consortium
5
 
6
Permission is hereby granted, free of charge, to any person obtaining a copy
7
of this software and associated documentation files (the "Software"), to deal
8
in the Software without restriction, including without limitation the rights
9
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
copies of the Software, and to permit persons to whom the Software is
11
furnished to do so, subject to the following conditions:
12
 
13
The above copyright notice and this permission notice shall be included in
14
all copies or substantial portions of the Software.
15
 
16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
19
X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
 
23
Except as contained in this notice, the name of the X Consortium shall not be
24
used in advertising or otherwise to promote the sale, use or other dealings
25
in this Software without prior written authorization from the X Consortium.
26
 
27
*/
28
 
29
 
30
#include "def.h"
31
 
32
extern struct   inclist inclist[ MAXFILES ],
33
                *inclistp;
34
extern char     *includedirs[ ];
35
extern char     *notdotdot[ ];
36
extern boolean  show_where_not;
37
extern boolean  warn_multiple;
38
 
39
struct inclist *inc_path(file, include, dot)
40
        register char   *file,
41
                        *include;
42
        boolean dot;
43
{
44
        static char     path[ MAX_PATH+1 ];
45
        register char   **pp, *p;
46
        register struct inclist *ip;
47
        struct stat     st;
48
        boolean found = FALSE;
49
 
50
/*        inc_dump(); */
51
        /*
52
         * Check all previously found include files for a path that
53
         * has already been expanded.
54
         */
55
        for (ip = inclist; ip->i_file; ip++)
56
        {
57
            if ((strcmp(ip->i_incstring, include) == 0) /* && !(ip->i_flags & INCLUDED_SYM) */ )
58
            {
59
 
60
                /*
61
                **  Previously the inc_path function would return NOT FOUND unless the
62
                **  INCLUDED_SYM flag was not set. This would result in multiple entries
63
                **  being created and this would result in elements being missed in
64
                **  the dependancy list.
65
                **
66
                **  The INCLUDED_SYM flag is set when a file #includes another file
67
                **  through the use of a macro name. ie: #include TIME_LIBRARY
68
                **
69
                **  Not sure why INCLUDED_SYM need to be cleared
70
                **  Possibly there are cases where different source files might include
71
                **  different #defines and different included files.
72
                **
73
                **  Whatever. The program will misbehave. It will get the wrong list
74
                **  of dependancies.
75
                **
76
                **  Perhaps the Symbolic entries need to be killed after processing
77
                **  each major source file.
78
                **
79
                **  Generate a debug message for potential future use
80
                */
81
                if ( (ip->i_flags & INCLUDED_SYM) )
82
                {
83
                    if ( !(ip->i_flags & INCLUDED_SYMW) )
84
                    {
85
                        warning( "Symbolic include file included by: %s\n", include );
86
                        ip->i_flags |= INCLUDED_SYMW;
87
                    }
88
                }
89
                found = TRUE;
90
                break;
91
            }
92
        }
93
 
94
        /*
95
         * If the path was surrounded by "" or is an absolute path,
96
         * then check the exact path provided.
97
         */
98
        if (!found && (dot || *include == '/')) {
99
                if ((stat(include, &st) == 0) && ( !S_ISDIR(st.st_mode))) {
100
                        ip = newinclude(include, include);
101
                        found = TRUE;
102
                }
103
                else if (show_where_not)
104
                        warning1("\tnot in %s\n", include);
105
        }
106
 
107
        /*
108
         * If the path was surrounded by "" see if this include file is in the
109
         * directory of the file being parsed.
110
         */
111
        if (!found && dot) {
112
                for (p=file+strlen(file); p>file; p--)
113
                        if (*p == '/')
114
                                break;
115
                if (p == file)
116
                        strcpy(path, include);
117
                else {
118
                        strncpy(path, file, (p-file) + 1);
119
                        path[ (p-file) + 1 ] = '\0';
120
                        strcpy(path + (p-file) + 1, include);
121
                }
122
                remove_dotdot(path);
123
                if ((stat(path, &st) == 0) && ( !S_ISDIR(st.st_mode))) {
124
                        ip = newinclude(path, include);
125
                        found = TRUE;
126
                }
127
                else if (show_where_not)
128
                        warning1("\tnot in %s\n", path);
129
        }
130
 
131
        /*
132
         * Check the include directories specified. (standard include dir
133
         * should be at the end.)
134
         */
135
        if (!found)
136
                for (pp = includedirs; *pp; pp++) {
137
                        sprintf(path, "%s/%s", *pp, include);
138
                        remove_dotdot(path);
139
                        if ((stat(path, &st) == 0) && ( !S_ISDIR(st.st_mode))) {
140
                                ip = newinclude(path, include);
141
                                found = TRUE;
142
                                break;
143
                        }
144
                        else if (show_where_not)
145
                                warning1("\tnot in %s\n", path);
146
                }
147
 
148
        if (!found)
149
                ip = NULL;
150
        return(ip);
151
}
152
 
153
/*
154
 * Occasionally, pathnames are created that look like .../x/../y
155
 * Any of the 'x/..' sequences within the name can be eliminated.
156
 * (but only if 'x' is not a symbolic link!!)
157
 */
158
remove_dotdot(path)
159
        char            *path;
160
{
161
        register char   *end, *from, *to, **cp;
162
        char            *components[ MAX_PATH+1 ],
163
                        newpath[ MAX_PATH+1 ];
164
        boolean         component_copied;
165
 
166
        /*
167
         *     slice path up into components.
168
         */
169
        to = newpath;
170
        if (*path == '/')
171
                *to++ = '/';
172
        *to = '\0';
173
        cp = components;
174
        for (from=end=path; *end; end++)
175
                if (*end == '/') {
176
                        while (*end == '/')
177
                                *end++ = '\0';
178
                        if (*from)
179
                                *cp++ = from;
180
                        from = end;
181
                        if (*end == '\0')
182
                                break;  /* handle paths with trailing '/' */
183
               }
184
        *cp++ = from;
185
        *cp = NULL;
186
 
187
        /*
188
         * Recursively remove all 'x/..' component pairs.
189
         */
190
        cp = components;
191
        while (*cp) {
192
                if (!isdot(*cp) && !isdotdot(*cp) && isdotdot(*(cp+1))
193
                        && !issymbolic(newpath, *cp))
194
                {
195
                    char **fp = cp+2;
196
                    char **tp = cp;
197
 
198
                    do 
199
                        *tp++ = *fp; /* move all the pointers down */
200
                    while (*fp++);
201
                    *tp = NULL;      
202
                    if (cp != components)
203
                        cp--;        /* go back and check for nested ".." */
204
                } else {
205
                    cp++;
206
                }
207
        }
208
 
209
        /*
210
         * Concatenate the remaining path elements.
211
         */
212
        cp = components;
213
        component_copied = FALSE;
214
        while (*cp) {
215
                if (component_copied)
216
                        *to++ = '/';
217
                component_copied = TRUE;
218
                for (from = *cp; *from;)
219
                        *to++ = *from++;
220
                *to = '\0';
221
                cp++;
222
        }
223
        *to++ = '\0';
224
 
225
        /*
226
         * copy the reconstituted path back to our pointer.
227
         */
228
        strcpy(path, newpath);
229
        return (0);
230
}
231
 
232
isdot(p)
233
        register char   *p;
234
{
235
        if(p && *p++ == '.' && *p++ == '\0')
236
                return(TRUE);
237
        return(FALSE);
238
}
239
 
240
isdotdot(p)
241
        register char   *p;
242
{
243
        if(p && *p++ == '.' && *p++ == '.' && *p++ == '\0')
244
                return(TRUE);
245
        return(FALSE);
246
}
247
 
248
issymbolic(dir, component)
249
        register char   *dir, *component;
250
{
251
#ifdef S_IFLNK
252
        struct stat     st;
253
        char            buf[ MAX_PATH+1 ], **pp;
254
 
255
        sprintf(buf, "%s%s%s", dir, *dir ? "/" : "", component);
256
        for (pp=notdotdot; *pp; pp++)
257
                if (strcmp(*pp, buf) == 0)
258
                        return (TRUE);
259
        if (lstat(buf, &st) == 0
260
        && (st.st_mode & S_IFMT) == S_IFLNK) {
261
                *pp++ = copy(buf);
262
                if (pp >= &notdotdot[ MAXDIRS ])
263
                        fatalerr("out of .. dirs, increase MAXDIRS\n");
264
                return(TRUE);
265
        }
266
#else
267
        (void) dir, component; 
268
#endif
269
        return(FALSE);
270
}
271
 
272
/*
273
 * Add an include file to the list of those included by 'file'.
274
 */
275
struct inclist *newinclude(newfile, incstring)
276
        register char   *newfile, *incstring;
277
{
278
        register struct inclist *ip;
279
 
280
        /*
281
         * First, put this file on the global list of include files.
282
         */
283
        ip = inclistp++;
284
        if (inclistp >= inclist + MAXFILES - 1)
285
                fatalerr("out of space: increase MAXFILES\n");
286
        ip->i_file = copy(newfile);
287
 
288
        /*
289
         * add to file list
290
         */
291
        if (incstring == NULL)
292
                ip->i_incstring = ip->i_file;
293
        else 
294
                ip->i_incstring = copy(incstring);
295
        return(ip);
296
}
297
 
298
 
299
void
300
included_by(ip, newfile)
301
        register struct inclist *ip, *newfile;
302
{
303
        register i;
304
 
305
        if (ip == NULL)
306
                return;
307
        /*
308
         * Put this include file (newfile) on the list of files included
309
         * by 'file'.  If 'file' is NULL, then it is not an include
310
         * file itself (i.e. was probably mentioned on the command line).
311
         * If it is already on the list, don't stick it on again.
312
         */
313
        if (ip->i_list == NULL) {
314
                ip->i_list = (struct inclist **)
315
                        malloc(sizeof(struct inclist *) * ++ip->i_listlen);
316
                ip->i_merged = (boolean *)
317
                    malloc(sizeof(boolean) * ip->i_listlen);
318
        } else {
319
                for (i=0; i<ip->i_listlen; i++)
320
                        if (ip->i_list[ i ] == newfile) {
321
                            i = strlen(newfile->i_file);
322
                            if (!(ip->i_flags & INCLUDED_SYM) &&
323
                                !(i > 2 &&
324
                                  newfile->i_file[i-1] == 'c' &&
325
                                  newfile->i_file[i-2] == '.'))
326
                            {
327
                                /* only bitch if ip has */
328
                                /* no #include SYMBOL lines  */
329
                                /* and is not a .c file */
330
                                if (warn_multiple)
331
                                {
332
                                        warning("%s includes %s more than once!\n",
333
                                                ip->i_file, newfile->i_file);
334
                                        warning1("Already have\n");
335
                                        for (i=0; i<ip->i_listlen; i++)
336
                                                warning1("\t%s\n", ip->i_list[i]->i_file);
337
                                }
338
                            }
339
                            return;
340
                        }
341
                ip->i_list = (struct inclist **) realloc(ip->i_list,
342
                        sizeof(struct inclist *) * ++ip->i_listlen);
343
                ip->i_merged = (boolean *)
344
                        realloc(ip->i_merged, sizeof(boolean) * ip->i_listlen);
345
        }
346
        ip->i_list[ ip->i_listlen-1 ] = newfile;
347
        ip->i_merged[ ip->i_listlen-1 ] = FALSE;
348
        return;
349
}
350
 
351
 
352
void
353
inc_clean ()
354
{
355
        register struct inclist *ip;
356
 
357
        for (ip = inclist; ip < inclistp; ip++) {
358
                ip->i_flags &= ~MARKED;
359
        }
360
        return;
361
}
362
 
363
void inc_dump(void)
364
{
365
#ifdef DEBUG
366
    register struct inclist *ip;
367
    int i;
368
 
369
    if ( ! _debugmask )
370
        return;
371
 
372
    for (ip = inclist; ip < inclistp; ip++)
373
    {
374
        debug (1,( "####Dump Include Entry: %s\n", ip->i_file ));
375
        for (i = 0; i < ip->i_listlen; i++)
376
            debug(1,("####Dump \t%s\n", ip->i_list[ i ]->i_incstring));
377
    }
378
    debug (1,( "####End Dump\n" ));
379
#endif
380
}
381