xref: /trunk/main/soltools/cpp/_include.c (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 #if (defined(_WIN32) || defined(_MSDOS) || defined(__IBMC__))
23 #   include <io.h>
24 #else
25 #   include <unistd.h>
26 #endif
27 
28 #ifdef _MSC_VER
29 #   define _POSIX_
30 #endif
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <fcntl.h>
35 
36 
37 #ifdef __hpux
38 #   define _HPUX_SOURCE
39 #endif
40 #if defined(__IBMC__) || defined(__EMX__)
41 #   include <fcntl.h>
42 #   define PATH_MAX _MAX_PATH
43 #endif
44 #include <limits.h>
45 
46 /*  The Microsoft C runtime used to define PATH_MAX in <limits.h> when _POSIX_
47     was defined, which is what the block at the top of this file is for.  The
48     UCRT -- VS2015 and every toolset since -- no longer does, and _POSIX_ no
49     longer selects anything, so PATH_MAX simply is not declared and the arrays
50     below become zero-sized.
51 
52     512 is the value the old runtime supplied, and it is kept rather than
53     substituting _MAX_PATH (260, as the __IBMC__ branch above does): the
54     buffers here hold an include directory concatenated with a file name, and
55     260 is not enough for that inside this tree's own output directories.  The
56     uses are all bounds-checked against sizeof, so the size is a limit rather
57     than a hazard -- but narrowing it would silently start rejecting includes
58     that resolve today.
59 
60     Inert wherever <limits.h> supplies a PATH_MAX of its own, VC9 included.  */
61 #ifndef PATH_MAX
62 #   define PATH_MAX 512
63 #endif
64 
65 #include "cpp.h"
66 
67 Includelist includelist[NINCLUDE];
68 Wraplist wraplist[NINCLUDE];
69 
70 void
doinclude(Tokenrow * trp,int depth,int import)71     doinclude(Tokenrow * trp, int depth, int import)
72 {
73     char fname[PATH_MAX], iname[PATH_MAX];
74     Includelist *ip;
75     int angled, fd, i;
76     size_t len;
77 
78     trp->tp += 1;
79     if (trp->tp >= trp->lp)
80         goto syntax;
81     if (trp->tp->type != STRING && trp->tp->type != LT)
82     {
83         len = trp->tp - trp->bp;
84         expandrow(trp, "<include>");
85         trp->tp = trp->bp + len;
86     }
87     if (trp->tp->type == STRING)
88     {
89         len = trp->tp->len - 2;
90         if (len > sizeof(fname) - 1)
91             len = sizeof(fname) - 1;
92         strncpy(fname, (char *) trp->tp->t + 1, len);
93         angled = 0;
94     }
95     else
96     {
97         if (trp->tp->type == LT)
98         {
99             len = 0;
100             trp->tp++;
101             while (trp->tp->type != GT)
102             {
103                 if (trp->tp > trp->lp || len + trp->tp->len + 2 >= sizeof(fname))
104                     goto syntax;
105                 strncpy(fname + len, (char *) trp->tp->t, trp->tp->len);
106                 len += trp->tp->len;
107                 trp->tp++;
108             }
109             angled = 1;
110         }
111         else
112             goto syntax;
113     }
114     trp->tp += 2;
115     if (trp->tp < trp->lp || len == 0)
116         goto syntax;
117     fname[len] = '\0';
118     if (fname[0] == '/')
119     {
120         fd = open(fname, O_RDONLY);
121         strcpy(iname, fname);
122     }
123     else
124     {
125         for (fd = -1, i = (depth < 0) ? (NINCLUDE - 1) : (depth - 1); i >= 0; i--)
126         {
127             ip = &includelist[i];
128             if (ip->file == NULL || ip->deleted || (angled && ip->always == 0))
129                 continue;
130             if (strlen(fname) + strlen(ip->file) + 2 > sizeof(iname))
131                 continue;
132             strcpy(iname, ip->file);
133             strcat(iname, "/");
134             strcat(iname, fname);
135             if ((fd = open(iname, O_RDONLY)) >= 0)
136                 break;
137         }
138     }
139 
140     if (fd >= 0)
141     {
142         if (++incdepth > NINC )
143             error(FATAL, "#%s too deeply nested", import ? "import" : "include");
144         if (Xflag)
145             genimport(fname, angled, iname, import);
146         if (Iflag)
147             error(INFO, "Open %s file [%s]", import ? "import" : "include", iname );
148 
149         for (i = NINCLUDE - 1; i >= 0; i--)
150         {
151             if ((wraplist[i].file != NULL) &&
152                 (strncmp(wraplist[i].file, iname, strlen(wraplist[i].file)) == 0))
153                 break;
154         }
155 
156         setsource((char *) newstring((uchar *) iname, strlen(iname), 0), i, fd, NULL, (i >= 0) ? 1 : 0);
157 
158         if (!Pflag)
159             genline();
160     }
161     else
162     {
163         trp->tp = trp->bp + 2;
164         error(ERROR, "Could not find %s file %r", import ? "import" : "include", trp);
165     }
166     return;
167 syntax:
168     error(ERROR, "Syntax error in #%s", import ? "import" : "include");
169     return;
170 }
171 
172 /*
173  * Generate a line directive for cursource
174  */
175 void
genline(void)176     genline(void)
177 {
178     static Token ta = {UNCLASS, 0, 0, 0, NULL, 0};
179     static Tokenrow tr = {&ta, &ta, &ta + 1, 1};
180     uchar *p;
181 
182     ta.t = p = (uchar *) outptr;
183     strcpy((char *) p, "#line ");
184     p += sizeof("#line ") - 1;
185     p = (uchar *) outnum((char *) p, cursource->line);
186     *p++ = ' ';
187     *p++ = '"';
188     if (cursource->filename[0] != '/' && wd[0])
189     {
190         strcpy((char *) p, wd);
191         p += strlen(wd);
192         *p++ = '/';
193     }
194     strcpy((char *) p, cursource->filename);
195     p += strlen((char *) p);
196     *p++ = '"';
197     *p++ = '\n';
198     ta.len = (char *) p - outptr;
199     outptr = (char *) p;
200     tr.tp = tr.bp;
201     puttokens(&tr);
202 }
203 
204 /*
205  * Generate a pragma import/include directive
206  */
207 void
genimport(char * fname,int angled,char * iname,int import)208     genimport(char *fname, int angled, char *iname, int import)
209 {
210     static Token ta = {UNCLASS, 0, 0, 0, NULL, 0};
211     static Tokenrow tr = {&ta, &ta, &ta + 1, 1};
212     uchar *p;
213 
214     ta.t = p = (uchar *) outptr;
215 
216     if (import)
217         strcpy((char *) p, "#pragma import");
218     else
219         strcpy((char *) p, "#pragma include");
220 
221     p += strlen((char *) p);
222 
223     *p++ = '(';
224 
225     *p++ = angled ? '<' : '"';
226     strcpy((char *) p, fname);
227     p += strlen(fname);
228     *p++ = angled ? '>' : '"';
229 
230     *p++ = ',';
231 
232     *p++ = '"';
233     strcpy((char *) p, iname);
234     p += strlen(iname);
235     *p++ = '"';
236 
237     *p++ = ')';
238     *p++ = '\n';
239 
240     ta.len = (char *) p - outptr;
241     outptr = (char *) p;
242     tr.tp = tr.bp;
243     puttokens(&tr);
244 }
245 
246 /*
247  * Generate a extern C directive
248  */
249 void
genwrap(int end)250     genwrap(int end)
251 {
252     static Token ta = {UNCLASS, 0, 0, 0, NULL, 0};
253     static Tokenrow tr = {&ta, &ta, &ta + 1, 1};
254     uchar *p;
255 
256     if (Cplusplus)
257     {
258         ta.t = p = (uchar *) outptr;
259 
260         if (! end)
261             strcpy((char *) p, "extern \"C\" {");
262         else
263             strcpy((char *) p, "}");
264 
265         p += strlen((char *) p);
266 
267         *p++ = '\n';
268 
269         ta.len = (char *) p - outptr;
270         outptr = (char *) p;
271         tr.tp = tr.bp;
272         puttokens(&tr);
273     }
274 }
275