Manually reading an integer literal
So far this is the test file I have (no other code needed to compile with cc (I presume my system is redirecting to gcc there), aside from obvious lack of backward compatibility with C89 and some left over stuff from when I started by testing on a hardcoded string does anyone see any particular issues in this or even think it's missing something or other? BTW I plan on implementing the LL stuff next, thinking of just croping it with a cast after the value is filled in for the sizing but for the unsigned part I will probably make a seperate similar function to mimic the behavior of pre-processors in that they treat it as signed unless explicitly given notice to treat as unsigned
Code:
#include <errno.h>
#include <ctype.h>
#include <inttypes.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
typedef signed char schar;
typedef unsigned char uchar;
typedef int (*int_c_void_t)();
typedef int (*int_c_pvoid_t)( void *src );
#define BASE_NUM "0123456789"
#define BASE_a2z "abcdefghijklmnopqrstuvqxyz"
#define BASE_A2Z "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
char upper_base62_text[] = BASE_NUM BASE_A2Z BASE_a2z;
char lower_base62_text[] = BASE_NUM BASE_a2z BASE_A2Z;
int rdU64_base62( int_c_pvoid_t getchr, void *source, int c,
uint base, _Bool lowercase1st, uint_least64_t *num ) {
uint i = 0;
uint_least64_t n = 0;
int rdU64_high() {
char *base_text =
lowercase1st ? lower_base62_text : upper_base62_text;
for ( i = 0; i < base && c != base_text[i]; ++i );
i = (i < base) ? i : 0;
while ( i < base && (c = getchr(source)) ) {
n *= base;
n += i;
for ( i = 0; i < base && c != base_text[i]; ++i );
}
if ( num ) *num = n + ((i < base) ? i : 0);
return c;
}
int rdU64_both() {
for ( i = 0; i < base &&
c != upper_base62_text[i] &&
c != lower_base62_text[i]; ++i );
i = (i < base) ? i : 0;
while ( i < base && (c = getchr(source)) ) {
n *= base;
n += i;
for ( i = 0; i < base &&
c != upper_base62_text[i] &&
c != lower_base62_text[i]; ++i );
}
if ( num ) *num = n + ((i < base) ? i : 0);
return c;
}
return (base < 2) ? -1 :
((base < 37) ? rdU64_both() : ((base < 63) ? rdU64_high() : -1));
}
int rdNum( int_c_pvoid_t getchr, void *source, int c, uint_least64_t *num ) {
int rdUint() {
c = getchr(source);
return (c == 'x' || c == 'X') ?
rdU64_base62( getchr, source, getchr(source), 16, 0, num ) :
((c == 'b' || c == 'B') ?
rdU64_base62( getchr, source, getchr(source), 2, 0, num ) :
rdU64_base62( getchr, source, c, 8, 0, num ));
}
int rdVal() {
return (c == '0') ? rdUint() :
rdU64_base62( getchr, source, c, 10, 0, num );
}
int rdInt() {
int p = c;
c = getchr(source);
c = rdVal();
if ( num ) *num = ( p == '-' ) ? -(*num) : *num;
return c;
}
return (c == '-' || c == '+') ? rdInt() : rdVal();
}
typedef struct str {
size_t pos;
size_t cap;
size_t len;
char * txt;
} str_t;
int rdstr( str_t *str ) {
return (str->pos < str->len) ? str->txt[str->pos++] : 0;
}
int main() {
uint_least64_t val123 = 0;
uint i = 0;
for ( ; i < 5; ++i ) {
(void)puts("Please enter a number");
rdNum(
(int_c_pvoid_t)getc, (void*)stdin, getc(stdin), &val123 );
(void)printf("Number entered: %" PRIuLEAST64 "\n", val123);
}
return 0;
}
The results of my last test:
Code:
lee@lee-pc-linux:/media/lee/ZXUIJI_1TB/github/mc$ make expr
cc -D OUT=main.elf -o expr.elf expr.c
./expr.elf
Please enter a number
+500
Number entered: 500
Please enter a number
600
Number entered: 600
Please enter a number
0456
Number entered: 302
Please enter a number
0x456
Number entered: 1110
Please enter a number
0b100
Number entered: 4
rm expr.elf
lee@lee-pc-linux:/media/lee/ZXUIJI_1TB/github/mc$