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