obj sanity check: check objects inside container */
| 3371 | |
| 3372 | /* obj sanity check: check objects inside container */ |
| 3373 | staticfn void |
| 3374 | check_contained(struct obj *container, const char *mesg) |
| 3375 | { |
| 3376 | struct obj *obj; |
| 3377 | /* big enough to work with, not too big to blow out stack in recursion */ |
| 3378 | char mesgbuf[40], nestedmesg[120]; |
| 3379 | |
| 3380 | if (!Has_contents(container)) |
| 3381 | return; |
| 3382 | /* change "invent sanity" to "contained invent sanity" |
| 3383 | but leave "nested contained invent sanity" as is */ |
| 3384 | if (!strstri(mesg, "contained")) |
| 3385 | mesg = strcat(strcpy(mesgbuf, "contained "), mesg); |
| 3386 | |
| 3387 | for (obj = container->cobj; obj; obj = obj->nobj) { |
| 3388 | /* catch direct cycle to avoid unbounded recursion */ |
| 3389 | if (obj == container) |
| 3390 | panic("failed sanity check: container holds itself"); |
| 3391 | if (obj->where != OBJ_CONTAINED) |
| 3392 | insane_object(obj, "%s obj %s %s: %s", mesg, (struct monst *) 0); |
| 3393 | else if (obj->ocontainer != container) |
| 3394 | impossible("%s obj %s in container %s, not %s", mesg, |
| 3395 | fmt_ptr((genericptr_t) obj), |
| 3396 | fmt_ptr((genericptr_t) obj->ocontainer), |
| 3397 | fmt_ptr((genericptr_t) container)); |
| 3398 | if (obj->globby) |
| 3399 | check_glob(obj, mesg); |
| 3400 | |
| 3401 | if (Has_contents(obj)) { |
| 3402 | /* catch most likely indirect cycle; we won't notice if |
| 3403 | parent is present when something comes before it, or |
| 3404 | notice more deeply embedded cycles (grandparent, &c) */ |
| 3405 | if (obj->cobj == container) |
| 3406 | panic("failed sanity check: container holds its parent"); |
| 3407 | /* change "contained... sanity" to "nested contained... sanity" |
| 3408 | and "nested contained..." to "nested nested contained..." */ |
| 3409 | Strcpy(nestedmesg, "nested "); |
| 3410 | copynchars(eos(nestedmesg), mesg, (int) sizeof nestedmesg |
| 3411 | - (int) strlen(nestedmesg) - 1); |
| 3412 | /* recursively check contents */ |
| 3413 | check_contained(obj, nestedmesg); |
| 3414 | } |
| 3415 | } |
| 3416 | } |
| 3417 | |
| 3418 | /* called when 'obj->globby' is set so we don't recheck it here */ |
| 3419 | staticfn void |
no test coverage detected