Пример #1
0
static void
fill_in_array(awk_value_t *new_array)
{
	awk_array_t a_cookie;
	awk_value_t index, value;

	a_cookie = create_array();

	(void) make_const_string("hello", 5, & index);
	(void) make_const_string("world", 5, & value);
	if (! set_array_element(a_cookie, & index, & value)) {
		printf("fill_in_array:%d: set_array_element failed\n", __LINE__);
		return;
	}

	(void) make_const_string("answer", 6, & index);
	(void) make_number(42.0, & value);
	if (! set_array_element(a_cookie, & index, & value)) {
		printf("fill_in_array:%d: set_array_element failed\n", __LINE__);
		return;
	}

	new_array->val_type = AWK_ARRAY;
	new_array->array_cookie = a_cookie;
}
Пример #2
0
static void
fill_path_element(awk_array_t element_array, const char *path)
{
	awk_value_t index, value;

	(void) make_const_string("path", 4, & index);
	(void) make_const_string(path, strlen(path), & value);
	if (! set_array_element(element_array, & index, & value)) {
		warning(ext_id, _("fill_path_element: could not set element"));
		fts_errors++;
	}
}
Пример #3
0
static void
fill_error_element(awk_array_t element_array, const int errcode)
{
	awk_value_t index, value;
	const char *err = strerror(errcode);

	(void) make_const_string("error", 5, & index);
	(void) make_const_string(err, strlen(err), & value);
	if (! set_array_element(element_array, & index, & value)) {
		warning(ext_id, _("fill_error_element: could not set element"));
		fts_errors++;
	}
}
Пример #4
0
/* <file> .filename false */
static int
zfilename(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    stream *s;
    gs_const_string fname;
    byte *str;

    check_file(s, op);
    if (sfilename(s, &fname) < 0) {
	make_false(op);
	return 0;
    }
    check_ostack(1);
    str = ialloc_string(fname.size, "filename");
    if (str == 0)
	return_error(e_VMerror);
    memcpy(str, fname.data, fname.size);
    push(1);			/* can't fail */
    make_const_string( op - 1 , 
		      a_all | imemory_space((const struct gs_ref_memory_s*) imemory), 
		      fname.size, 
		      str);
    make_true(op);
    return 0;
}
Пример #5
0
/* Run the initialization procedures of the individual operator files. */
int
zop_init(i_ctx_t *i_ctx_p)
{
    const op_def *const *tptr;
    int code;

    /* Because of a bug in Sun's SC1.0 compiler, */
    /* we have to spell out the typedef for op_def_ptr here: */
    const op_def *def;

    for (tptr = op_defs_all; *tptr != 0; tptr++) {
	for (def = *tptr; def->oname != 0; def++)
	    DO_NOTHING;
	if (def->proc != 0) {
	    code = def->proc(i_ctx_p);
	    if (code < 0) {
		lprintf2("op_init proc 0x%lx returned error %d!\n",
			 (ulong)def->proc, code);
		return code;
	    }
	}
    }

    /* Initialize the predefined names other than operators. */
    /* Do this here in case op_init changed any of them. */
    {
	ref vcr, vpr, vpf, vre, vrd;

	make_const_string(&vcr, a_readonly | avm_foreign,
			  strlen(gs_copyright), (const byte *)gs_copyright);
	make_const_string(&vpr, a_readonly | avm_foreign,
			  strlen(gs_product), (const byte *)gs_product);
	make_const_string(&vpf, a_readonly | avm_foreign,
			  strlen(gs_productfamily),
			  (const byte *)gs_productfamily);
	make_int(&vre, gs_revision);
	make_int(&vrd, gs_revisiondate);
	if ((code = initial_enter_name("copyright", &vcr)) < 0 ||
	    (code = initial_enter_name("product", &vpr)) < 0 ||
	    (code = initial_enter_name("productfamily", &vpf)) < 0 ||
	    (code = initial_enter_name("revision", &vre)) < 0 ||
	    (code = initial_enter_name("revisiondate", &vrd)) < 0)
	    return code;
    }

    return 0;
}
Пример #6
0
static void
array_set(awk_array_t array, const char *sub, awk_value_t *value)
{
	awk_value_t index;

	set_array_element(array,
			make_const_string(sub, strlen(sub), & index),
			value);

}
Пример #7
0
/* - .filenamelistseparator <string> */
static int
zfilenamelistseparator(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;

    push(1);
    make_const_string(op, avm_foreign | a_readonly, 1,
		      (const byte *)&gp_file_name_list_separator);
    return 0;
}
Пример #8
0
/* <device> .devicename <string> */
static int
zdevicename(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    const char *dname;

    check_read_type(*op, t_device);
    dname = op->value.pdevice->dname;
    make_const_string(op, avm_foreign | a_readonly, strlen(dname),
		      (const byte *)dname);
    return 0;
}
Пример #9
0
/* <cid9font> <cid> .type9mapcid <charstring> <font_index> */
int
ztype9mapcid(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    gs_font *pfont;
    gs_font_cid0 *pfcid;
    int code = font_param(op - 1, &pfont);
    gs_glyph_data_t gdata;
    int fidx;

    if (code < 0)
        return code;
    if (pfont->FontType != ft_CID_encrypted)
        return_error(e_invalidfont);
    check_type(*op, t_integer);
    pfcid = (gs_font_cid0 *)pfont;
    gdata.memory = pfont->memory;
    code = pfcid->cidata.glyph_data((gs_font_base *)pfcid,
                        (gs_glyph)(gs_min_cid_glyph + op->value.intval),
                                    &gdata, &fidx);

    /* return code; original error-sensitive & fragile code */
    if (code < 0) { /* failed to load glyph data, put CID 0 */
       int default_fallback_CID = 0 ;

       if_debug2('J', "[J]ztype9cidmap() use CID %d instead of glyph-missing CID %d\n", default_fallback_CID, op->value.intval);

       op->value.intval = default_fallback_CID;

       /* reload glyph for default_fallback_CID */

       code = pfcid->cidata.glyph_data((gs_font_base *)pfcid,
                    (gs_glyph)(gs_min_cid_glyph + default_fallback_CID),
                                   &gdata, &fidx);

       if (code < 0) {
           if_debug1('J', "[J]ztype9cidmap() could not load default glyph (CID %d)\n", op->value.intval);
           return_error(e_invalidfont);
       }

    }

    /****** FOLLOWING IS NOT GENERAL W.R.T. ALLOCATION OF GLYPH DATA ******/
    make_const_string(op - 1,
                      a_readonly | imemory_space((gs_ref_memory_t *)pfont->memory),
                      gdata.bits.size,
                      gdata.bits.data);
    make_int(op, fidx);
    return code;
}
Пример #10
0
/* r_size(op1) was set just above. */
static int
do_execstack(i_ctx_t *i_ctx_p, bool include_marks, os_ptr op1)
{
    os_ptr op = osp;
    ref *arefs = op1->value.refs;
    uint asize = r_size(op1);
    uint i;
    ref *rq;

    /*
     * Copy elements from the stack to the array,
     * optionally skipping executable nulls.
     * Clear the executable bit in any internal operators, and
     * convert t_structs and t_astructs (which can only appear
     * in connection with stack marks, which means that they will
     * probably be freed when unwinding) to something harmless.
     */
    for (i = 0, rq = arefs + asize; rq != arefs; ++i) {
        const ref *rp = ref_stack_index(&e_stack, (long)i);

        if (r_has_type_attrs(rp, t_null, a_executable) && !include_marks)
            continue;
        --rq;
        ref_assign_old(op1, rq, rp, "execstack");
        switch (r_type(rq)) {
            case t_operator: {
                uint opidx = op_index(rq);

                if (opidx == 0 || op_def_is_internal(op_index_def(opidx)))
                    r_clear_attrs(rq, a_executable);
                break;
            }
            case t_struct:
            case t_astruct: {
                const char *tname = rq->value.pstruct ?
                    gs_struct_type_name_string(
                                gs_object_type(imemory, rq->value.pstruct))
                    : "NULL";

                make_const_string(rq, a_readonly | avm_foreign,
                                  strlen(tname), (const byte *)tname);
                break;
            }
            default:
                ;
        }
    }
    pop(op - op1);
    return 0;
}
Пример #11
0
static awk_bool_t init_testext(void)
{
	awk_value_t value;
	static const char message[] = "hello, world";	/* of course */
	static const char message2[] = "i am a scalar";

	/* add at_exit functions */
	awk_atexit(at_exit0, NULL);
	awk_atexit(at_exit1, & data_for_1);
	awk_atexit(at_exit2, NULL);

/*
BEGIN {
	printf("answer_num = %g\n", answer_num);
	printf("message_string = %s\n", message_string);
	for (i in new_array)
		printf("new_array[\"%s\"] = \"%s\"\n", i, new_array[i])
	print ""
}
*/

	/* install some variables */
	if (! sym_update("answer_num", make_number(42, & value)))
		printf("testext: sym_update(\"answer_num\") failed!\n");

	if (! sym_update("message_string",
			make_const_string(message, strlen(message), & value)))
		printf("testext: sym_update(\"answer_num\") failed!\n");

	if (! sym_update("the_scalar",
			make_const_string(message2, strlen(message2), & value)))
		printf("testext: sym_update(\"the_scalar\") failed!\n");

	create_new_array();

	return awk_true;
}
Пример #12
0
/* Prepare to write a string value. */
static int
ref_param_write_string_value(ref * pref, const gs_param_string * pvalue,
			     gs_ref_memory_t *imem)
{
    const byte *pdata = pvalue->data;
    uint n = pvalue->size;

    if (pvalue->persistent)
	make_const_string(pref, a_readonly | avm_foreign, n, pdata);
    else {
	byte *pstr = gs_alloc_string((gs_memory_t *)imem, n,
				     "ref_param_write_string");

	if (pstr == 0)
	    return_error(e_VMerror);
	memcpy(pstr, pdata, n);
	make_string(pref, a_readonly | imemory_space(imem), n, pstr);
    }
    return 0;
}
Пример #13
0
/* <int> .getiodevice <string|null> */
static int
zgetiodevice(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    gx_io_device *iodev;
    const byte *dname;

    check_type(*op, t_integer);
    if (op->value.intval != (int)op->value.intval)
	return_error(e_rangecheck);
    iodev = gs_getiodevice((int)(op->value.intval));
    if (iodev == 0)		/* index out of range */
	return_error(e_rangecheck);
    dname = (const byte *)iodev->dname;
    if (dname == 0)
	make_null(op);
    else
	make_const_string(op, a_readonly | avm_foreign,
			  strlen((const char *)dname), dname);
    return 0;
}
Пример #14
0
static void
fill_stat_element(awk_array_t element_array, const char *name, struct stat *sbuf)
{
	awk_value_t index, value;
	awk_array_t stat_array;

	stat_array = create_array();
	if (stat_array == NULL) {
		warning(ext_id, _("fill_stat_element: could not create array"));
		fts_errors++;
		return;
	}
	fill_stat_array(name, stat_array, sbuf);
	(void) make_const_string("stat", 4, & index);
	value.val_type = AWK_ARRAY;
	value.array_cookie = stat_array;
	if (! set_array_element(element_array, & index, & value)) {
		warning(ext_id, _("fill_stat_element: could not set element"));
		fts_errors++;
	}
}
Пример #15
0
static awk_value_t *
test_scalar(int nargs, awk_value_t *result)
{
	awk_value_t new_value, new_value2;
	awk_value_t the_scalar;

	(void) nargs;		/* silence warnings */
	make_number(0.0, result);

	if (! sym_lookup("the_scalar", AWK_SCALAR, & the_scalar)) {
		printf("test_scalar: could not get scalar cookie\n");
		goto out;
	}

	if (! get_argument(0, AWK_UNDEFINED, & new_value)) {
		printf("test_scalar: could not get argument\n");
		goto out;
	} else if (new_value.val_type != AWK_STRING && new_value.val_type != AWK_NUMBER) {
		printf("test_scalar: argument is not a scalar\n");
		goto out;
	}

	if (new_value.val_type == AWK_STRING) {
		make_const_string(new_value.str_value.str, new_value.str_value.len, & new_value2);
	} else {
		new_value2 = new_value;
	}

	if (! sym_update_scalar(the_scalar.scalar_cookie, & new_value2)) {
		printf("test_scalar: could not update new_value2!\n");
		goto out;
	}

	make_number(1.0, result);

out:
	return result;
}
Пример #16
0
static awk_value_t *
try_modify_environ(int nargs, awk_value_t *result)
{
	awk_value_t value, index, newvalue;
	awk_flat_array_t *flat_array;
	awk_array_t environ_array;
	size_t count;
	int i;

	assert(result != NULL);
	make_number(0.0, result);

	if (nargs != 0) {
		printf("try_modify_environ: nargs not right (%d should be 0)\n", nargs);
		goto out;
	}

	/* get ENVIRON array */
	if (sym_lookup("ENVIRON", AWK_ARRAY, & value))
		printf("try_modify_environ: sym_lookup of ENVIRON passed\n");
	else {
		printf("try_modify_environ: sym_lookup of ENVIRON failed\n");
		goto out;
	}

	environ_array = value.array_cookie;
	if (! get_element_count(environ_array, & count)) {
		printf("try_modify_environ: get_element_count failed\n");
		goto out;
	}

	/* setting an array element should fail */
	(void) make_const_string("testext2", 8, & index);
	(void) make_const_string("a value", 7, & value);
	if (set_array_element(environ_array, & index, & newvalue)) {
		printf("try_modify_environ: set_array_element of ENVIRON passed\n");
	} else {
		printf("try_modify_environ: set_array_element of ENVIRON failed\n");
		gawk_free(index.str_value.str);
		gawk_free(value.str_value.str);
	}

	if (! flatten_array(environ_array, & flat_array)) {
		printf("try_modify_environ: could not flatten array\n");
		goto out;
	}

	if (flat_array->count != count) {
		printf("try_modify_environ: flat_array->count (%lu) != count (%lu)\n",
				(unsigned long) flat_array->count,
				(unsigned long) count);
		goto out;
	}

	for (i = 0; i < flat_array->count; i++) {
		/* don't print */
	/*
		printf("\t%s[\"%.*s\"] = %s\n",
			name,
			(int) flat_array->elements[i].index.str_value.len,
			flat_array->elements[i].index.str_value.str,
			valrep2str(& flat_array->elements[i].value));
	*/
		if (strcmp("testext", flat_array->elements[i].index.str_value.str) == 0) {
			flat_array->elements[i].flags |= AWK_ELEMENT_DELETE;
			printf("try_modify_environ: marking element \"%s\" for deletion\n",
				flat_array->elements[i].index.str_value.str);
		}
	}

	if (! release_flattened_array(environ_array, flat_array)) {
		printf("try_modify_environ: could not release flattened array\n");
		goto out;
	}

	make_number(1.0, result);
out:
	return result;
}
Пример #17
0
/* <prefix|null> <access_string> .tempfile <name_string> <file> */
static int
ztempfile(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    const char *pstr;
    char fmode[4];
    int code = parse_file_access_string(op, fmode);
    char prefix[gp_file_name_sizeof];
    char fname[gp_file_name_sizeof];
    uint fnlen;
    FILE *sfile;
    stream *s;
    byte *buf;

    if (code < 0)
	return code;
    strcat(fmode, gp_fmode_binary_suffix);
    if (r_has_type(op - 1, t_null))
	pstr = gp_scratch_file_name_prefix;
    else {
	uint psize;

	check_read_type(op[-1], t_string);
	psize = r_size(op - 1);
	if (psize >= gp_file_name_sizeof)
	    return_error(e_rangecheck);
	memcpy(prefix, op[-1].value.const_bytes, psize);
	prefix[psize] = 0;
	pstr = prefix;
    }

    if (gp_file_name_is_absolute(pstr, strlen(pstr))) {
	if (check_file_permissions(i_ctx_p, pstr, strlen(pstr),
				   "PermitFileWriting") < 0) {
	    return_error(e_invalidfileaccess);
	}
    } else if (!prefix_is_simple(pstr)) {
	return_error(e_invalidfileaccess);
    }

    s = file_alloc_stream(imemory, "ztempfile(stream)");
    if (s == 0)
	return_error(e_VMerror);
    buf = gs_alloc_bytes(imemory, file_default_buffer_size,
			 "ztempfile(buffer)");
    if (buf == 0)
	return_error(e_VMerror);
    sfile = gp_open_scratch_file(pstr, fname, fmode);
    if (sfile == 0) {
	gs_free_object(imemory, buf, "ztempfile(buffer)");
	return_error(e_invalidfileaccess);
    }
    fnlen = strlen(fname);
    file_init_stream(s, sfile, fmode, buf, file_default_buffer_size);
    code = ssetfilename(s, (const unsigned char*) fname, fnlen);
    if (code < 0) {
	sclose(s);
	iodev_default->procs.delete_file(iodev_default, fname);
	return_error(e_VMerror);
    }
    make_const_string(op - 1, a_readonly | icurrent_space, fnlen,
		      s->file_name.data);
    make_stream_file(op, s, fmode);
    return code;
}
Пример #18
0
static int
fill_stat_array(const char *name, awk_array_t array, struct stat *sbuf)
{
	char *pmode;	/* printable mode */
	const char *type = "unknown";
	awk_value_t tmp;
	static struct ftype_map {
		unsigned int mask;
		const char *type;
	} ftype_map[] = {
		{ S_IFREG, "file" },
		{ S_IFBLK, "blockdev" },
		{ S_IFCHR, "chardev" },
		{ S_IFDIR, "directory" },
#ifdef S_IFSOCK
		{ S_IFSOCK, "socket" },
#endif
#ifdef S_IFIFO
		{ S_IFIFO, "fifo" },
#endif
#ifdef S_IFLNK
		{ S_IFLNK, "symlink" },
#endif
#ifdef S_IFDOOR	/* Solaris weirdness */
		{ S_IFDOOR, "door" },
#endif /* S_IFDOOR */
	};
	int j, k;

	/* empty out the array */
	clear_array(array);

	/* fill in the array */
	array_set(array, "name", make_const_string(name, strlen(name), & tmp));
	array_set_numeric(array, "dev", sbuf->st_dev);
	array_set_numeric(array, "ino", sbuf->st_ino);
	array_set_numeric(array, "mode", sbuf->st_mode);
	array_set_numeric(array, "nlink", sbuf->st_nlink);
	array_set_numeric(array, "uid", sbuf->st_uid);
	array_set_numeric(array, "gid", sbuf->st_gid);
	array_set_numeric(array, "size", sbuf->st_size);
	array_set_numeric(array, "blocks", sbuf->st_blocks);
	array_set_numeric(array, "atime", sbuf->st_atime);
	array_set_numeric(array, "mtime", sbuf->st_mtime);
	array_set_numeric(array, "ctime", sbuf->st_ctime);

	/* for block and character devices, add rdev, major and minor numbers */
	if (S_ISBLK(sbuf->st_mode) || S_ISCHR(sbuf->st_mode)) {
		array_set_numeric(array, "rdev", sbuf->st_rdev);
		array_set_numeric(array, "major", major(sbuf->st_rdev));
		array_set_numeric(array, "minor", minor(sbuf->st_rdev));
	}

#ifdef HAVE_ST_BLKSIZE
	array_set_numeric(array, "blksize", sbuf->st_blksize);
#endif /* HAVE_ST_BLKSIZE */

	pmode = format_mode(sbuf->st_mode);
	array_set(array, "pmode", make_const_string(pmode, strlen(pmode), & tmp));

	/* for symbolic links, add a linkval field */
	if (S_ISLNK(sbuf->st_mode)) {
		char *buf;
		ssize_t linksize;

		if ((buf = read_symlink(name, sbuf->st_size,
					& linksize)) != NULL)
			array_set(array, "linkval", make_malloced_string(buf, linksize, & tmp));
		else
			warning(ext_id, "stat: unable to read symbolic link `%s'", name);
	}

	/* add a type field */
	type = "unknown";	/* shouldn't happen */
	for (j = 0, k = sizeof(ftype_map)/sizeof(ftype_map[0]); j < k; j++) {
		if ((sbuf->st_mode & S_IFMT) == ftype_map[j].mask) {
			type = ftype_map[j].type;
			break;
		}
	}

	array_set(array, "type", make_const_string(type, strlen(type), &tmp));

	return 0;
}
Пример #19
0
/*
BEGIN {
	n = split("one two three four five six", test_array2)
	ret = test_array_elem(test_array2, "3")
	printf("test_array_elem() returned %d, test_array2[3] = %g\n", ret, test_array2[3])
	if ("5" in test_array2)
		printf("error: test_array_elem() did not remove element \"5\"\n")
	else
		printf("test_array_elem() did remove element \"5\"\n")
	if ("7" in test_array2)
		printf("test_array_elem() added element \"7\" --> %s\n", test_array2[7])
	else
		printf("test_array_elem() did not add element \"7\"\n")
	if ("subarray" in test_array2) {
		if (isarray(test_array2["subarray"])) {
			for (i in test_array2["subarray"])
				printf("test_array2[\"subarray\"][\"%s\"] = %s\n",
					i, test_array2["subarray"][i])
		} else
			printf("test_array_elem() added element \"subarray\" as scalar\n")
	} else
		printf("test_array_elem() did not add element \"subarray\"\n")
	print ""
}
*/
static awk_value_t *
test_array_elem(int nargs, awk_value_t *result)
{
	awk_value_t array, index, index2, value;

	make_number(0.0, result);	/* default return until full success */

	assert(result != NULL);

	if (nargs != 2) {
		printf("test_array_elem: nargs not right (%d should be 2)\n", nargs);
		goto out;
	}

	/* look up an array element and print the value */
	if (! get_argument(0, AWK_ARRAY, & array)) {
		printf("test_array_elem: get_argument 0 (array) failed\n");
		goto out;
	}
	if (! get_argument(1, AWK_STRING, & index)) {
		printf("test_array_elem: get_argument 1 (index) failed\n");
		goto out;
	}
	(void) make_const_string(index.str_value.str, index.str_value.len, & index2);
	if (! get_array_element(array.array_cookie, & index2, AWK_UNDEFINED, & value)) {
		printf("test_array_elem: get_array_element failed\n");
		goto out;
	}
	printf("test_array_elem: a[\"%.*s\"] = %s\n",
			(int) index.str_value.len,
			index.str_value.str,
			valrep2str(& value));

	/* change the element - "3" */
	(void) make_number(42.0, & value);
	(void) make_const_string(index.str_value.str, index.str_value.len, & index2);
	if (! set_array_element(array.array_cookie, & index2, & value)) {
		printf("test_array_elem: set_array_element failed\n");
		goto out;
	}

	/* delete another element - "5" */
	(void) make_const_string("5", 1, & index);
	if (! del_array_element(array.array_cookie, & index)) {
		printf("test_array_elem: del_array_element failed\n");
		goto out;
	}

	/* add a new element - "7" */
	(void) make_const_string("7", 1, & index);
	(void) make_const_string("seven", 5, & value);
	if (! set_array_element(array.array_cookie, & index, & value)) {
		printf("test_array_elem: set_array_element failed\n");
		goto out;
	}

	/* add a subarray */
	(void) make_const_string("subarray", 8, & index);
	fill_in_array(& value);
	if (! set_array_element(array.array_cookie, & index, & value)) {
		printf("test_array_elem: set_array_element (subarray) failed\n");
		goto out;
	}

	/* change and deletion should be reflected in awk script */
	make_number(1.0, result);
out:
	return result;
}
Пример #20
0
static void
process(FTS *heirarchy, awk_array_t destarray, int seedot)
{
	FTSENT *fentry;
	awk_value_t index, value;
	awk_array_t element_array, newdir_array, dot_array;
	int bad_ret = 0;

	/* path is full path,  pathlen is length thereof */
	/* name is name in directory, namelen is length thereof */
	while ((fentry = fts_read(heirarchy)) != NULL) {
		bad_ret = 0;

		switch (fentry->fts_info) {
		case FTS_D:
			/* directory */
			/* create array to hold entries */
			newdir_array = create_array();
			if (newdir_array == NULL) {
				warning(ext_id, _("fts-process: could not create array"));
				fts_errors++;
				break;
			}

			/* store new directory in its parent directory */
			(void) make_const_string(fentry->fts_name, fentry->fts_namelen, & index);
			value.val_type = AWK_ARRAY;
			value.array_cookie = newdir_array;
			if (! set_array_element(destarray, & index, & value)) {
				warning(ext_id, _("fts-process: could not set element"));
				fts_errors++;
				break;
			}
			newdir_array = value.array_cookie;

			/* push current directory */
			stack_push(destarray);

			/* new directory becomes current */
			destarray = newdir_array;
			break;

		case FTS_DNR:
		case FTS_DC:
		case FTS_ERR:
		case FTS_NS:
			/* error */
			bad_ret = 1;
			/* fall through */

		case FTS_NSOK:
		case FTS_SL:
		case FTS_SLNONE:
		case FTS_F:
		case FTS_DOT:
			/* if see dot, skip "." */
			if (seedot && strcmp(fentry->fts_name, ".") == 0)
				break;

			/*
			 * File case.
			 * destarray is the directory we're reading.
			 * step 1: create new empty array
			 */
			element_array = create_array();
			if (element_array == NULL) {
				warning(ext_id, _("fts-process: could not create array"));
				fts_errors++;
				break;
			}

			/* step 2: add element array to parent array */
			(void) make_const_string(fentry->fts_name, fentry->fts_namelen, & index);
			value.val_type = AWK_ARRAY;
			value.array_cookie = element_array;
			if (! set_array_element(destarray, & index, & value)) {
				warning(ext_id, _("fts-process: could not set element"));
				fts_errors++;
				break;
			}

			/* step 3: fill in path, stat, error elements */
			fill_default_elements(element_array, fentry, bad_ret);
			break;

		case FTS_DP:
			/* create "." subarray */
			dot_array = create_array();

			/* add it to parent */
			(void) make_const_string(".", 1, & index);
			value.val_type = AWK_ARRAY;
			value.array_cookie = dot_array;
			if (! set_array_element(destarray, & index, & value)) {
				warning(ext_id, _("fts-process: could not set element"));
				fts_errors++;
				break;
			}

			/* fill it in with path, stat, error elements */
			fill_default_elements(dot_array, fentry, bad_ret);

			/* now pop the parent directory off the stack */
			if (! stack_empty()) {
				/* pop stack */
				destarray = stack_pop();
			}

			break;

		case FTS_DEFAULT:
			/* nothing to do */
			break;
		}
	}
}