private String
substitute(String spec, long n) throws IOException {
	boolean escaped = false;
	byte [] str = spec.getBytes();
	StringBuffer sb = new StringBuffer();

	for (int i = 0; i < str.length; i++) {
		char c = (char)(str[i] & 0xFF);
		if (escaped) {
			sb.append(c);
			escaped = false;
		} else if (c == '\\') {
			if (i + 1 == str.length)
				throw new TextParseException
						("invalid escape character");
			escaped = true;
		} else if (c == '$') {
			boolean negative = false;
			long offset = 0;
			long width = 0;
			long base = 10;
			boolean wantUpperCase = false;
			if (i + 1 < str.length && str[i + 1] == '$') {
				// '$$' == literal '$' for backwards
				// compatibility with old versions of BIND.
				c = (char)(str[++i] & 0xFF);
				sb.append(c);
				continue;
			} else if (i + 1 < str.length && str[i + 1] == '{') {
				// It's a substitution with modifiers.
				i++;
				if (i + 1 < str.length && str[i + 1] == '-') {
					negative = true;
					i++;
				}
				while (i + 1 < str.length) {
					c = (char)(str[++i] & 0xFF);
					if (c == ',' || c == '}')
						break;
					if (c < '0' || c > '9')
						throw new TextParseException(
							"invalid offset");
					c -= '0';
					offset *= 10;
					offset += c;
				}
				if (negative)
					offset = -offset;

				if (c == ',') {
					while (i + 1 < str.length) {
						c = (char)(str[++i] & 0xFF);
						if (c == ',' || c == '}')
							break;
						if (c < '0' || c > '9')
							throw new
							   TextParseException(
							   "invalid width");
						c -= '0';
						width *= 10;
						width += c;
					}
				}

				if (c == ',') {
					if  (i + 1 == str.length)
						throw new TextParseException(
							   "invalid base");
					c = (char)(str[++i] & 0xFF);
					if (c == 'o')
						base = 8;
					else if (c == 'x')
						base = 16;
					else if (c == 'X') {
						base = 16;
						wantUpperCase = true;
					}
					else if (c != 'd')
						throw new TextParseException(
							   "invalid base");
				}

				if (i + 1 == str.length || str[i + 1] != '}')
					throw new TextParseException
						("invalid modifiers");
				i++;
			}
			long v = n + offset;
			if (v < 0)
				throw new TextParseException
						("invalid offset expansion");
			String number;
			if (base == 8)
				number = Long.toOctalString(v);
			else if (base == 16)
				number = Long.toHexString(v);
			else
				number = Long.toString(v);
			if (wantUpperCase)
				number = number.toUpperCase();
			if (width != 0 && width > number.length()) {
				int zeros = (int)width - number.length();
				while (zeros-- > 0)
					sb.append('0');
			}
			sb.append(number);
		} else {
			sb.append(c);
		}
	}
	return sb.toString();
}
Creates a specification for generating records, as a $GENERATE
statement in a master file.
@param start The start of the range.
@param end The end of the range.
@param step The step value of the range.
@param namePattern The pattern to use for generating record names.
@param type The type of the generated records.  The supported types are
PTR, CNAME, DNAME, A, AAAA, and NS.
@param dclass The class of the generated records.
@param ttl The ttl of the generated records.
@param rdataPattern The pattern to use for generating record data.
@param origin The origin to append to relative names.
@throws IllegalArgumentException The range is invalid.
@throws IllegalArgumentException The type does not support generation.
@throws IllegalArgumentException The dclass is not a valid class.
src/main/java/core/org/xbill/DNS/Generator.java