| File: | src/libexec/tradcpp/files.c |
| Warning: | line 287, column 4 Value stored to 'nextlinestart' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /*- |
| 2 | * Copyright (c) 2010, 2013 The NetBSD Foundation, Inc. |
| 3 | * All rights reserved. |
| 4 | * |
| 5 | * This code is derived from software contributed to The NetBSD Foundation |
| 6 | * by David A. Holland. |
| 7 | * |
| 8 | * Redistribution and use in source and binary forms, with or without |
| 9 | * modification, are permitted provided that the following conditions |
| 10 | * are met: |
| 11 | * 1. Redistributions of source code must retain the above copyright |
| 12 | * notice, this list of conditions and the following disclaimer. |
| 13 | * 2. Redistributions in binary form must reproduce the above copyright |
| 14 | * notice, this list of conditions and the following disclaimer in the |
| 15 | * documentation and/or other materials provided with the distribution. |
| 16 | * |
| 17 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
| 18 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
| 19 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 20 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
| 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 27 | * POSSIBILITY OF SUCH DAMAGE. |
| 28 | */ |
| 29 | |
| 30 | #include <stdio.h> |
| 31 | #include <stdlib.h> |
| 32 | #include <string.h> |
| 33 | #include <unistd.h> |
| 34 | #include <fcntl.h> |
| 35 | #include <errno(*__errno()).h> |
| 36 | |
| 37 | #include "bool.h" |
| 38 | #include "array.h" |
| 39 | #include "mode.h" |
| 40 | #include "place.h" |
| 41 | #include "files.h" |
| 42 | #include "directive.h" |
| 43 | |
| 44 | struct incdir { |
| 45 | const char *name; |
| 46 | bool issystem; |
| 47 | }; |
| 48 | |
| 49 | DECLARRAY(incdir, static UNUSED)struct incdirarray { struct array arr; }; static __attribute__ ((__unused__)) struct incdirarray *incdirarray_create(void); static __attribute__((__unused__)) void incdirarray_destroy(struct incdirarray *a); static __attribute__((__unused__)) void incdirarray_init (struct incdirarray *a); static __attribute__((__unused__)) void incdirarray_cleanup(struct incdirarray *a); static __attribute__ ((__unused__)) unsigned incdirarray_num(const struct incdirarray *a); static __attribute__((__unused__)) struct incdir *incdirarray_get (const struct incdirarray *a, unsigned index_); static __attribute__ ((__unused__)) void incdirarray_set(struct incdirarray *a, unsigned index_, struct incdir *val); static __attribute__((__unused__ )) void incdirarray_setsize(struct incdirarray *a, unsigned num ); static __attribute__((__unused__)) void incdirarray_add(struct incdirarray *a, struct incdir *val, unsigned *index_ret); static __attribute__((__unused__)) void incdirarray_insert(struct incdirarray *a, unsigned index_); static __attribute__((__unused__)) void incdirarray_remove(struct incdirarray *a, unsigned index_); |
| 50 | DEFARRAY(incdir, static)static void incdirarray_init(struct incdirarray *a) { array_init (&a->arr); } static void incdirarray_cleanup(struct incdirarray *a) { array_cleanup(&a->arr); } static struct incdirarray *incdirarray_create(void) { struct incdirarray *a; a = domalloc (sizeof(*a)); incdirarray_init(a); return a; } static void incdirarray_destroy (struct incdirarray *a) { incdirarray_cleanup(a); dofree(a, sizeof (*a)); } static unsigned incdirarray_num(const struct incdirarray *a) { return array_num(&a->arr); } static struct incdir * incdirarray_get(const struct incdirarray *a, unsigned index_ ) { return (struct incdir *)array_get(&a->arr, index_) ; } static void incdirarray_set(struct incdirarray *a, unsigned index_, struct incdir *val) { array_set(&a->arr, index_ , (void *)val); } static void incdirarray_setsize(struct incdirarray *a, unsigned num) { array_setsize(&a->arr, num); } static void incdirarray_add(struct incdirarray *a, struct incdir *val , unsigned *ret) { array_add(&a->arr, (void *)val, ret ); } static void incdirarray_insert(struct incdirarray *a, unsigned index_) { array_insert(&a->arr, index_); } static void incdirarray_remove(struct incdirarray *a, unsigned index_) { array_remove(&a->arr, index_); }; |
| 51 | |
| 52 | static struct incdirarray quotepath, bracketpath; |
| 53 | |
| 54 | //////////////////////////////////////////////////////////// |
| 55 | // management |
| 56 | |
| 57 | static |
| 58 | struct incdir * |
| 59 | incdir_create(const char *name, bool issystem) |
| 60 | { |
| 61 | struct incdir *id; |
| 62 | |
| 63 | id = domalloc(sizeof(*id)); |
| 64 | id->name = name; |
| 65 | id->issystem = issystem; |
| 66 | return id; |
| 67 | } |
| 68 | |
| 69 | static |
| 70 | void |
| 71 | incdir_destroy(struct incdir *id) |
| 72 | { |
| 73 | dofree(id, sizeof(*id)); |
| 74 | } |
| 75 | |
| 76 | void |
| 77 | files_init(void) |
| 78 | { |
| 79 | incdirarray_init("epath); |
| 80 | incdirarray_init(&bracketpath); |
| 81 | } |
| 82 | |
| 83 | DESTROYALL_ARRAY(incdir, )void incdirarray_destroyall(struct incdirarray *arr); void incdirarray_destroyall (struct incdirarray *arr) { unsigned i, num; struct incdir *t ; num = incdirarray_num(arr); for (i=0; i<num; i++) { t = incdirarray_get (arr, i); incdir_destroy(t); } incdirarray_setsize(arr, 0); }; |
| 84 | |
| 85 | void |
| 86 | files_cleanup(void) |
| 87 | { |
| 88 | incdirarray_destroyall("epath); |
| 89 | incdirarray_cleanup("epath); |
| 90 | incdirarray_destroyall(&bracketpath); |
| 91 | incdirarray_cleanup(&bracketpath); |
| 92 | } |
| 93 | |
| 94 | //////////////////////////////////////////////////////////// |
| 95 | // path setup |
| 96 | |
| 97 | void |
| 98 | files_addquotepath(const char *dir, bool issystem) |
| 99 | { |
| 100 | struct incdir *id; |
| 101 | |
| 102 | id = incdir_create(dir, issystem); |
| 103 | incdirarray_add("epath, id, NULL((void*)0)); |
| 104 | } |
| 105 | |
| 106 | void |
| 107 | files_addbracketpath(const char *dir, bool issystem) |
| 108 | { |
| 109 | struct incdir *id; |
| 110 | |
| 111 | id = incdir_create(dir, issystem); |
| 112 | incdirarray_add(&bracketpath, id, NULL((void*)0)); |
| 113 | } |
| 114 | |
| 115 | //////////////////////////////////////////////////////////// |
| 116 | // parsing |
| 117 | |
| 118 | /* |
| 119 | * Find the end of the logical line. End of line characters that are |
| 120 | * commented out do not count. |
| 121 | */ |
| 122 | static |
| 123 | size_t |
| 124 | findeol(const char *buf, size_t start, size_t limit) |
| 125 | { |
| 126 | size_t i; |
| 127 | int incomment = 0; |
| 128 | bool inquote = false0; |
| 129 | char quote = '\0'; |
| 130 | |
| 131 | for (i=start; i<limit; i++) { |
| 132 | if (incomment) { |
| 133 | if (i+1 < limit && buf[i] == '*' && buf[i+1] == '/') { |
| 134 | i++; |
| 135 | incomment = 0; |
| 136 | } |
| 137 | } else if (!inquote && i+1 < limit && |
| 138 | buf[i] == '/' && buf[i+1] == '*') { |
| 139 | i++; |
| 140 | incomment = 1; |
| 141 | } else if (i+1 < limit && |
| 142 | buf[i] == '\\' && buf[i+1] != '\n') { |
| 143 | i++; |
| 144 | } else if (!inquote && (buf[i] == '"' || buf[i] == '\'')) { |
| 145 | inquote = true1; |
| 146 | quote = buf[i]; |
| 147 | } else if (inquote && buf[i] == quote) { |
| 148 | inquote = false0; |
| 149 | } else if (buf[i] == '\n') { |
| 150 | return i; |
| 151 | } |
| 152 | } |
| 153 | return limit; |
| 154 | } |
| 155 | |
| 156 | static |
| 157 | unsigned |
| 158 | countnls(const char *buf, size_t start, size_t limit) |
| 159 | { |
| 160 | size_t i; |
| 161 | unsigned count = 0; |
| 162 | |
| 163 | for (i=start; i<limit; i++) { |
| 164 | if (buf[i] == '\n') { |
| 165 | count++; |
| 166 | if (count == 0) { |
| 167 | /* just return the max and error downstream */ |
| 168 | return count - 1; |
| 169 | } |
| 170 | } |
| 171 | } |
| 172 | return count; |
| 173 | } |
| 174 | |
| 175 | static |
| 176 | void |
| 177 | file_read(const struct placefile *pf, int fd, const char *name, bool toplevel) |
| 178 | { |
| 179 | struct lineplace places; |
| 180 | struct place ptmp; |
| 181 | size_t bufend, bufmax, linestart, lineend, nextlinestart, tmp; |
| 182 | ssize_t result; |
| 183 | bool ateof = false0; |
| 184 | char *buf; |
| 185 | |
| 186 | place_setfilestart(&places.current, pf); |
| 187 | places.nextline = places.current; |
| 188 | |
| 189 | if (name) { |
| 190 | debuglog(&places.current, "Reading file %s", name); |
| 191 | } else { |
| 192 | debuglog(&places.current, "Reading standard input"); |
| 193 | } |
| 194 | |
| 195 | bufmax = 128; |
| 196 | bufend = 0; |
| 197 | linestart = 0; |
| 198 | lineend = 0; |
| 199 | buf = domalloc(bufmax); |
| 200 | |
| 201 | while (1) { |
| 202 | if (lineend >= bufend) { |
| 203 | /* do not have a whole line in the buffer; read more */ |
| 204 | assert(bufend >= linestart)((bufend >= linestart) ? (void)0 : __assert2("/usr/src/libexec/tradcpp/files.c" , 204, __func__, "bufend >= linestart")); |
| 205 | if (linestart > 0 && bufend > linestart) { |
| 206 | /* slide to beginning of buffer */ |
| 207 | memmove(buf, buf+linestart, bufend-linestart); |
| 208 | bufend -= linestart; |
| 209 | lineend -= linestart; |
| 210 | linestart = 0; |
| 211 | } |
| 212 | if (bufend >= bufmax) { |
| 213 | /* need bigger buffer */ |
| 214 | buf = dorealloc(buf, bufmax, bufmax*2); |
| 215 | bufmax = bufmax*2; |
| 216 | /* just in case someone's screwing around */ |
| 217 | if (bufmax > 0xffffffff) { |
| 218 | complain(&places.current, |
| 219 | "Input line too long"); |
| 220 | die(); |
| 221 | } |
| 222 | } |
| 223 | |
| 224 | if (ateof) { |
| 225 | /* don't read again, in case it's a socket */ |
| 226 | result = 0; |
| 227 | } else { |
| 228 | result = read(fd, buf+bufend, bufmax - bufend); |
| 229 | } |
| 230 | |
| 231 | if (result == -1) { |
| 232 | /* read error */ |
| 233 | complain(NULL((void*)0), "%s: %s", |
| 234 | name, strerror(errno(*__errno()))); |
| 235 | complain_fail(); |
| 236 | } else if (result == 0 && bufend == linestart) { |
| 237 | /* eof */ |
| 238 | ateof = true1; |
| 239 | break; |
| 240 | } else if (result == 0) { |
| 241 | /* eof in middle of line */ |
| 242 | ateof = true1; |
| 243 | ptmp = places.current; |
| 244 | place_addcolumns(&ptmp, bufend - linestart); |
| 245 | if (buf[bufend - 1] == '\n') { |
| 246 | complain(&ptmp, "Unclosed comment"); |
| 247 | complain_fail(); |
| 248 | } else { |
| 249 | complain(&ptmp, |
| 250 | "No newline at end of file"); |
| 251 | } |
| 252 | if (mode.werror) { |
| 253 | complain_fail(); |
| 254 | } |
| 255 | assert(bufend < bufmax)((bufend < bufmax) ? (void)0 : __assert2("/usr/src/libexec/tradcpp/files.c" , 255, __func__, "bufend < bufmax")); |
| 256 | lineend = bufend++; |
| 257 | buf[lineend] = '\n'; |
| 258 | } else { |
| 259 | bufend += (size_t)result; |
| 260 | lineend = findeol(buf, linestart, bufend); |
| 261 | } |
| 262 | /* loop in case we still don't have a whole line */ |
| 263 | continue; |
| 264 | } |
| 265 | |
| 266 | /* have a line */ |
| 267 | assert(buf[lineend] == '\n')((buf[lineend] == '\n') ? (void)0 : __assert2("/usr/src/libexec/tradcpp/files.c" , 267, __func__, "buf[lineend] == '\\n'")); |
| 268 | buf[lineend] = '\0'; |
| 269 | nextlinestart = lineend+1; |
| 270 | place_addlines(&places.nextline, 1); |
| 271 | |
| 272 | /* check for CR/NL */ |
| 273 | if (lineend > 0 && buf[lineend-1] == '\r') { |
| 274 | buf[lineend-1] = '\0'; |
| 275 | lineend--; |
| 276 | } |
| 277 | |
| 278 | /* check for continuation line */ |
| 279 | if (lineend > 0 && buf[lineend-1]=='\\') { |
| 280 | lineend--; |
| 281 | tmp = nextlinestart - lineend; |
| 282 | if (bufend > nextlinestart) { |
| 283 | memmove(buf+lineend, buf+nextlinestart, |
| 284 | bufend - nextlinestart); |
| 285 | } |
| 286 | bufend -= tmp; |
| 287 | nextlinestart -= tmp; |
Value stored to 'nextlinestart' is never read | |
| 288 | lineend = findeol(buf, linestart, bufend); |
| 289 | /* might not have a whole line, so loop */ |
| 290 | continue; |
| 291 | } |
| 292 | |
| 293 | /* line now goes from linestart to lineend */ |
| 294 | assert(buf[lineend] == '\0')((buf[lineend] == '\0') ? (void)0 : __assert2("/usr/src/libexec/tradcpp/files.c" , 294, __func__, "buf[lineend] == '\\0'")); |
| 295 | |
| 296 | /* count how many commented-out newlines we swallowed */ |
| 297 | place_addlines(&places.nextline, |
| 298 | countnls(buf, linestart, lineend)); |
| 299 | |
| 300 | /* process the line (even if it's empty) */ |
| 301 | directive_gotline(&places, buf+linestart, lineend-linestart); |
| 302 | |
| 303 | linestart = nextlinestart; |
| 304 | lineend = findeol(buf, linestart, bufend); |
| 305 | places.current = places.nextline; |
| 306 | } |
| 307 | |
| 308 | if (toplevel) { |
| 309 | directive_goteof(&places.current); |
| 310 | } |
| 311 | dofree(buf, bufmax); |
| 312 | } |
| 313 | |
| 314 | //////////////////////////////////////////////////////////// |
| 315 | // path search |
| 316 | |
| 317 | static |
| 318 | char * |
| 319 | mkfilename(struct place *place, const char *dir, const char *file) |
| 320 | { |
| 321 | size_t dlen, flen, rlen; |
| 322 | char *ret; |
| 323 | bool needslash = false0; |
| 324 | |
| 325 | if (dir == NULL((void*)0)) { |
| 326 | dir = place_getparsedir(place); |
| 327 | } |
| 328 | |
| 329 | dlen = strlen(dir); |
| 330 | flen = strlen(file); |
| 331 | if (dlen > 0 && dir[dlen-1] != '/') { |
| 332 | needslash = true1; |
| 333 | } |
| 334 | |
| 335 | rlen = dlen + (needslash ? 1 : 0) + flen; |
| 336 | ret = domalloc(rlen + 1); |
| 337 | snprintf(ret, rlen+1, "%s%s%s", dir, needslash ? "/" : "", file); |
| 338 | return ret; |
| 339 | } |
| 340 | |
| 341 | static |
| 342 | int |
| 343 | file_tryopen(const char *file) |
| 344 | { |
| 345 | int fd; |
| 346 | |
| 347 | /* XXX check for non-regular files */ |
| 348 | |
| 349 | fd = open(file, O_RDONLY0x0000); |
| 350 | if (fd == -1) { |
| 351 | if (errno(*__errno()) != ENOENT2 && errno(*__errno()) != ENOTDIR20) { |
| 352 | complain(NULL((void*)0), "%s: %s", file, strerror(errno(*__errno()))); |
| 353 | } |
| 354 | return -1; |
| 355 | } |
| 356 | |
| 357 | return fd; |
| 358 | } |
| 359 | |
| 360 | static |
| 361 | void |
| 362 | file_search(struct place *place, struct incdirarray *path, const char *name) |
| 363 | { |
| 364 | unsigned i, num; |
| 365 | struct incdir *id; |
| 366 | const struct placefile *pf; |
| 367 | char *file; |
| 368 | int fd; |
| 369 | |
| 370 | assert(place != NULL)((place != ((void*)0)) ? (void)0 : __assert2("/usr/src/libexec/tradcpp/files.c" , 370, __func__, "place != NULL")); |
| 371 | |
| 372 | if (name[0] == '/') { |
| 373 | fd = file_tryopen(name); |
| 374 | if (fd >= 0) { |
| 375 | pf = place_addfile(place, name, true1); |
| 376 | file_read(pf, fd, name, false0); |
| 377 | close(fd); |
| 378 | return; |
| 379 | } |
| 380 | } else { |
| 381 | num = incdirarray_num(path); |
| 382 | for (i=0; i<num; i++) { |
| 383 | id = incdirarray_get(path, i); |
| 384 | file = mkfilename(place, id->name, name); |
| 385 | fd = file_tryopen(file); |
| 386 | if (fd >= 0) { |
| 387 | pf = place_addfile(place, file, id->issystem); |
| 388 | file_read(pf, fd, file, false0); |
| 389 | dostrfree(file); |
| 390 | close(fd); |
| 391 | return; |
| 392 | } |
| 393 | dostrfree(file); |
| 394 | } |
| 395 | } |
| 396 | complain(place, "Include file %s not found", name); |
| 397 | complain_fail(); |
| 398 | } |
| 399 | |
| 400 | void |
| 401 | file_readquote(struct place *place, const char *name) |
| 402 | { |
| 403 | file_search(place, "epath, name); |
| 404 | } |
| 405 | |
| 406 | void |
| 407 | file_readbracket(struct place *place, const char *name) |
| 408 | { |
| 409 | file_search(place, &bracketpath, name); |
| 410 | } |
| 411 | |
| 412 | void |
| 413 | file_readabsolute(struct place *place, const char *name) |
| 414 | { |
| 415 | const struct placefile *pf; |
| 416 | int fd; |
| 417 | |
| 418 | assert(place != NULL)((place != ((void*)0)) ? (void)0 : __assert2("/usr/src/libexec/tradcpp/files.c" , 418, __func__, "place != NULL")); |
| 419 | |
| 420 | if (name == NULL((void*)0)) { |
| 421 | fd = STDIN_FILENO0; |
| 422 | pf = place_addfile(place, "<standard-input>", false0); |
| 423 | } else { |
| 424 | fd = file_tryopen(name); |
| 425 | if (fd < 0) { |
| 426 | complain(NULL((void*)0), "%s: %s", name, strerror(errno(*__errno()))); |
| 427 | die(); |
| 428 | } |
| 429 | pf = place_addfile(place, name, false0); |
| 430 | } |
| 431 | |
| 432 | file_read(pf, fd, name, true1); |
| 433 | |
| 434 | if (name != NULL((void*)0)) { |
| 435 | close(fd); |
| 436 | } |
| 437 | } |