[PATCH v2 1/3] Add a new helper file 'tools.c' that provides some useful APIs

Bhupesh Sharma bhsharma at redhat.com
Tue Mar 6 02:17:15 PST 2018


Hello Masaki,

On Tue, Mar 6, 2018 at 3:33 PM, Masaki Tachibana
<mas-tachibana at vf.jp.nec.com> wrote:
> Hi bhupesh,
>
> Thank you for your V2 patchset.
>
> When you have introduced tools.c from crash utility,
> you have deleted a part of htol()'s error handling
> that is unnecessary for makedumpfile as follows;
>
> htol_error:
> -       switch (flags & (FAULT_ON_ERROR|RETURN_ON_ERROR))
> -       {
> -       case FAULT_ON_ERROR:
> -               RESTART();
> -
> -       case RETURN_ON_ERROR:
> -               if (errptr)
> -                       *errptr = TRUE;
> -               break;
> -       }
> -
>         return BADADDR;
> }
>
> As a result of this, htol() does not refer to 3rd parameter 'errptr'
> and RETURN_ON_ERROR.
> I understand that some codes are not used on makedumpfile's tools.c.
> They may be used in the future.

Indeed the 3rd parameter in 'htol()' is not currently needed by
makedumpfile code, but like you mentioned I earlier thought it might
be required for future compatibility some some future feature
addition.

> However I think 'errptr' should be deleted, so I have tried modifying
> your patches as follows;
> $ diff "PATCH v2 13 Add a new helper file 'tools
> .c' that provides some useful APIs.patch.old" "PATCH v2 13 Add a new helper file
>  'tools.c' that provides some useful APIs.patch"
> 100c100
> < +ulong htol(char *s, int flags, int *errptr);
> ---
>> +ulong htol(char *s, int flags);
> 681c681
> < +htol(char *s, int flags, int *errptr)
> ---
>> +htol(char *s, int flags)
>
> $ diff "PATCH v2 23 arm64 Add support to read sy
> mbols like _stext from 'prockallsyms'.patch.old" "PATCH v2 23 arm64 Add support
> to read symbols like _stext from 'prockallsyms'.patch"
> 62c62
> < @@ -177,6 +181,45 @@ get_phys_base_arm64(void)
> ---
>> @@ -177,6 +181,44 @@ get_phys_base_arm64(void)
> 94,95c94
> < +                     kallsym = htol(kallsyms[0], RETURN_ON_ERROR,
> < +                                     NULL);
> ---
>> +                     kallsym = htol(kallsyms[0], 0);
>
> How about this ?
> If you agree, I'll merge the modified patchset into V1.6.4.

Yes. This seems fine to me. We can add the 3rd parameter to 'htol'
later if its needed in future.

Please feel free to merge the modified patchset into V1.6.4

Regards,
Bhupesh

>
>> -----Original Message-----
>> From: kexec [mailto:kexec-bounces at lists.infradead.org] On Behalf Of Bhupesh Sharma
>> Sent: Tuesday, March 06, 2018 2:13 AM
>> To: kexec at lists.infradead.org
>> Cc: bhsharma at redhat.com; bhupesh.linux at gmail.com
>> Subject: [PATCH v2 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 at 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/Makefile b/Makefile
>> index f4b7c56b6f3d..e870b1362c95 100644
>> --- a/Makefile
>> +++ b/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/common.h b/common.h
>> index 6ad3ca7b952c..6e2f657a79c7 100644
>> --- a/common.h
>> +++ b/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.h b/makedumpfile.h
>> index 01eece231475..0ce75e29fa7f 100644
>> --- a/makedumpfile.h
>> +++ b/makedumpfile.h
>> @@ -237,6 +237,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))
>> @@ -2319,4 +2322,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 *errptr);
>> +int hexadecimal(char *s, int count);
>> +int decimal(char *s, int count);
>> +int file_exists(char *file);
>> +
>>  #endif /* MAKEDUMPFILE_H */
>> diff --git a/tools.c b/tools.c
>> new file mode 100644
>> index 000000000000..746ffa104816
>> --- /dev/null
>> +++ b/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, int *errptr)
>> +{
>> +     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
>>
>>
>> _______________________________________________
>> kexec mailing list
>> kexec at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/kexec
>
>



More information about the kexec mailing list