Blame SOURCES/kexec-tools-2.0.15-makedumpfile-Add-a-new-helper-file-tools.c-that-provides-some-use.patch

26a7a5
From 4d86cc76f09f7632bb60833832406d7f294baf25 Mon Sep 17 00:00:00 2001
26a7a5
From: Bhupesh Sharma <bhsharma@redhat.com>
26a7a5
Date: Tue, 6 Mar 2018 02:13:00 +0900
26a7a5
Subject: [PATCH 1/3] Add a new helper file 'tools.c' that provides some useful
26a7a5
 APIs
26a7a5
26a7a5
This patch borrows the 'tools.c' helper file from the crash utility
26a7a5
project and adds it to the makedumpfile source code, to allow
26a7a5
some basic useful APIs to be present which can be invoked from
26a7a5
other source code files.
26a7a5
26a7a5
'tools.c' provides some useful APIs like 'htol' (convert
26a7a5
a string to a hexadecimal long value), etc. which can be
26a7a5
invoked by other functions (a functionality that is exposed
26a7a5
by follow-up patches).
26a7a5
26a7a5
Signed-off-by: Bhupesh Sharma <bhsharma@redhat.com>
26a7a5
---
26a7a5
 Makefile       |   2 +-
26a7a5
 common.h       |   8 +
26a7a5
 makedumpfile.h |  14 ++
26a7a5
 tools.c        | 766 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
26a7a5
 4 files changed, 789 insertions(+), 1 deletion(-)
26a7a5
 create mode 100644 tools.c
26a7a5
26a7a5
diff --git a/makedumpfile-1.6.2/Makefile b/makedumpfile-1.6.2/Makefile
26a7a5
index f4b7c56b6f3d..e870b1362c95 100644
26a7a5
--- a/makedumpfile-1.6.2/Makefile
26a7a5
+++ b/makedumpfile-1.6.2/Makefile
26a7a5
@@ -46,7 +46,7 @@ CFLAGS_ARCH += -m32
26a7a5
 endif
26a7a5
 
26a7a5
 SRC_BASE = makedumpfile.c makedumpfile.h diskdump_mod.h sadump_mod.h sadump_info.h
26a7a5
-SRC_PART = print_info.c dwarf_info.c elf_info.c erase_info.c sadump_info.c cache.c
26a7a5
+SRC_PART = print_info.c dwarf_info.c elf_info.c erase_info.c sadump_info.c cache.c tools.c
26a7a5
 OBJ_PART=$(patsubst %.c,%.o,$(SRC_PART))
26a7a5
 SRC_ARCH = arch/arm.c arch/arm64.c arch/x86.c arch/x86_64.c arch/ia64.c arch/ppc64.c arch/s390x.c arch/ppc.c arch/sparc64.c
26a7a5
 OBJ_ARCH=$(patsubst %.c,%.o,$(SRC_ARCH))
26a7a5
diff --git a/makedumpfile-1.6.2/common.h b/makedumpfile-1.6.2/common.h
26a7a5
index 6ad3ca7b952c..6e2f657a79c7 100644
26a7a5
--- a/makedumpfile-1.6.2/common.h
26a7a5
+++ b/makedumpfile-1.6.2/common.h
26a7a5
@@ -19,6 +19,8 @@
26a7a5
 #define TRUE		(1)
26a7a5
 #define FALSE		(0)
26a7a5
 #define ERROR		(-1)
26a7a5
+#define UNUSED   	(-1)
26a7a5
+#define RETURN_ON_ERROR  	(0x2)
26a7a5
 
26a7a5
 #ifndef LONG_MAX
26a7a5
 #define LONG_MAX	((long)(~0UL>>1))
26a7a5
@@ -35,12 +37,18 @@
26a7a5
 #define round(x, y)	(((x) / (y)) * (y))
26a7a5
 #define roundup(x, y)	((((x) + ((y) - 1)) / (y)) * (y))
26a7a5
 
26a7a5
+#define NUM_HEX  (0x1)
26a7a5
+#define NUM_DEC  (0x2)
26a7a5
+#define NUM_EXPR (0x4)
26a7a5
+#define NUM_ANY  (NUM_HEX|NUM_DEC|NUM_EXPR)
26a7a5
+
26a7a5
 /*
26a7a5
  * Incorrect address
26a7a5
  */
