summaryrefslogtreecommitdiffstats
path: root/cpukit/libmisc/stringto/stringto_template.h
blob: 6bc61c9c040e4b08e441cc1c003d1282eddf0d11 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
 *  COPYRIGHT (c) 2009.
 *  On-Line Applications Research Corporation (OAR).
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *  http://www.rtems.com/license/LICENSE.
 *
 *  $Id$
 */

#include <errno.h>
#include <stdlib.h>
#include <limits.h>
#include <stdbool.h>

#include <rtems/stringto.h>

/*
 *  If we are doing floating point conversion, then we need math.h
 */
#if defined(STRING_TO_FLOAT)
  #include <math.h>
#endif

#include <rtems.h>

/*
 * This file is designed to be included multiple times to instantiate
 * it and should NOT be protected against multiple inclusions.
 */

#if defined(STRING_TO_POINTER)
  #define STRING_TO_INTEGER
#endif

#if !defined(STRING_TO_FLOAT) && !defined(STRING_TO_INTEGER)
  #error "Neither STRING_TO_FLOAT nor STRING_TO_INTEGER defined"
#endif

#if defined(STRING_TO_FLOAT) && defined(STRING_TO_INTEGER)
  #error "Both STRING_TO_FLOAT nor STRING_TO_INTEGER defined"
#endif

#ifndef STRING_TO_TYPE
  #error "STRING_TO_TYPE not defined"
#endif

#ifndef STRING_TO_NAME
  #error "STRING_TO_NAME not defined"
#endif

#ifndef STRING_TO_METHOD
  #error "STRING_TO_METHOD not defined"
#endif

#ifndef STRING_TO_MAX
  #error "STRING_TO_MAX not defined"
#endif

#undef ZERO
#ifdef STRING_TO_FLOAT
  #define ZERO 0.0
#elif defined(STRING_TO_INTEGER)
  #define ZERO 0
#endif

#if !defined(STRING_TO_INPUT_TYPE)
  #define STRING_TO_INPUT_TYPE STRING_TO_TYPE
#endif

rtems_status_code STRING_TO_NAME (
  const char      *s,
  STRING_TO_TYPE  *n,
  char           **endptr
  #if defined(STRING_TO_INTEGER) && !defined(STRING_TO_POINTER)
    ,
    int              base
  #endif
)
{
  STRING_TO_INPUT_TYPE  result;
  char                 *end;

  if ( !n )
    return RTEMS_INVALID_ADDRESS;

  errno = 0;
  *n    = 0;

  #ifdef STRING_TO_FLOAT
    result = STRING_TO_METHOD( s, &end );
  #elif defined(STRING_TO_POINTER)
    result = STRING_TO_METHOD( s, &end, 16 );
  #elif defined(STRING_TO_INTEGER)
    result = STRING_TO_METHOD( s, &end, base );
  #endif

  /* If the user wants the end pointer back, then return it. */
  if ( endptr )
    *endptr = end;

  /* nothing was converted */
  if ( end == s )
    return RTEMS_NOT_DEFINED;

  /*
   * In theory, we should check this but newlib never returns anything
   * but range errors.  So this is unreachable code based upon the newlib
   * implementation of strXXX methods as of 1 December 2009. --joel
   */
  #if 0
  /* there was a conversion error */
  if ( (result == ZERO) && errno )
    return RTEMS_INVALID_NUMBER;
  #endif

  #ifdef STRING_TO_MAX
    /* there was an overflow */
    if ( (result == STRING_TO_MAX) && (errno == ERANGE))
      return RTEMS_INVALID_NUMBER;
  #endif

  #ifdef STRING_TO_MIN
    /* there was an underflow */
    if ( (result == STRING_TO_MIN) && (errno == ERANGE))
      return RTEMS_INVALID_NUMBER;
  #endif

  #if defined(STRING_TO_POINTER)
    *n = (STRING_TO_TYPE) (uintptr_t)result;
  #else
    *n = (STRING_TO_TYPE) result;
  #endif
  return RTEMS_SUCCESSFUL;
}