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

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