26a7a5
 #define NOT_MEMMAP_ADDR	(0x0)
26a7a5
 #define NOT_KV_ADDR	(0x0)
26a7a5
 #define NOT_PADDR	(ULONGLONG_MAX)
26a7a5
+#define BADADDR  	((ulong)(-1))
26a7a5
 
26a7a5
 #endif  /* COMMON_H */
26a7a5
 
26a7a5
diff --git a/makedumpfile-1.6.2/makedumpfile.h b/makedumpfile-1.6.2/makedumpfile.h
26a7a5
index c2143a8d794b..733ac4ef40d1 100644
26a7a5
--- a/makedumpfile-1.6.2/makedumpfile.h
26a7a5
+++ b/makedumpfile-1.6.2/makedumpfile.h
26a7a5
@@ -244,6 +244,9 @@ isAnon(unsigned long mapping)
26a7a5
 #define MIN_ELF_HEADER_SIZE \
26a7a5
 	MAX(MIN_ELF32_HEADER_SIZE, MIN_ELF64_HEADER_SIZE)
26a7a5
 static inline int string_exists(char *s) { return (s ? TRUE : FALSE); }
26a7a5
+#define STREQ(A, B) (string_exists((char *)A) && 	\
26a7a5
+		     string_exists((char *)B) && 	\
26a7a5
+	(strcmp((char *)(A), (char *)(B)) == 0))
26a7a5
 #define STRNEQ(A, B)(string_exists((char *)(A)) &&	\
26a7a5
 		     string_exists((char *)(B)) &&	\
26a7a5
 	(strncmp((char *)(A), (char *)(B), strlen((char *)(B))) == 0))
26a7a5
@@ -2328,4 +2331,15 @@ int prepare_splitblock_table(void);
26a7a5
 int initialize_zlib(z_stream *stream, int level);
26a7a5
 int finalize_zlib(z_stream *stream);
26a7a5
 
26a7a5
+int parse_line(char *str, char *argv[]);
26a7a5
+char *shift_string_left(char *s, int cnt);
26a7a5
+char *clean_line(char *line);
26a7a5
+char *strip_linefeeds(char *line);
26a7a5
+char *strip_beginning_whitespace(char *line);
26a7a5
+char *strip_ending_whitespace(char *line);
26a7a5
+ulong htol(char *s, int flags);
26a7a5
+int hexadecimal(char *s, int count);
26a7a5
+int decimal(char *s, int count);
26a7a5
+int file_exists(char *file);
26a7a5
+
26a7a5
 #endif /* MAKEDUMPFILE_H */
