From 588bd802d15f45ae57009e3645a05e01fa69a65a Mon Sep 17 00:00:00 2001 From: sof Date: Sun, 17 Aug 1997 18:38:43 +0000 Subject: [PATCH] [project @ 1997-08-17 18:38:36 by sof] Removed:unused --- glafp-utils/msub/Makefile | 7 - glafp-utils/msub/msub.c | 520 ---------------------------------------- glafp-utils/msub/msub.man | 274 --------------------- glafp-utils/msub/msub.ms | 128 ---------- glafp-utils/msub/test.makefile | 18 -- glafp-utils/msub/test.stdout | 11 - glafp-utils/msub/testfile | 13 - 7 files changed, 971 deletions(-) delete mode 100644 glafp-utils/msub/Makefile delete mode 100644 glafp-utils/msub/msub.c delete mode 100644 glafp-utils/msub/msub.man delete mode 100644 glafp-utils/msub/msub.ms delete mode 100644 glafp-utils/msub/test.makefile delete mode 100644 glafp-utils/msub/test.stdout delete mode 100644 glafp-utils/msub/testfile diff --git a/glafp-utils/msub/Makefile b/glafp-utils/msub/Makefile deleted file mode 100644 index 2a0d89b..0000000 --- a/glafp-utils/msub/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -TOP=.. -include $(TOP)/mk/boilerplate.mk - -C_SRCS=msub.c -C_PROG=msub -CLEAN_FILES += $(C_PROG) $(C_OBJS) -include $(TOP)/mk/target.mk diff --git a/glafp-utils/msub/msub.c b/glafp-utils/msub/msub.c deleted file mode 100644 index dc90b47..0000000 --- a/glafp-utils/msub/msub.c +++ /dev/null @@ -1,520 +0,0 @@ -/* - msub - Read file(s) and perform substitutions using values of - variables defined in makefile. - - Syntax: msub [-f makefile] [file ...] - - Multiple -f options may be given. - - 27 Mar 1990 Paul DuBois dubois@primate.wisc.edu - - 27 Mar 1990 V1.0. Created. -*/ - -# include -# include -# include - -# define true (1) -# define false (0) - - -extern char *calloc (); - - -char *NewString(); - - -typedef struct Def Def; - -struct Def -{ - char *var; /* variable name */ - char *val; /* variable value */ - int simple; /* whether value has been expanded */ - Def *nextDef; /* next definition in list */ -}; - - -char *usage = "Usage: msub [ -f makefile ] file"; -char *makefile = NULL; -Def *defList = NULL; /* list of definitions */ -int nDefs = 0; /* number of definitions */ -int changes; - -main (argc, argv) -int argc; -char **argv; -{ -FILE *f; -Def *dp; -int i, pass; - - --argc; - ++argv; - - while (argc > 0 && argv[0][0] == '-') - { - if (strcmp (argv[0], "-f") == 0) - { - if (argc < 2) - panic (usage); - if ((f = fopen (makefile = argv[1], "r")) == NULL) - panic ("Can't open makefile"); - ReadMake (f); - fclose (f); - argc -= 2; - argv += 2; - } - else - panic (usage); /* bad flag */ - } - - if (makefile == NULL) /* no -f options given */ - { - if ((f = fopen ("makefile", "r")) == NULL) - { - if ((f = fopen ("Makefile", "r")) == NULL) - panic ("Can't open makefile"); - } - ReadMake (f); - fclose (f); - } - - EncodeEscapes (); - - /* determine which values need expanding */ - for (dp = defList; dp != NULL; dp = dp->nextDef) - dp->simple = !FindVarRef (dp->val, NULL, NULL, false); - - /* expand values to eliminate embedded var references */ - for (pass = 0; pass < nDefs; pass++) - { - changes = 0; - for (dp = defList; dp != NULL; dp = dp->nextDef) - { - if (!dp->simple) - Expand (dp); - } - if (changes == 0) /* loop while values expand */ - break; - } - - /* sanity check: shouldn't have to make more than nDefs passes */ - if (pass >= nDefs) - panic ("Too many expansion passes. Something's wrong!"); - - DecodeEscapes (); - - /* partain addition: - args of form "foo=bar" are taken to be defs to add in - */ - while (argc > 0 && strchr(argv[0], '=') && isalpha(argv[0][0])) - { - char name[BUFSIZ], *np, *p; - int len; - p = argv[0]; - /* copied from below */ - np = name; - while (isalnum (*p) || *p == '_') - *np++ = *p++; - *np = '\0'; - while (isspace (*p)) /* skip whitespace */ - ++p; - if (*p++ == '=') /* it's a definition */ - { - /* skip leading/trailing whitespace */ - while (isspace (*p)) - ++p; - len = strlen (p); - while (len > 0 && isspace (p[len-1])) - p[--len] = '\0'; - AddDef (name, p, 1); - /* find var refs in value -- NUKED */ - /* FindAllVarRefs (p); */ - /* also NUKED: continue; */ - } - /* end of: copied from below */ - --argc; - ++argv; - } - /* end of partain addition */ - - /* read source file(s) and perform substitutions */ - if (argc == 0) - DoSub (stdin); - else while (argc > 0) - { - if ((f = fopen (*argv, "r")) == NULL) - { - fprintf (stderr, "Can't open \"%s\". ", *argv); - panic ("Quitting."); - } - DoSub (f); - fclose (f); - --argc; - ++argv; - } - - exit (0); -} - - -/* - Read a makefile. -*/ - -ReadMake (f) -FILE *f; -{ -char input[BUFSIZ * 4], name[BUFSIZ], *p, *np; -int i, len; - - while (GetLine (f, input)) /* get line, check whether def'n */ - { - for (p = input; isspace (*p); p++) { /* nop */ } - if (*p == '#' || *p == '\0') /* comment or blank line */ - continue; - if (isalpha (*p)) /* look for var name */ - { - np = name; - while (isalnum (*p) || *p == '_') - *np++ = *p++; - *np = '\0'; - while (isspace (*p)) /* skip whitespace */ - ++p; - if (*p++ == '=') /* it's a definition */ - { - /* skip leading/trailing whitespace */ - while (isspace (*p)) - ++p; - len = strlen (p); - while (len > 0 && isspace (p[len-1])) - p[--len] = '\0'; - AddDef (name, p, 1); - /* find var refs in value */ - FindAllVarRefs (p); - continue; - } - } - /* not a definition; find var refs anywhere in line */ - FindAllVarRefs (input); - } -} - - -/* - Find definition by variable name. -*/ - -Def *FindDefByVar (s) -char *s; -{ -Def *dp; - - for (dp = defList; dp != NULL; dp = dp->nextDef) - { - if (strcmp (dp->var, s) == 0) - return (dp); - } - return (NULL); -} - - -/* - Add a definition. If the name hasn't been seen yet, create a new - definition on the list. If the name has been seen, and replace is - non-zero, replace the current value with the new one. (replace will - be zero if we're just adding a variable which is known by its being - referenced somewhere.) -*/ - -AddDef (name, value, replace) -char *name, *value; -int replace; -{ -Def *dp; - - if ((dp = FindDefByVar (name)) == NULL) - { - if ((dp = (Def *) calloc (1, sizeof (Def))) == NULL) - panic ("AddDef: out of memory"); - dp->var = NewString (name); - dp->val = NewString (value); - dp->simple = 0; /* assume not */ - dp->nextDef = defList; - defList = dp; - ++nDefs; - } - else if (replace) - { - free (dp->val); - dp->val = NewString (value); - } -} - - -/* - Replace instances of '$$' with a single ^A. -*/ - -EncodeEscapes () -{ -Def *dp; -char *p, *q; - - for (dp = defList; dp != NULL; dp = dp->nextDef) - { - for (p = q = dp->val; *p != '\0'; p++, q++) - { - *q = *p; - if (*p == '$' && *(p+1) == '$') - { - *q = '\01'; - p++; - } - } - *q = '\0'; - } -} - - -/* - Replace instances of ^A with a '$'. -*/ - -DecodeEscapes () -{ -Def *dp; -char *p; - - for (dp = defList; dp != NULL; dp = dp->nextDef) - { - for (p = dp->val; *p != '\0'; p++) - { - if (*p == '\01') - *p = '$'; - } - } -} - - -/* - Find variable reference in variable value. begin is set to - the index of the '$' and end is set to the index of the closing - delimiter. (If either is NULL, it is not set.) - - recogEsc is non-zero (true) if '$$' is recognized as an escaped '$' - and skipped. It will be true during initial searching for var refs - and while substituting in source files, false while expanding variable - values. - - $v, ${}, ${1}, ${v), etc. are not accepted as valid and are ignored. -*/ - -FindVarRef (s, beg, end, recogEsc) -char *s; -int *beg, *end, recogEsc; -{ -int i; -char c, delim; - - i = 0; - for (;;) - { - while ((c = s[i]) != '\0') - { - if (c == '$') - { - if ((c = s[i+1]) == '{' || c == '(') - break; - if (recogEsc && c == '$') /* escaped $ */ - ++i; - } - ++i; - } - if (c == '\0') - return (0); /* no reference */ - if (beg != (int *) NULL) - *beg = i; - if (s[++i] == '{') - delim = '}'; - else - delim = ')'; - ++i; - if (!isalpha (s[i])) /* must have at least one char, must */ - continue; /* begin with letter */ - while ((c = s[++i]) != '\0') - { - if (c == delim) /* find matching delim */ - { - if (end != (int *) NULL) - *end = i; - return (1); - } - if (!isalnum (c) && c != '_') - break; - } - } -} - - -FindAllVarRefs (s) -char *s; -{ -char name[BUFSIZ]; -int begin, end; - - while (FindVarRef (s, &begin, &end, true)) - { - /* add with empty value if unknown, */ - /* but don't replace value if known */ - strncpy (name, s + begin + 2, end - begin - 2); - name[end-begin-2] = '\0'; - AddDef (name, "", 0); - s += end + 1; - } -} - - -/* - Pull out a variable reference, skipping leading '$(' or '${' and - trailing ')' or '}'. -*/ - -YankVarRef (dst, src, begin, end) -char *dst, *src; -int begin, end; -{ - strncpy (dst, src + begin + 2, end - begin - 2); - dst[end - begin - 2] = '\0'; -} - - -/* - Look for variable references in a variable value and expand them - when possible. If a variable is referenced but never defined, it - disappears. If a variable is referenced, but its value has not itself - been fully expanded, defer expansion of value until another pass, at - which time the referenced variable might then be expanded. This - prevents infinite expansions on circular references. -*/ - -Expand (dp) -Def *dp; -{ -Def *dp2; -/* partain: made 4 * BUFSIZ -char buf[BUFSIZ]; -*/ -char buf[4 * BUFSIZ]; -int begin, end, vn; - - while (FindVarRef (dp->val, &begin, &end, false)) - { - YankVarRef (buf, dp->val, begin, end); - if ((dp2 = FindDefByVar (buf)) == NULL) - { - fprintf (stderr, "Expand error: can't find %s, ", buf); - panic ("quitting"); - } - if (!dp2->simple) /* can't expand, give up for now */ - break; - dp->val[begin] = '\0'; - sprintf (buf, "%s%s%s", dp->val, dp2->val, &(dp->val)[end+1]); - free (dp->val); - dp->val = NewString (buf); - ++changes; - } - dp->simple = !FindVarRef (dp->val, NULL, NULL, false); -} - - -/* - Read through file, performing substitutions for any variables - known from Makefile. If a variable reference is found that is - for an unknown variable, leave it alone, as it may be a reference - to a real variable in a shell script. -*/ - -DoSub (f) -FILE *f; -{ -Def *dp; -char input[BUFSIZ], var[BUFSIZ], *p; -int begin, end; - - while (fgets (input, sizeof (input), f) != NULL) - { - p = input; - while (FindVarRef (p, &begin, &end, true)) - { - write (1, p, begin); /* write prefix */ - YankVarRef (var, p, begin, end); - /* if var is known from makefile, write */ - /* value, else just echo the reference */ - if ((dp = FindDefByVar (var)) != NULL) - write (1, dp->val, strlen (dp->val)); - else - write (1, p + begin, end - begin + 1); - p += end + 1; - } - write (1, p, strlen (p)); - } -} - - -/* - Get next line from Makefile (combines continuation lines into one). - No overflow checking, oops. -*/ - -GetLine (f, lbuf) -FILE *f; -char *lbuf; -{ -char buf[BUFSIZ]; -int loop = 1, haveLine = 0, len; - - *lbuf = '\0'; - while (loop && fgets (buf, sizeof (buf), f) != NULL) - { - loop = 0; - haveLine = 1; - len = strlen (buf); - if (len > 0 && buf[len-1] == '\n') /* trim newline */ - buf[--len] = '\0'; - if (len > 0 && buf[len-1] == '\\') /* need continuation */ - { - loop = 1; - buf[--len] = ' '; - } - strcat (lbuf, buf); - } - return (haveLine); -} - - -/* - Allocate space for a string, copy the string into it, and return - a pointer to the copy. -*/ - - -char *NewString (s) -char *s; -{ -char *p; - - if ((p = calloc (1, strlen (s) + 1)) == NULL) - panic ("NewString: out of space"); - return (strcpy (p, s)); -} - - -panic (s) -char *s; -{ - fprintf (stderr, "%s\n", s); - exit (1); -} diff --git a/glafp-utils/msub/msub.man b/glafp-utils/msub/msub.man deleted file mode 100644 index 51fd5a6..0000000 --- a/glafp-utils/msub/msub.man +++ /dev/null @@ -1,274 +0,0 @@ -.TH MSUB 1 -.SH NAME -msub \- substitute \fImake\fR variables into template to produce script -.SH SYNOPSIS -.B msub -[ -.B \-e -] [ -.B \-f -.I file -] [ -.BI \+R str -] [ -.BI \-R str -] [ -.IB variable = value -] [ -.I file -\&... -] -.SH DESCRIPTION -Makefiles often contain project configuration information specified as -.I make -variables, and it is often desirable to make use of that information in other -files. -.I msub -allows targets to be produced easily -from templates that contain references to those variables. -.I msub -is particularly useful in software projects that use -.IR imake -because virtually all configuration parameters are written into Makefiles -and are thus available for propagation into other files. -.PP -First -.I msub -reads the -.I Makefile -and finds all variable definition lines -of the form ``\fIvar\fR = \fIvalue\fR''. -Then -.I msub -reads any files named on the command line (or the standard input -if none), looks for references to those variables, and replaces the -references with the corresponding variable values. -References to undefined variables are replaced by the empty string. -The result is written to the standard output. -.PP -.I msub -takes the following options: -.TP -.B \-e -Environment variable values override assignments within Makefiles. -Normally assignments within Makefiles override environment variables. -.TP -.BI \-f \ file -By default, variable values are extracted from -.I Makefile -(or -.I makefile -if -.I Makefile -is missing) in the current directory. -If the -.B \-f -.I file -option is given, variable values are extracted from -.I file -instead. -Multiple -.B \-f -options may be specified. -(Note: -.I make -recognizes -.B \-f\ \- -to mean the -.I Makefile -should be read from -.IR stdin . -.I msub -doesn't, because template input may come from -.IR stdin .) -.TP -.BI +R str -.TP -.BI \-R str -The default variable reference indicators within templates -are the same as in Makefiles, i.e., -``$('' and ``)'', and ``${'' and ``}''. -These can be changed with the -.B +R -and -.B \-R -options, which must be specified in pairs. -.B +R -specifies the string that initiates a variable reference and -.B \-R -specifies the string that terminates it. -Multiple pairs of reference indicators may be given. -.TP -.IB variable = value -Variable definition. -This definition overrides any regular definition for the specified -variable within the makefile itself or in the environment. -.SH EXAMPLES -Suppose you want to produce for a program a help file that indicates the local -e-mail address to which questions may be directed. -If this address is specified as the variable EMAILHELPADDR in the -.IR Makefile , -you can write a template -.I helpfile.msub -like this: -.in +.5i -.nf -.sp .5v -\&.\|.\|.\|\fIstuff\fP\|.\|.\|. -Please direct questions to ${EMAILHELPADDR}. -\&.\|.\|.\|\fImore stuff\fP\|.\|.\|. -.sp .5v -.fi -.in -Process the template to produce the help file like this: -.in +.5i -.nf -.sp .5v -msub helpfile.msub > helpfile -.sp .5v -.fi -.in -If the -.I Makefile -contains the following lines: -.in +.5i -.nf -.sp .5v -EMAILHELPADDR = postmaster@$(DOMAIN) -DOMAIN = primate.wisc.edu -.sp .5v -.fi -.in -then -.I helpfile -will look like this: -.in +.5i -.nf -.sp .5v -\&.\|.\|.\|\fIstuff\fP\|.\|.\|. -Please direct questions to postmaster@primate.wisc.edu. -\&.\|.\|.\|\fImore stuff\fP\|.\|.\|. -.sp .5v -.fi -.in -.I msub -can produce executable scripts, too. -If the processor for which you're producing -the script allows variable references, make sure you refer to -.I make -variables in the template in a different way than the processor refers to -variables. -For instance, ``${\fIvar\fP}'' is ambiguous in a shell script template \- is -it a reference to a shell variable that you want -.I msub -to leave alone, or to a -.I make -variable for which you want -.I msub -to substitute the variable's value? -To resolve the ambiguity, you can refer to shell variables as ``$\fIvar\fP'' -(which the shell recognizes, but -.I msub -doesn't), or you can use different indicators than the defaults to refer to -.I make -variables in the template. -For example, you could use ``@<'' and ``>@'' and refer to variables as -``@<\fIvar\fP>@''. -Suppose you have a simple shell script to print your home directory pathname. -You might write it like this: -.in +.5i -.nf -.sp .5v -#!@@ -echo ${HOME} -.sp .5v -.fi -.in -Then you can process the template like this (note that you must quote the -arguments because ``<'' and ``>'' are special to the shell): -.in +.5i -.nf -.sp .5v -msub +R"@<" \-R">@" template > script -.sp .5v -.fi -.in -The -.B +R/\-R -arguments cause -.I msub -to recognize ``@@'' but not ``${HOME}''. -The result looks like this: -.in +.5i -.nf -.sp .5v -#!/bin/sh -echo ${HOME} -.sp .5v -.fi -.in -.SH "WHO-TO-BLAME" -Paul DuBois, dubois@primate.wisc.edu -.SH "BUGS AND RESTRICTIONS" -CC, YACC, etc., have implicit values in -.I make -even if they're not defined in the -.IR Makefile , -which isn't true for -.IR msub . -However, when -.I msub -is used with -.IR imake , -this isn't normally a problem since -.IR imake -generated -Makefiles tend to contain explicit definitions for every parameter in the -known universe. -.PP -.I msub -is more restrictive in the variable names it recognizes and -performs substitutions on than -.IR make . -.I make -allows single character names to be referenced as ``$\fIc\fP'', where -.I c -is a letter; -.I msub -doesn't. -.I msub -also ignores -.I make -variables like -``$*'' and ``$@''. -.PP -Recursive references in -.I Makefile -variables aren't expanded. -If a -.I Makefile -contains the definition ``X = ${X}'', X won't be expanded. -Indirectly recursive references aren't expanded, either. -If a -.I Makefile -contains the definitions ``X = ${Y}'' and ``Y = ${X}'', -neither X nor Y will be expanded. -(These actually aren't bugs in -.IR msub , -they're problems in the -.IR Makefile .) -.PP -A comment at the end of a variable assignment line become part of the -variable's value. -If -.I Makefile -contains the following line: -.in +.5i -.nf -.sp .5v -SHELL = /bin/shell # default shell -.sp .5v -.fi -.in -then -.I msub -takes the value of SHELL to be ``/bin/shell # default shell''. diff --git a/glafp-utils/msub/msub.ms b/glafp-utils/msub/msub.ms deleted file mode 100644 index 7fe019f..0000000 --- a/glafp-utils/msub/msub.ms +++ /dev/null @@ -1,128 +0,0 @@ -.SH -Theory of Operation -.LP -.I msub -reads the makefile in the current directory (or the file named after the -.B \-f -flag) and finds all variable definitions and references. -Definitions are lines of the form ``\fIname\fR = \fIvalue\fR''. -References are instances of ``$(\fIvar\fR)'' or ``${\fIvar\fR}'', either in -the value part of definition lines, or any part of dependency or command lines. -Then variable values are examined to eliminate references to other variables -by replacing the referenced variables with their values. -Variables which are referenced but never defined have a value of the empty -string. -.LP -Then -.I msub -reads any files named on the command line (or -.I stdin -if none) and looks for instances of ``$(\fIvar\fR)'' or ``${\fIvar\fR}'', -where -.I var -is known from the makefile, and substitutes the value of -.I var . -.SH -Purpose -.LP -The motivation for -.I msub -is that project configuration information is often contained in makefiles -and it is often desirable to make use of that information. -.I msub -allows files to be produced from templates that contain references -to makefile variables. -In this sense it is similar to the way that the C preprocessor -.I cpp -uses #define statements in header files; the -makefile is the implicit ``header'' file and definition lines are the -``#define'' statements. -.LP -Although it is possible to use -.I cpp -to perform substitutions on templates, a disadvantage of -.I cpp -is that it modifies its source in other ways (eg., lines beginning with -``#'' are special and comments (``/* ... */'') are deleted. -Also, it is necessary to pass a -D flag for every symbol to be substituted. -Similarly, for C programs it can be simpler to use -.I msub -to produce a single configuration header file from a template -than to pass a lot of -D flags to each invocation of -.I cc . -.LP -.I msub -performs no textual modification besides substitution of references -to makefile variables; it leaves everything else alone. -In particular, -references to variables not known from the makefile are left untouched. -This allows -.I msub -to be used to produce shell scripts that use variables of -their own. -.LP -.I msub -is particularly useful in software projects that use -.I imake . -Virtually all configuration information is propagated into makefiles -thus produced, so it is available for propagation into other files using -.I msub . -.SH -Problems -.LP -If -.I msub -is used to produce shell scripts, it is unwise for the script to use names -for its own variables that are the same as those in the makefile. -The problem can be avoided entirely if, for instance, variables in makefiles -are all uppercase and the scripts' own variables are lowercase or mixed case. -.LP -Circular references in makefile variables are not expanded. -If a makefile contains the definitions ``X = ${Y}'' and ``Y = ${X}'', -neither X nor Y will be expanded. -But that is really a problem with the makefile, not -.I msub . -.LP -.I make -recognizes -.B \-f\ \- -to mean the makefile should be read from -.I stdin . -.I msub -does not. -.LP -CC, YACC, etc., have implicit values in -.I make -even if not defined in the makefile. -Not true in -.I msub . -.LP -.I msub -is more restrictive in the variable names that it recognizes and -performs substitutions on. -Names that do not begin with a letter and -that contain any characters besides letters, digits and underscores are -ignored. -This means that variable names such as ``${1}'' are not recognized; -the reason for this is that shell scripts often use such variables and -they should be left untouched. -Also, -``$\fIx\fR'' is legal in -.I make -when -.I x -is a single character, but -.I msub -ignores such references. -.i msub -.LP -.I make -allows variables to be defined on the command line. -.I msub -does not. -.LP -If you try to be tricky with your variable references, e.g., by using -recursive references, you may get burned. -.LP -There is no way to prevent substitution, in a source file, of a reference to -a variable known from the makefile. diff --git a/glafp-utils/msub/test.makefile b/glafp-utils/msub/test.makefile deleted file mode 100644 index 1245db3..0000000 --- a/glafp-utils/msub/test.makefile +++ /dev/null @@ -1,18 +0,0 @@ -foo = ${bar} -bar = ${ugh} -ugh = Huh? -space = x -a = ${wildcard x} - -c : ${xyz} - -xyz = abc - - -dollar = $$ -doubledollar = ${dollar}${dollar} - -X1 = Y -X2 = 1 -Y1 = y1 -Y2 = ${${X1}${X2}} diff --git a/glafp-utils/msub/test.stdout b/glafp-utils/msub/test.stdout deleted file mode 100644 index 506999f..0000000 --- a/glafp-utils/msub/test.stdout +++ /dev/null @@ -1,11 +0,0 @@ -foo = Huh? -bar = Huh? -ugh = Huh? -xy -${wildcard x} - -This (abc) should be abc. - -This should be a single dollar: $ -This should be a double dollar: $$ -So should this: $$ diff --git a/glafp-utils/msub/testfile b/glafp-utils/msub/testfile deleted file mode 100644 index 46f37f6..0000000 --- a/glafp-utils/msub/testfile +++ /dev/null @@ -1,13 +0,0 @@ -foo = ${foo} -bar = ${bar} -ugh = ${ugh} -${space}y -${a} - -The stuff in parens should be "abc": (${xyz}) - -This should be a single dollar-sign: ${dollar} -This should be a double dollar-sign: ${dollar}${dollar} -So should this: ${doubledollar} - -This should say "y1": ${Y2} -- 1.7.10.4