aboutsummaryrefslogtreecommitdiff
path: root/newlib/libc/stdlib/a64l.c
diff options
context:
space:
mode:
authorJeff Johnston <jjohnstn@redhat.com>2002-05-06 20:44:54 +0000
committerJeff Johnston <jjohnstn@redhat.com>2002-05-06 20:44:54 +0000
commitc33c3635f7a20a40af570342d9a7609d4a22c39e (patch)
treed1ed761cf5ae28675e0529e0cc14f7e072848376 /newlib/libc/stdlib/a64l.c
parentf78e59a8f90f72609c153d4db493c2d43e6ca379 (diff)
downloadnewlib-c33c3635f7a20a40af570342d9a7609d4a22c39e.zip
newlib-c33c3635f7a20a40af570342d9a7609d4a22c39e.tar.gz
newlib-c33c3635f7a20a40af570342d9a7609d4a22c39e.tar.bz2
2002-05-06 Jeff Johnston <jjohnstn@redhat.com>
* libc/include/sys/reent.h (_l64a_buf): New reentrant area. (_REENT_L64A_BUF): New macro for accessing area. * libc/stdlib/Makefile.am: Add a64l.c and l64a.c. * libc/stdlib/Makefile.in: Regenerated. * libc/stdlib/a64l.c: New file. * libc/stdlib/l64a.c: New file.
Diffstat (limited to 'newlib/libc/stdlib/a64l.c')
-rw-r--r--newlib/libc/stdlib/a64l.c192
1 files changed, 192 insertions, 0 deletions
diff --git a/newlib/libc/stdlib/a64l.c b/newlib/libc/stdlib/a64l.c
new file mode 100644
index 0000000..9a56a91
--- /dev/null
+++ b/newlib/libc/stdlib/a64l.c
@@ -0,0 +1,192 @@
+/*
+FUNCTION
+<<a64l>>,<<l64a>>---convert between radix-64 ascii string and long
+
+INDEX
+ a64l
+INDEX
+ l64a
+
+ANSI_SYNOPSIS
+ #include <stdlib.h>
+ long a64l(const char *<[input]>);
+ char *l64a(long <[input]>);
+
+TRAD_SYNOPSIS
+ #include <stdlib.h>
+ long a64l(<[input]>)
+ const char *<[input]>;
+
+ char *l64a(<[input]>)
+ long <[input]>;
+
+DESCRIPTION
+Conversion is performed between long and radix-64 characters. The <<l64a>> routine
+transforms up to 32-bits of input value starting from least significant bits to
+the most significant bits. The input value is split up into a maximum of 5
+groups of 6-bits and possibly one group of 2 bits (bits 31 and 30).
+
+Each group of 6 bits forms a value from 0-63 which is translated into a character
+as follows:
+
+ 0 = '.'
+ 1 = '/'
+ 2-11 = '0' to '9'
+ 12-37 = 'A' to 'Z'
+ 38-63 = 'a' to 'z'
+
+When remaining bits are zero or all bits have been translated, a nul terminator
+is appended to the string. An input value of 0 results in the empty string.
+
+The <<a64l>> performs the reverse translation. Each character is used to generate
+a 6-bit value for up to 30 bits and then a 2-bit value to complete a 32-bit result.
+The nul terminator means that the remaining digits are 0. An empty input string or
+NULL string results in 0L. An invalid string results in undefined behavior.
+If the size of a long is > 32 bits, the result is sign-extended.
+
+RETURNS
+<<l64a>> returns a nul-terminated string of 0 to 6 characters.
+<<a64l>> returns the 32-bit translated value from the input character string.
+
+PORTABILITY
+<<l64a>> and <<a64l>> are non-ANSI and are defined by the Single Unix Specification.
+
+Supporting OS subroutines required: None.
+*/
+
+#include <_ansi.h>
+#include <stdlib.h>
+#include <limits.h>
+
+long
+_DEFUN (a64l, (input),
+ const char *input)
+{
+ char *ptr;
+ char ch;
+ int i, digit;
+ unsigned long result = 0;
+
+ if (input == NULL)
+ return 0;
+
+ ptr = input;
+
+ /* it easiest to go from most significant digit to least so find end of input or up
+ to 6 characters worth */
+ for (i = 0; i < 6; ++i)
+ {
+ if (*ptr)
+ ++ptr;
+ }
+
+ while (ptr > input)
+ {
+ ch = *(--ptr);
+
+#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
+ if (ch >= 'a')
+ digit = (ch - 'a') + 38;
+ else if (ch >= 'A')
+ digit = (ch - 'A') + 12;
+ else if (ch >= '0')
+ digit = (ch - '0') + 2;
+ else if (ch == '/')
+ digit = 1;
+ else
+ digit = 0;
+#else /* !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) */
+ switch (ch)
+ {
+ case '/':
+ digit = 1;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ digit = (ch - '0') + 2;
+ break;
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ digit = (ch - 'A') + 12;
+ break;
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z':
+ digit = (ch - 'A') + 38;
+ break;
+ default:
+ digit = 0;
+ break;
+ }
+#endif /* !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) */
+
+ result = (result << 6) + digit;
+ }
+
+#if LONG_MAX > 2147483647
+ /* for implementations where long is > 32 bits, the result must be sign-extended */
+ if (result & 0x80000000)
+ return (((long)-1 >> 32) << 32) + result;
+#endif
+
+ return result;
+}
+
+
+
+