26a7a5
diff --git a/makedumpfile-1.6.2/tools.c b/makedumpfile-1.6.2/tools.c
26a7a5
new file mode 100644
26a7a5
index 000000000000..5814a775d42d
26a7a5
--- /dev/null
26a7a5
+++ b/makedumpfile-1.6.2/tools.c
26a7a5
@@ -0,0 +1,766 @@
26a7a5
+/* tools.c - Borrowed from crash utility code
26a7a5
+ *           (https://github.com/crash-utility/crash)
26a7a5
+ *
26a7a5
+ * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
26a7a5
+ * Copyright (C) 2002-2017 David Anderson
26a7a5
+ * Copyright (C) 2002-2018 Red Hat, Inc. All rights reserved.
26a7a5
+ *
26a7a5
+ * This program is free software; you can redistribute it and/or modify
26a7a5
+ * it under the terms of the GNU General Public License as published by
26a7a5
+ * the Free Software Foundation; either version 2 of the License, or
26a7a5
+ * (at your option) any later version.
26a7a5
+ *
26a7a5
+ * This program is distributed in the hope that it will be useful,
26a7a5
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26a7a5
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26a7a5
+ * GNU General Public License for more details.
26a7a5
+ */
26a7a5
+
26a7a5
+#include "common.h"
26a7a5
+#include "makedumpfile.h"
26a7a5
+#include <ctype.h>
26a7a5
+
26a7a5
+#define FAULT_ON_ERROR		(0x1)
26a7a5
+#define RETURN_ON_ERROR		(0x2)
26a7a5
+#define QUIET			(0x4)
26a7a5
+#define HEX_BIAS		(0x8)
26a7a5
+#define LONG_LONG		(0x10)
26a7a5
+#define RETURN_PARTIAL		(0x20)
26a7a5
+#define NO_DEVMEM_SWITCH	(0x40)
26a7a5
+
26a7a5
+#define MAX_HEXADDR_STRLEN	(16)
26a7a5
+
26a7a5
+#define FIRSTCHAR(s)		(s[0])
26a7a5
+
26a7a5
+/*
26a7a5
+ * Determine whether a file exists, using the caller's stat structure if
26a7a5
+ * one was passed in.
26a7a5
+ */
26a7a5
+int
26a7a5
+file_exists(char *file)
26a7a5
+{
26a7a5
+	struct stat sbuf;
26a7a5
+
26a7a5
+	if (stat(file, &sbuf) == 0)
26a7a5
+		return TRUE;
26a7a5
+
26a7a5
+	return FALSE;
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Parse a line into tokens, populate the passed-in argv[] array, and
26a7a5
+ * return the count of arguments found. This function modifies the
26a7a5
+ * passed-string by inserting a NULL character at the end of each token.
26a7a5
+ * Expressions encompassed by parentheses, and strings encompassed by
26a7a5
+ * apostrophes, are collected into single tokens.
26a7a5
+ */
26a7a5
+int
26a7a5
+parse_line(char *str, char *argv[])
26a7a5
+{
26a7a5
+	int i, j, k;
26a7a5
+	int string;
26a7a5
+	int expression;
26a7a5
+
26a7a5
+	for (i = 0; i < MAXARGS; i++)
26a7a5
+		argv[i] = NULL;
26a7a5
+
26a7a5
+	clean_line(str);
26a7a5
+
26a7a5
+	if (str == NULL || strlen(str) == 0)
26a7a5
+		return(0);
26a7a5
+
26a7a5
+	i = j = k = 0;
26a7a5
+	string = expression = FALSE;
26a7a5
+
26a7a5
+	/*
26a7a5
+	 * Special handling for when the first character is a '"'.
26a7a5
+	 */
26a7a5
+	if (str[0] == '"') {
26a7a5
+next:
26a7a5
+		do {
26a7a5
+			i++;
26a7a5
+		} while ((str[i] != NULLCHAR) && (str[i] != '"'));
26a7a5
+
26a7a5
+		switch (str[i])
26a7a5
+		{
26a7a5
+		case NULLCHAR:
26a7a5
+			argv[j] = &str[k];
26a7a5
+			return j+1;
26a7a5
+		case '"':
26a7a5
+			argv[j++] = &str[k+1];
26a7a5
+			str[i++] = NULLCHAR;
26a7a5
+			if (str[i] == '"') {
26a7a5
+				k = i;
26a7a5
+				goto next;
26a7a5
+			}
26a7a5
+			break;
26a7a5
+		}
26a7a5
+	} else
26a7a5
+		argv[j++] = str;
26a7a5
+
26a7a5
+	while (TRUE) {
26a7a5
+		if (j == MAXARGS)
26a7a5
+			ERRMSG("too many arguments in string!\n");
26a7a5
+
26a7a5
+		while (str[i] != ' ' && str[i] != '\t' && str[i] != NULLCHAR) {
26a7a5
+			i++;
26a7a5
+		}
26a7a5
+
26a7a5
+		switch (str[i])
26a7a5
+		{
26a7a5
+		case ' ':
26a7a5
+		case '\t':
26a7a5
+			str[i++] = NULLCHAR;
26a7a5
+
26a7a5
+			while (str[i] == ' ' || str[i] == '\t') {
26a7a5
+				i++;
26a7a5
+			}
26a7a5
+
26a7a5
+			if (str[i] == '"') {
26a7a5
+				str[i] = ' ';
26a7a5
+				string = TRUE;
26a7a5
+				i++;
26a7a5
+			}
26a7a5
+
26a7a5
+			if (!string && str[i] == '(') {
26a7a5
+				expression = TRUE;
26a7a5
+			}
26a7a5
+
26a7a5
+			if (str[i] != NULLCHAR && str[i] != '\n') {
26a7a5
+				argv[j++] = &str[i];
26a7a5
+				if (string) {
26a7a5
+					string = FALSE;
26a7a5
+					while (str[i] != '"' && str[i] != NULLCHAR)
26a7a5
+						i++;
26a7a5
+					if (str[i] == '"')
26a7a5
+						str[i] = ' ';
26a7a5
+				}
26a7a5
+				if (expression) {
26a7a5
+					expression = FALSE;
26a7a5
+					while (str[i] != ')' && str[i] != NULLCHAR)
26a7a5
+						i++;
26a7a5
+				}
26a7a5
+				break;
26a7a5
+			}
26a7a5
+			/* else fall through */
26a7a5
+		case '\n':
26a7a5
+			str[i] = NULLCHAR;
26a7a5
+			/* keep falling... */
26a7a5
+		case NULLCHAR:
26a7a5
+			argv[j] = NULLCHAR;
26a7a5
+			return(j);
26a7a5
+		}
26a7a5
+	}
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Defuse controversy re: extensions to ctype.h
26a7a5
+ */
26a7a5
+int
26a7a5
+whitespace(int c)
26a7a5
+{
26a7a5
+	return ((c == ' ') ||(c == '\t'));
26a7a5
+}
26a7a5
+
26a7a5
+int
26a7a5
+ascii(int c)
26a7a5
+{
26a7a5
+	return ((c >= 0) && (c <= 0x7f));
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Strip line-ending whitespace and linefeeds.
26a7a5
+ */
26a7a5
+char *
26a7a5
+strip_line_end(char *line)
26a7a5
+{
26a7a5
+	strip_linefeeds(line);
26a7a5
+	strip_ending_whitespace(line);
26a7a5
+	return(line);
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Strip line-beginning and line-ending whitespace and linefeeds.
26a7a5
+ */
26a7a5
+char *
26a7a5
+clean_line(char *line)
26a7a5
+{
26a7a5
+	strip_beginning_whitespace(line);
26a7a5
+	strip_linefeeds(line);
26a7a5
+	strip_ending_whitespace(line);
26a7a5
+	return(line);
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Strip line-ending linefeeds in a string.
26a7a5
+ */
26a7a5
+char *
26a7a5
+strip_linefeeds(char *line)
26a7a5
+{
26a7a5
+	char *p;
26a7a5
+
26a7a5
+	if (line == NULL || strlen(line) == 0)
26a7a5
+		return(line);
26a7a5
+
26a7a5
+	p = &LASTCHAR(line);
26a7a5
+
26a7a5
+	while (*p == '\n') {
26a7a5
+		*p = NULLCHAR;
26a7a5
+		if (--p < line)
26a7a5
+			break;
26a7a5
+	}
26a7a5
+
26a7a5
+	return(line);
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Strip a specified line-ending character in a string.
26a7a5
+ */
26a7a5
+char *
26a7a5
+strip_ending_char(char *line, char c)
26a7a5
+{
26a7a5
+	char *p;
26a7a5
+
26a7a5
+	if (line == NULL || strlen(line) == 0)
26a7a5
+		return(line);
26a7a5
+
26a7a5
+	p = &LASTCHAR(line);
26a7a5
+
26a7a5
+	if (*p == c)
26a7a5
+		*p = NULLCHAR;
26a7a5
+
26a7a5
+	return(line);
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Strip a specified line-beginning character in a string.
26a7a5
+ */
26a7a5
+char *
26a7a5
+strip_beginning_char(char *line, char c)
26a7a5
+{
26a7a5
+	if (line == NULL || strlen(line) == 0)
26a7a5
+		return(line);
26a7a5
+
26a7a5
+	if (FIRSTCHAR(line) == c)
26a7a5
+		shift_string_left(line, 1);
26a7a5
+
26a7a5
+	return(line);
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Strip line-ending whitespace.
26a7a5
+ */
26a7a5
+char *
26a7a5
+strip_ending_whitespace(char *line)
26a7a5
+{
26a7a5
+	char *p;
26a7a5
+
26a7a5
+	if (line == NULL || strlen(line) == 0)
26a7a5
+		return(line);
26a7a5
+
26a7a5
+	p = &LASTCHAR(line);
26a7a5
+
26a7a5
+	while (*p == ' ' || *p == '\t') {
26a7a5
+		*p = NULLCHAR;
26a7a5
+		if (p == line)
26a7a5
+			break;
26a7a5
+		p--;
26a7a5
+	}
26a7a5
+
26a7a5
+	return(line);
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Strip line-beginning whitespace.
26a7a5
+ */
26a7a5
+char *
26a7a5
+strip_beginning_whitespace(char *line)
26a7a5
+{
26a7a5
+	char buf[BUFSIZE];
26a7a5
+	char *p;
26a7a5
+
26a7a5
+	if (line == NULL || strlen(line) == 0)
26a7a5
+		return(line);
26a7a5
+
26a7a5
+	strcpy(buf, line);
26a7a5
+	p = &buf[0];
26a7a5
+	while (*p == ' ' || *p == '\t')
26a7a5
+		p++;
26a7a5
+	strcpy(line, p);
26a7a5
+
26a7a5
+	return(line);
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * End line at first comma found.
26a7a5
+ */
26a7a5
+char *
26a7a5
+strip_comma(char *line)
26a7a5
+{
26a7a5
+	char *p;
26a7a5
+
26a7a5
+	if ((p = strstr(line, ",")))
26a7a5
+		*p = NULLCHAR;
26a7a5
+
26a7a5
+	return(line);
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Strip the 0x from the beginning of a hexadecimal value string.
26a7a5
+ */
26a7a5
+char *
26a7a5
+strip_hex(char *line)
26a7a5
+{
26a7a5
+	if (STRNEQ(line, "0x"))
26a7a5
+		shift_string_left(line, 2);
26a7a5
+
26a7a5
+	return(line);
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Turn a string into upper-case.
26a7a5
+ */
26a7a5
+char *
26a7a5
+upper_case(const char *s, char *buf)
26a7a5
+{
26a7a5
+	const char *p1;
26a7a5
+	char *p2;
26a7a5
+
26a7a5
+	p1 = s;
26a7a5
+	p2 = buf;
26a7a5
+
26a7a5
+	while (*p1) {
26a7a5
+		*p2 = toupper(*p1);
26a7a5
+		p1++, p2++;
26a7a5
+	}
26a7a5
+
26a7a5
+	*p2 = NULLCHAR;
26a7a5
+
26a7a5
+	return(buf);
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Return pointer to first non-space/tab in a string.
26a7a5
+ */
26a7a5
+char *
26a7a5
+first_nonspace(char *s)
26a7a5
+{
26a7a5
+	return(s + strspn(s, " \t"));
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Return pointer to first space/tab in a string. If none are found,
26a7a5
+ * return a pointer to the string terminating NULL.
26a7a5
+ */
26a7a5
+char *
26a7a5
+first_space(char *s)
26a7a5
+{
26a7a5
+	return(s + strcspn(s, " \t"));
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Replace the first space/tab found in a string with a NULL character.
26a7a5
+ */
26a7a5
+char *
26a7a5
+null_first_space(char *s)
26a7a5
+{
26a7a5
+	char *p1;
26a7a5
+
26a7a5
+	p1 = first_space(s);
26a7a5
+	if (*p1)
26a7a5
+		*p1 = NULLCHAR;
26a7a5
+
26a7a5
+	return s;
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Replace any instances of the characters in string c that are found in
26a7a5
+ * string s with the character passed in r.
26a7a5
+ */
26a7a5
+char *
26a7a5
+replace_string(char *s, char *c, char r)
26a7a5
+{
26a7a5
+	int i, j;
26a7a5
+
26a7a5
+	for (i = 0; s[i]; i++) {
26a7a5
+		for (j = 0; c[j]; j++) {
26a7a5
+			if (s[i] == c[j])
26a7a5
+				s[i] = r;
26a7a5
+		}
26a7a5
+	}
26a7a5
+
26a7a5
+	return s;
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Find the rightmost instance of a substring in a string.
26a7a5
+ */
26a7a5
+char *
26a7a5
+strstr_rightmost(char *s, char *lookfor)
26a7a5
+{
26a7a5
+	char *next, *last, *p;
26a7a5
+
26a7a5
+	for (p = s, last = NULL; *p; p++) {
26a7a5
+		if (!(next = strstr(p, lookfor)))
26a7a5
+			break;
26a7a5
+		last = p = next;
26a7a5
+	}
26a7a5
+
26a7a5
+	return last;
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Shifts the contents of a string to the left by cnt characters,
26a7a5
+ * disposing the leftmost characters.
26a7a5
+ */
26a7a5
+char *
26a7a5
+shift_string_left(char *s, int cnt)
26a7a5
+{
26a7a5
+	int origlen;
26a7a5
+
26a7a5
+	if (!cnt)
26a7a5
+		return(s);
26a7a5
+
26a7a5
+	origlen = strlen(s);
26a7a5
+	memmove(s, s+cnt, (origlen-cnt));
26a7a5
+	*(s+(origlen-cnt)) = NULLCHAR;
26a7a5
+	return(s);
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Prints a string verbatim, allowing strings with % signs to be displayed
26a7a5
+ * without printf conversions.
26a7a5
+ */
26a7a5
+void
26a7a5
+print_verbatim(FILE *filep, char *line)
26a7a5
+{
26a7a5
+	int i;
26a7a5
+
26a7a5
+	for (i = 0; i < strlen(line); i++) {
26a7a5
+		fputc(line[i], filep);
26a7a5
+		fflush(filep);
26a7a5
+	}
26a7a5
+}
26a7a5
+
26a7a5
+char *
26a7a5
+fixup_percent(char *s)
26a7a5
+{
26a7a5
+	char *p1;
26a7a5
+
26a7a5
+	if ((p1 = strstr(s, "%")) == NULL)
26a7a5
+		return s;
26a7a5
+
26a7a5
+	s[strlen(s)+1] = NULLCHAR;
26a7a5
+	memmove(p1+1, p1, strlen(p1));
26a7a5
+	*p1 = '%';
26a7a5
+
26a7a5
+	return s;
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Append a two-character string to a number to make 1, 2, 3 and 4 into
26a7a5
+ * 1st, 2nd, 3rd, 4th, and so on...
26a7a5
+ */
26a7a5
+char *
26a7a5
+ordinal(ulong val, char *buf)
26a7a5
+{
26a7a5
+	char *p1;
26a7a5
+
26a7a5
+	sprintf(buf, "%ld", val);
26a7a5
+	p1 = &buf[strlen(buf)-1];
26a7a5
+
26a7a5
+	switch (*p1)
26a7a5
+	{
26a7a5
+	case '1':
26a7a5
+		strcat(buf, "st");
26a7a5
+		break;
26a7a5
+	case '2':
26a7a5
+		strcat(buf, "nd");
26a7a5
+		break;
26a7a5
+	case '3':
26a7a5
+		strcat(buf, "rd");
26a7a5
+		break;
26a7a5
+	default:
26a7a5
+		strcat(buf, "th");
26a7a5
+		break;
26a7a5
+	}
26a7a5
+
26a7a5
+	return buf;
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Determine whether a string contains only decimal characters.
26a7a5
+ * If count is non-zero, limit the search to count characters.
26a7a5
+ */
26a7a5
+int
26a7a5
+decimal(char *s, int count)
26a7a5
+{
26a7a5
+	char *p;
26a7a5
+	int cnt, digits;
26a7a5
+
26a7a5
+	if (!count) {
26a7a5
+		strip_line_end(s);
26a7a5
+		cnt = 0;
26a7a5
+	} else
26a7a5
+		cnt = count;
26a7a5
+
26a7a5
+	for (p = &s[0], digits = 0; *p; p++) {
26a7a5
+		switch(*p)
26a7a5
+		{
26a7a5
+		case '0':
26a7a5
+		case '1':
26a7a5
+		case '2':
26a7a5
+		case '3':
26a7a5
+		case '4':
26a7a5
+		case '5':
26a7a5
+		case '6':
26a7a5
+		case '7':
26a7a5
+		case '8':
26a7a5
+		case '9':
26a7a5
+			digits++;
26a7a5
+		case ' ':
26a7a5
+			break;
26a7a5
+		default:
26a7a5
+			return FALSE;
26a7a5
+		}
26a7a5
+
26a7a5
+		if (count && (--cnt == 0))
26a7a5
+			break;
26a7a5
+	}
26a7a5
+
26a7a5
+	return (digits ? TRUE : FALSE);
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Determine whether a string contains only ASCII characters.
26a7a5
+ */
26a7a5
+int
26a7a5
+ascii_string(char *s)
26a7a5
+{
26a7a5
+	char *p;
26a7a5
+
26a7a5
+	for (p = &s[0]; *p; p++) {
26a7a5
+		if (!ascii(*p))
26a7a5
+			return FALSE;
26a7a5
+	}
26a7a5
+
26a7a5
+	return TRUE;
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Check whether a string contains only printable ASCII characters.
26a7a5
+ */
26a7a5
+int
26a7a5
+printable_string(char *s)
26a7a5
+{
26a7a5
+	char *p;
26a7a5
+
26a7a5
+	for (p = &s[0]; *p; p++) {
26a7a5
+		if (!isprint(*p))
26a7a5
+			return FALSE;
26a7a5
+	}
26a7a5
+
26a7a5
+	return TRUE;
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Convert a string to a hexadecimal long value.
26a7a5
+ */
26a7a5
+ulong
26a7a5
+htol(char *s, int flags)
26a7a5
+{
26a7a5
+	ulong i, j;
26a7a5
+	ulong n;
26a7a5
+
26a7a5
+	if (s == NULL) {
26a7a5
+		if (!(flags & QUIET))
26a7a5
+			ERRMSG("received NULL string\n");
26a7a5
+		goto htol_error;
26a7a5
+	}
26a7a5
+
26a7a5
+	if (STRNEQ(s, "0x") || STRNEQ(s, "0X"))
26a7a5
+		s += 2;
26a7a5
+
26a7a5
+	if (strlen(s) > MAX_HEXADDR_STRLEN) {
26a7a5
+		if (!(flags & QUIET))
26a7a5
+			ERRMSG("input string too large: \"%s\" (%d vs %d)\n",
26a7a5
+					s, (int)strlen(s), (int)MAX_HEXADDR_STRLEN);
26a7a5
+		goto htol_error;
26a7a5
+	}
26a7a5
+
26a7a5
+	for (n = i = 0; s[i] != 0; i++) {
26a7a5
+		switch (s[i])
26a7a5
+		{
26a7a5
+		case 'a':
26a7a5
+		case 'b':
26a7a5
+		case 'c':
26a7a5
+		case 'd':
26a7a5
+		case 'e':
26a7a5
+		case 'f':
26a7a5
+			j = (s[i] - 'a') + 10;
26a7a5
+			break;
26a7a5
+		case 'A':
26a7a5
+		case 'B':
26a7a5
+		case 'C':
26a7a5
+		case 'D':
26a7a5
+		case 'E':
26a7a5
+		case 'F':
26a7a5
+			j = (s[i] - 'A') + 10;
26a7a5
+			break;
26a7a5
+		case '1':
26a7a5
+		case '2':
26a7a5
+		case '3':
26a7a5
+		case '4':
26a7a5
+		case '5':
26a7a5
+		case '6':
26a7a5
+		case '7':
26a7a5
+		case '8':
26a7a5
+		case '9':
26a7a5
+		case '0':
26a7a5
+			j = s[i] - '0';
26a7a5
+			break;
26a7a5
+		case 'x':
26a7a5
+		case 'X':
26a7a5
+		case 'h':
26a7a5
+			continue;
26a7a5
+		default:
26a7a5
+			if (!(flags & QUIET))
26a7a5
+				ERRMSG("invalid input: \"%s\"\n", s);
26a7a5
+			goto htol_error;
26a7a5
+		}
26a7a5
+		n = (16 * n) + j;
26a7a5
+	}
26a7a5
+
26a7a5
+	return(n);
26a7a5
+
26a7a5
+htol_error:
26a7a5
+	return BADADDR;
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Determine whether a string contains only hexadecimal characters.
26a7a5
+ * If count is non-zero, limit the search to count characters.
26a7a5
+ */
26a7a5
+int
26a7a5
+hexadecimal(char *s, int count)
26a7a5
+{
26a7a5
+	char *p;
26a7a5
+	int cnt, digits;
26a7a5
+
26a7a5
+	if (!count) {
26a7a5
+		strip_line_end(s);
26a7a5
+		cnt = 0;
26a7a5
+	} else
26a7a5
+		cnt = count;
26a7a5
+
26a7a5
+	for (p = &s[0], digits = 0; *p; p++) {
26a7a5
+		switch(*p)
26a7a5
+		{
26a7a5
+		case 'a':
26a7a5
+		case 'b':
26a7a5
+		case 'c':
26a7a5
+		case 'd':
26a7a5
+		case 'e':
26a7a5
+		case 'f':
26a7a5
+		case 'A':
26a7a5
+		case 'B':
26a7a5
+		case 'C':
26a7a5
+		case 'D':
26a7a5
+		case 'E':
26a7a5
+		case 'F':
26a7a5
+		case '1':
26a7a5
+		case '2':
26a7a5
+		case '3':
26a7a5
+		case '4':
26a7a5
+		case '5':
26a7a5
+		case '6':
26a7a5
+		case '7':
26a7a5
+		case '8':
26a7a5
+		case '9':
26a7a5
+		case '0':
26a7a5
+			digits++;
26a7a5
+		case 'x':
26a7a5
+		case 'X':
26a7a5
+			break;
26a7a5
+
26a7a5
+		case ' ':
26a7a5
+			if (*(p+1) == NULLCHAR)
26a7a5
+				break;
26a7a5
+			else
26a7a5
+				return FALSE;
26a7a5
+		default:
26a7a5
+			return FALSE;
26a7a5
+		}
26a7a5
+
26a7a5
+		if (count && (--cnt == 0))
26a7a5
+			break;
26a7a5
+	}
26a7a5
+
26a7a5
+	return (digits ? TRUE : FALSE);
26a7a5
+}
26a7a5
+
26a7a5
+/*
26a7a5
+ * Determine whether a string contains only hexadecimal characters.
26a7a5
+ * and cannot be construed as a decimal number.
26a7a5
+ * If count is non-zero, limit the search to count characters.
26a7a5
+ */
26a7a5
+int
26a7a5
+hexadecimal_only(char *s, int count)
26a7a5
+{
26a7a5
+	char *p;
26a7a5
+	int cnt, only;
26a7a5
+
26a7a5
+	if (!count) {
26a7a5
+		strip_line_end(s);
26a7a5
+		cnt = 0;
26a7a5
+	} else
26a7a5
+		cnt = count;
26a7a5
+
26a7a5
+	only = 0;
26a7a5
+
26a7a5
+	for (p = &s[0]; *p; p++) {
26a7a5
+		switch(*p)
26a7a5
+		{
26a7a5
+		case 'a':
26a7a5
+		case 'b':
26a7a5
+		case 'c':
26a7a5
+		case 'd':
26a7a5
+		case 'e':
26a7a5
+		case 'f':
26a7a5
+		case 'A':
26a7a5
+		case 'B':
26a7a5
+		case 'C':
26a7a5
+		case 'D':
26a7a5
+		case 'E':
26a7a5
+		case 'F':
26a7a5
+		case 'x':
26a7a5
+		case 'X':
26a7a5
+			only++;
26a7a5
+			break;
26a7a5
+		case '1':
26a7a5
+		case '2':
26a7a5
+		case '3':
26a7a5
+		case '4':
26a7a5
+		case '5':
26a7a5
+		case '6':
26a7a5
+		case '7':
26a7a5
+		case '8':
26a7a5
+		case '9':
26a7a5
+		case '0':
26a7a5
+			break;
26a7a5
+
26a7a5
+		case ' ':
26a7a5
+			if (*(p+1) == NULLCHAR)
26a7a5
+				break;
26a7a5
+			else
26a7a5
+				return FALSE;
26a7a5
+		default:
26a7a5
+			return FALSE;
26a7a5
+		}
26a7a5
+
26a7a5
+		if (count && (--cnt == 0))
26a7a5
+			break;
26a7a5
+	}
26a7a5
+
26a7a5
+	return only;
26a7a5
+}
26a7a5
-- 
26a7a5
2.7.4
26a7a5