1/*
2
3Copyright (c) 1993, 1994, 1998 The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25*/
26
27#include "def.h"
28
29void
30add_include(struct filepointer *filep, struct inclist *file,
31            struct inclist *file_red, const char *include, int type,
32            boolean failOK)
33{
34    struct inclist *newfile;
35
36    /*
37     * First decide what the pathname of this include file really is.
38     */
39    newfile = inc_path(file->i_file, include, type);
40    if (newfile == NULL) {
41        if (failOK)
42            return;
43        if (file != file_red)
44            warning("%s (reading %s, line %ld): ",
45                    file_red->i_file, file->i_file, filep->f_line);
46        else
47            warning("%s, line %ld: ", file->i_file, filep->f_line);
48        warning1("cannot find include file \"%s\"\n", include);
49        show_where_not = TRUE;
50        newfile = inc_path(file->i_file, include, type);
51        show_where_not = FALSE;
52    }
53
54    if (newfile) {
55        included_by(file, newfile);
56        if (!(newfile->i_flags & SEARCHED)) {
57            struct filepointer *content;
58
59            newfile->i_flags |= SEARCHED;
60            content = getfile(newfile->i_file);
61            find_includes(content, newfile, file_red, 0, failOK);
62            freefile(content);
63        }
64    }
65}
66
67/**
68 * Replaces all ":" occurrences in @p input with "\:" using @p outputbuffer (of size @p bufsize)
69 * possibly to hold the result. @p returns the string with quoted colons
70 */
71static const char *
72quoteColons(const char *input, char *outputbuffer, size_t bufsize)
73{
74    const char *tmp;
75    const char *loc;
76    char *output = outputbuffer;
77
78    loc = strchr(input, ':');
79    if (loc == NULL) {
80        return input;
81    }
82
83    tmp = input;
84    while (loc != NULL && bufsize > loc - tmp + 2) {
85        memcpy(output, tmp, loc - tmp);
86        output += loc - tmp;
87        bufsize -= loc - tmp + 2;
88        tmp = loc + 1;
89        *output = '\\';
90        output++;
91        *output = ':';
92        output++;
93        loc = strchr(tmp, ':');
94    }
95
96    if (strlen(tmp) <= bufsize)
97        strcpy(output, tmp);
98    else {
99        strncpy(output, tmp, bufsize - 1);
100        output[bufsize] = 0;
101    }
102    return outputbuffer;
103}
104
105static void
106pr(struct inclist *ip, const char *file, const char *base)
107{
108    static const char *lastfile;
109    static int current_len;
110    int len;
111    const char *quoted;
112    char quotebuf[BUFSIZ];
113
114    printed = TRUE;
115    quoted = quoteColons(ip->i_file, quotebuf, sizeof(quotebuf));
116    len = strlen(quoted) + 1;
117    if (current_len + len > width || file != lastfile) {
118        lastfile = file;
119        current_len = fprintf(stdout, "\n%s%s%s: %s",
120                              objprefix, base, objsuffix, quoted);
121    }
122    else {
123        fprintf(stdout, " %s", quoted);
124        current_len += len;
125    }
126
127    /*
128     * If verbose is set, then print out what this file includes.
129     */
130    if (!verbose || ip->i_list == NULL || ip->i_flags & NOTIFIED)
131        return;
132    ip->i_flags |= NOTIFIED;
133    lastfile = NULL;
134    printf("\n# %s includes:", ip->i_file);
135    for (unsigned int i = 0; i < ip->i_listlen; i++)
136        printf("\n#\t%s", ip->i_list[i]->i_incstring);
137}
138
139void
140recursive_pr_include(struct inclist *head, const char *file, const char *base)
141{
142    if (head->i_flags & MARKED)
143        return;
144    head->i_flags |= MARKED;
145    if (head->i_file != file)
146        pr(head, file, base);
147    for (unsigned int i = 0; i < head->i_listlen; i++)
148        recursive_pr_include(head->i_list[i], file, base);
149}
150