1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-02-15 04:32:24 +00:00

util/mkshadow: delete ancient unused utility

This commit is contained in:
Jon Trulson 2018-06-27 13:10:34 -06:00
parent 29ea5f794d
commit 4aa9392e98
5 changed files with 0 additions and 779 deletions

View file

@ -1,5 +0,0 @@
XCOMM $XConsortium: Imakefile,v 1.1 94/04/13 18:44:40 rws Exp $
SRCS = mkshadow.c savedir.c wildmat.c
OBJS = mkshadow.o savedir.o wildmat.o
ComplexProgramTarget(mkshadow)

View file

@ -1,38 +0,0 @@
The mkshadow programs makes a "shadow tree" of a directory tree.
It logically copies all of the "MASTER" directory into ".".
However, ordinary files, and RCS/SCCS directories are "copied"
by creating a sybolic link to the corresponding file in MASTER.
The wildmat.c file is by Rich Salz, and from comp.sources.misc, volume 17.
The savedir.c file is lightly modified from the version written
by David MacKenzie for GNU fileutils; the Free Software Foundation
has graciously agreed to waive their usual copyright so this
program can be distributed by the X Consortium.
If you have problems compiling savedir.c, try setting the DIRENT make
variable as suggested in the Makefile.
* Usage: mkshadow [-X exclude_file] [-x exclude_pattern] ... MASTER
* Makes the current directory be a "shadow copy" of MASTER.
* Sort of like a recursive copy of MASTER to .
* However, symbolic links are used instead of actually
* copying (non-directory) files.
* Also, directories named RCS or SCCS are shared (with a symbolic link).
* Warning messages are printed for files (and directories) in .
* that don't match a corresponding file in MASTER (though
* symbolic links are silently removed).
* Also, a warning message is printed for non-directory files
* under . that are not symbolic links.
*
* Files and directories can be excluded from the sharing
* with the -X and -x flags. The flag `-x pattern' (or `-xpattern')
* means that mkshadow should ignore any file whose name matches
* the pattern. The pattern is a "globbing" pattern, i.e. the
* characters *?[^-] are interpreted as by the shell.
* If the pattern contains a '/' is is matched against the complete
* current path (relative to '.'); otherwise, it is matched
* against the last component of the path.
* A `-X filename' flag means to read a set of exclusion patterns
* from the named file, one pattern to a line.
Author: Per Bothner. bothner@cygnus.com. November 1990, 1993.

View file

@ -1,400 +0,0 @@
/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $XConsortium: mkshadow.c /main/2 1996/12/04 10:11:51 swick $ */
/* mkshadow.c - make a "shadow copy" of a directory tree with symlinks.
Copyright 1990, 1993 Free Software Foundation, Inc.
Permission to use, copy, modify, and distribute this program for
any purpose and without fee is hereby granted, provided that this
copyright and permission notice appear on all copies, and that
notice be given that copying and distribution is by permission of
the Free Software Foundation. The Free Software Foundation makes
no representations about the suitability of this software for any
purpose. It is provided "as is" without expressed or implied
warranty.
(The FSF has modified its usual distribution terms, for this file,
as a courtesy to the X project.) */
/*
* Usage: mkshadow [-X exclude_file] [-x exclude_pattern] ... MASTER [SHADOW]
* Makes SHADOW be a "shadow copy" of MASTER. SHADOW defaults to the current
* directory. Sort of like a recursive copy of MASTER to SHADOW.
* However, symbolic links are used instead of actually
* copying (non-directory) files.
* Also, directories named RCS or SCCS are shared (with a symbolic link).
* Warning messages are printed for files (and directories) in .
* that don't match a corresponding file in MASTER (though
* symbolic links are silently removed).
* Also, a warning message is printed for non-directory files
* under SHADOW that are not symbolic links.
*
* Files and directories can be excluded from the sharing
* with the -X and -x flags. The flag `-x pattern' (or `-xpattern')
* means that mkshadow should ignore any file whose name matches
* the pattern. The pattern is a "globbing" pattern, i.e. the
* characters *?[^-] are interpreted as by the shell.
* If the pattern contains a '/' is is matched against the complete
* current path (relative to '.'); otherwise, it is matched
* against the last component of the path.
* A `-X filename' flag means to read a set of exclusion patterns
* from the named file, one pattern to a line.
*
* Originally written by Per Bothner at University of Wisconsin-Madison,
* inspired by the lndir script distributed with X11.
* Modified by Per Bothner <bothner@cygnus.com> November 1993
* to more-or-less follow Posix.
*/
#include <sys/types.h>
#include <stdio.h>
#ifdef BSD
#include <strings.h>
#define strchr index
#else
#include <string.h>
#endif
#include <sys/stat.h>
#if defined(S_IFDIR) && !defined(S_ISDIR)
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#endif
#if defined(S_IFLNK) && !defined(S_ISLNK)
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
#endif
#ifndef S_ISLNK
#define lstat stat
#endif
#ifndef MAXPATHLEN
#define MAXPATHLEN 1024
#endif
#include <errno.h>
#ifndef errno
extern int errno;
#endif
extern char * savedir();
fatal(msg)
char *msg;
{
if (errno) perror(msg ? msg : "");
else if (msg) fprintf(stderr, "mkshadow: %s\n", msg);
exit(-1);
}
/* When handling symbolic links to relative directories,
* we need to prepend "../" to the "source".
* We preallocate MAX_DEPTH repetations of "../" using a simple trick.
*/
#define MAX_DEPTH 20
#define PREPEND_BUFFER_SIZE (MAX_DEPTH*3)
char master_buffer[MAXPATHLEN+PREPEND_BUFFER_SIZE] =
"../../../../../../../../../../../../../../../../../../../../";
/* The logical start of the master_buffer is defined by
* master_start, which skips the fixed prepend area.
*/
#define master_start (master_buffer+PREPEND_BUFFER_SIZE)
char shadow_buffer[MAXPATHLEN];
void bad_args(msg)
{
if (msg) fprintf(stderr, "%s\n", msg);
fprintf (stderr, "usage: mkshadow [-X exclude_file] [-x exclude_pattern]");
fprintf (stderr, " master [shadow]\n");
exit(-1);
}
int exclude_count = 0;
char **exclude_patterns = NULL;
int exclude_limit = 0;
void add_exclude(pattern)
char *pattern;
{
if (exclude_limit == 0) {
exclude_limit = 100;
exclude_patterns = (char**)malloc(exclude_limit * sizeof(char*));
} else if (exclude_count + 1 >= exclude_limit) {
exclude_limit += 100;
exclude_patterns = (char**)realloc(exclude_patterns,
exclude_limit * sizeof(char*));
}
exclude_patterns[exclude_count] = pattern;
exclude_count++;
}
void add_exclude_file(name)
char *name;
{
char buf[MAXPATHLEN];
FILE *file = fopen(name, "r");
if (file == NULL) fatal("failed to find -X (exclude) file");
for (;;) {
int len;
char *str = fgets(buf, MAXPATHLEN, file);
if (str == NULL) break;
len = strlen(str);
if (len && str[len-1] == '\n') str[--len] = 0;
if (!len) continue;
str = (char*)malloc(len+1);
strcpy(str, buf);
add_exclude(str);
}
fclose(file);
}
main(argc, argv)
char **argv;
{
char *master_name = NULL;
char *shadow_name = NULL;
int i;
for (i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
switch(argv[i][1]) {
case 'X':
if (argv[i][2]) add_exclude_file(&argv[i][2]);
else if (++i >= argc) bad_args(NULL);
else add_exclude_file(argv[i]);
break;
case 'x':
if (argv[i][2]) add_exclude(&argv[i][2]);
else if (++i >= argc) bad_args(NULL);
else add_exclude(argv[i]);
break;
default:
bad_args(NULL);
}
} else if (master_name == NULL)
master_name = argv[i];
else if (shadow_name == NULL)
shadow_name = argv[i];
else bad_args (NULL);
}
if (master_name == NULL) bad_args(NULL);
if (shadow_name == NULL)
shadow_name = ".";
else if ((shadow_name[0] != '.' || shadow_name[1])
&& master_name[0] != '/') {
fprintf(stderr, "Shadowing a relative directory pathname to a \n");
fprintf(stderr, "shadow other than '.' is not supported!\n");
exit(-1);
}
strcpy(shadow_buffer, shadow_name);
strcpy(master_start, master_name);
DoCopy(master_start, shadow_buffer, 0);
return 0;
}
int compare_strings(ptr1, ptr2)
char **ptr1, **ptr2;
{
return strcmp(*ptr1, *ptr2);
}
void MakeLink(master, current, depth)
char *master;
char *current;
int depth;
{
if (master[0] != '/') {
/* Source directory was specified with a relative pathname. */
if (master != master_start) {
fatal("Internal bug: bad string buffer use");
}
/* Pre-pend "../" depth times. This compensates for
* the directories we've entered. */
master -= 3 * depth;
}
if (symlink(master, current)) {
fprintf(stderr, "Failed to create symbolic link %s->%s\n",
current, master);
exit (-1);
}
}
/* Get a sorted NULL_terminator array of (char*) using 'names'
* (created by save_dir) as data.
*/
char ** get_name_pointers(names)
char *names;
{
int n_names = 0;
int names_buf_size = 64;
char *namep;
char ** pointers = (char**)malloc(names_buf_size * sizeof(char*));
if (!names || !pointers) fatal("virtual memory exhausted");
for (namep = names; *namep; namep += strlen(namep) + 1) {
if (n_names + 1 >= names_buf_size) {
names_buf_size *= 2;
pointers = (char**)realloc(pointers,
names_buf_size * sizeof(char*));
if (!pointers) fatal("virtual memory exhausted");
}
pointers[n_names++] = namep;
}
pointers[n_names] = 0;
qsort(pointers, n_names, sizeof(char*), compare_strings);
return pointers;
}
/* Recursively shadow the directory whose name is in MASTER
* (which is == MASTER_START) into the destination directory named CURRENT.
*/
DoCopy(master, current, depth)
char *master; /* The source directory. */
char *current; /* The destination directory. */
int depth;
{
struct stat stat_master, stat_current;
char **master_pointer, **current_pointer;
char **master_names, **current_names;
char *master_end, *current_end;
char *master_name_buf, *current_name_buf;
master_end = master + strlen(master);
current_end = current + strlen(current);
/* Get rid of terminal '/' */
if (master_end[-1] == '/' && master != master_end - 1)
*--master_end = 0;
if (current_end[-1] == '/' && current != current_end - 1)
*--current_end = 0;
if (depth >= MAX_DEPTH) {
fprintf(stderr,
"Nesting too deep (depth %d at %s). Probable circularity.\n",
depth, master);
exit(-1);
}
master_name_buf = savedir(master, 500);
if (master_name_buf == NULL) {
fprintf(stderr, "Not enough memory or no such directory: %s\n",
master);
exit(-1);
}
current_name_buf = savedir(current, 500);
if (current_name_buf == NULL) {
fprintf(stderr, "Not enough memory or no such directory: %s\n",
current);
exit(-1);
}
master_names = get_name_pointers(master_name_buf);
current_names = get_name_pointers(current_name_buf);
master_pointer = master_names;
current_pointer = current_names;
for (;;) {
int cmp, ipat;
int in_master, in_current;
char *cur_name;
if (*master_pointer == NULL && *current_pointer == NULL)
break;
if (*master_pointer == NULL) cmp = 1;
else if (*current_pointer == NULL) cmp = -1;
else cmp = strcmp(*master_pointer, *current_pointer);
if (cmp < 0) { /* file only exists in master directory */
in_master = 1; in_current = 0;
} else if (cmp == 0) { /* file exists in both directories */
in_master = 1; in_current = 1;
} else { /* file only exists in current directory */
in_current = 1; in_master = 0;
}
cur_name = in_master ? *master_pointer : *current_pointer;
sprintf(master_end, "/%s", cur_name);
sprintf(current_end, "/%s", cur_name);
for (ipat = 0; ipat < exclude_count; ipat++) {
char *pat = exclude_patterns[ipat];
char *cur;
if (strchr(pat, '/')) cur = current + 2; /* Skip initial "./" */
else cur = cur_name;
if (wildmat(cur, pat)) goto skip;
}
if (in_master)
if (lstat(master, &stat_master) != 0) fatal("stat failed");
if (in_current)
if (lstat(current, &stat_current) != 0) fatal("stat failed");
if (in_current && !in_master) {
if (S_ISLNK(stat_current.st_mode))
if (unlink(current)) {
fprintf(stderr, "Failed to remove symbolic link %s.\n",
current);
}
else
fprintf(stderr, "Removed symbolic link %s.\n",
current);
else {
fprintf(stderr,
"The file %s does not exist in the master tree.\n",
current);
}
}
else if (S_ISDIR(stat_master.st_mode)
&& strcmp(cur_name, "RCS") != 0
&& strcmp(cur_name, "SCCS") != 0) {
if (!in_current) {
if (mkdir(current, 0775)) fatal("mkdir failed");
}
else if (stat(current, &stat_current)) fatal("stat failed");
if (!in_current || stat_current.st_dev != stat_master.st_dev
|| stat_current.st_ino != stat_master.st_ino)
DoCopy(master, current, depth+1);
else
fprintf(stderr, "Link %s is the same as directory %s.\n",
current, master);
}
else {
if (!in_current)
MakeLink(master, current, depth);
else if (!S_ISLNK(stat_current.st_mode)) {
fprintf(stderr, "Existing file %s is not a symbolc link.\n",
current);
} else {
if (stat(current, &stat_current) || stat(master, &stat_master))
fatal("stat failed");
if (stat_current.st_dev != stat_master.st_dev
|| stat_current.st_ino != stat_master.st_ino) {
fprintf(stderr, "Fixing incorrect symbolic link %s.\n",
current);
if (unlink(current)) {
fprintf(stderr, "Failed to remove symbolic link %s.\n",
current);
}
else
MakeLink(master, current, depth);
}
}
}
skip:
if (in_master) master_pointer++;
if (in_current) current_pointer++;
}
free(master_names); free(current_names);
free(master_name_buf); free(current_name_buf);
}

View file

@ -1,147 +0,0 @@
/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $XConsortium: savedir.c,v 1.1 94/04/13 18:26:54 rws Exp $ */
/* savedir.c -- save the list of files in a directory in a string
Copyright 1990, 1993 Free Software Foundation, Inc.
Permission to use, copy, modify, and distribute this program for
any purpose and without fee is hereby granted, provided that this
copyright and permission notice appear on all copies, and that
notice be given that copying and distribution is by permission of
the Free Software Foundation. The Free Software Foundation makes
no representations about the suitability of this software for any
purpose. It is provided "as is" without expressed or implied
warranty.
(The FSF has modified its usual distribution terms, for this file,
as a courtesy to the X project.) */
/* Written by David MacKenzie <djm@ai.mit.edu>.
Modified to use <dirent.h> by default. Per Bothner <bothner@cygnus.com>. */
#include <sys/types.h>
#if !defined(DIRECT) && !defined(BSD)
#include <dirent.h>
#define NLENGTH(direct) (strlen((direct)->d_name))
#else
#undef dirent
#define dirent direct
#define NLENGTH(direct) ((direct)->d_namlen)
#ifdef BSD
#include <sys/dir.h>
#else
#ifdef SYSNDIR
#include <sys/ndir.h>
#else
#include <ndir.h>
#endif
#endif
#endif
#if defined(VOID_CLOSEDIR) || defined(BSD)
/* Fake a return value. */
#define CLOSEDIR(d) (closedir (d), 0)
#else
#define CLOSEDIR(d) closedir (d)
#endif
#ifdef STDC_HEADERS
#include <stdlib.h>
#include <string.h>
#else
char *malloc ();
char *realloc ();
int strlen ();
#ifndef NULL
#define NULL 0
#endif
#endif
char *stpcpy ();
/* Return a freshly allocated string containing the filenames
in directory DIR, separated by '\0' characters;
the end is marked by two '\0' characters in a row.
NAME_SIZE is the number of bytes to initially allocate
for the string; it will be enlarged as needed.
Return NULL if DIR cannot be opened or if out of memory. */
char *
savedir (dir, name_size)
char *dir;
unsigned name_size;
{
DIR *dirp;
struct dirent *dp;
char *name_space;
char *namep;
dirp = opendir (dir);
if (dirp == NULL)
return NULL;
name_space = (char *) malloc (name_size);
if (name_space == NULL)
{
closedir (dirp);
return NULL;
}
namep = name_space;
while ((dp = readdir (dirp)) != NULL)
{
/* Skip "." and ".." (some NFS filesystems' directories lack them). */
if (dp->d_name[0] != '.'
|| (dp->d_name[1] != '\0'
&& (dp->d_name[1] != '.' || dp->d_name[2] != '\0')))
{
unsigned size_needed = (namep - name_space) + NLENGTH (dp) + 2;
if (size_needed > name_size)
{
char *new_name_space;
while (size_needed > name_size)
name_size += 1024;
new_name_space = realloc (name_space, name_size);
if (new_name_space == NULL)
{
closedir (dirp);
return NULL;
}
namep += new_name_space - name_space;
name_space = new_name_space;
}
strcpy (namep, dp->d_name);
namep += strlen (namep) + 1;
}
}
*namep = '\0';
if (CLOSEDIR (dirp))
{
free (name_space);
return NULL;
}
return name_space;
}

View file

@ -1,189 +0,0 @@
/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $XConsortium: wildmat.c,v 1.2 94/04/13 18:40:59 rws Exp $ */
/*
**
** Do shell-style pattern matching for ?, \, [], and * characters.
** Might not be robust in face of malformed patterns; e.g., "foo[a-"
** could cause a segmentation violation. It is 8bit clean.
**
** Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
** Rich $alz is now <rsalz@bbn.com>.
** April, 1991: Replaced mutually-recursive calls with in-line code
** for the star character.
**
** Special thanks to Lars Mathiesen <thorinn@diku.dk> for the ABORT code.
** This can greatly speed up failing wildcard patterns. For example:
** pattern: -*-*-*-*-*-*-12-*-*-*-m-*-*-*
** text 1: -adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1
** text 2: -adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1
** Text 1 matches with 51 calls, while text 2 fails with 54 calls. Without
** the ABORT, then it takes 22310 calls to fail. Ugh. The following
** explanation is from Lars:
** The precondition that must be fulfilled is that DoMatch will consume
** at least one character in text. This is true if *p is neither '*' nor
** '\0'.) The last return has ABORT instead of FALSE to avoid quadratic
** behaviour in cases like pattern "*a*b*c*d" with text "abcxxxxx". With
** FALSE, each star-loop has to run to the end of the text; with ABORT
** only the last one does.
**
** Once the control of one instance of DoMatch enters the star-loop, that
** instance will return either TRUE or ABORT, and any calling instance
** will therefore return immediately after (without calling recursively
** again). In effect, only one star-loop is ever active. It would be
** possible to modify the code to maintain this context explicitly,
** eliminating all recursive calls at the cost of some complication and
** loss of clarity (and the ABORT stuff seems to be unclear enough by
** itself). I think it would be unwise to try to get this into a
** released version unless you have a good test data base to try it out
** on.
*/
#define TRUE 1
#define FALSE 0
#define ABORT -1
/* What character marks an inverted character class? */
#define NEGATE_CLASS '^'
/* Is "*" a common pattern? */
#define OPTIMIZE_JUST_STAR
/* Do tar(1) matching rules, which ignore a trailing slash? */
#undef MATCH_TAR_PATTERN
/*
** Match text and p, return TRUE, FALSE, or ABORT.
*/
static int
DoMatch(text, p)
register char *text;
register char *p;
{
register int last;
register int matched;
register int reverse;
for ( ; *p; text++, p++) {
if (*text == '\0' && *p != '*')
return ABORT;
switch (*p) {
case '\\':
/* Literal match with following character. */
p++;
/* FALLTHROUGH */
default:
if (*text != *p)
return FALSE;
continue;
case '?':
/* Match anything. */
continue;
case '*':
while (*++p == '*')
/* Consecutive stars act just like one. */
continue;
if (*p == '\0')
/* Trailing star matches everything. */
return TRUE;
while (*text)
if ((matched = DoMatch(text++, p)) != FALSE)
return matched;
return ABORT;
case '[':
reverse = p[1] == NEGATE_CLASS ? TRUE : FALSE;
if (reverse)
/* Inverted character class. */
p++;
for (last = 0400, matched = FALSE; *++p && *p != ']'; last = *p)
/* This next line requires a good C compiler. */
if (*p == '-' ? *text <= *++p && *text >= last : *text == *p)
matched = TRUE;
if (matched == reverse)
return FALSE;
continue;
}
}
#ifdef MATCH_TAR_PATTERN
if (*text == '/')
return TRUE;
#endif /* MATCH_TAR_ATTERN */
return *text == '\0';
}
/*
** User-level routine. Returns TRUE or FALSE.
*/
int
wildmat(text, p)
char *text;
char *p;
{
#ifdef OPTIMIZE_JUST_STAR
if (p[0] == '*' && p[1] == '\0')
return TRUE;
#endif /* OPTIMIZE_JUST_STAR */
return DoMatch(text, p) == TRUE;
}
#ifdef TEST
#include <stdio.h>
/* Yes, we use gets not fgets. Sue me. */
extern char *gets();
main()
{
char p[80];
char text[80];
printf("Wildmat tester. Enter pattern, then strings to test.\n");
printf("A blank line gets prompts for a new pattern; a blank pattern\n");
printf("exits the program.\n");
for ( ; ; ) {
printf("\nEnter pattern: ");
(void)fflush(stdout);
if (gets(p) == NULL || p[0] == '\0')
break;
for ( ; ; ) {
printf("Enter text: ");
(void)fflush(stdout);
if (gets(text) == NULL)
exit(0);
if (text[0] == '\0')
/* Blank line; go back and get a new pattern. */
break;
printf(" %s\n", wildmat(text, p) ? "YES" : "NO");
}
}
exit(0);
/* NOTREACHED */
}
#endif /* TEST */