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