scanf register new conversion specifier - c

I wrote this week an extension for the printf family of functions to accept %b to print binary. For that, I used the function register_printf_specifier().
Now I wonder if I can do the same in the scanf family of functions to accept a binary input and write it into a variable.
Is there any extension that allows me to do that?

TL;DR: No. At least no when using glibc.
I've downloaded recent glibc version:
% wget https://ftp.gnu.org/gnu/glibc/glibc-2.29.tar.gz
% tar -xzf glibc-2.29.tar.gz
And grep'ed find, searching for random scanf family function that came to my mind - in this case, it was vfscanf:
% find | grep "vfscanf"
From my experience I know that real implementations are somewhere in -internal, yet I looked through output:
./stdio-common/iovfscanf.c
./stdio-common/isoc99_vfscanf.c
./stdio-common/vfscanf-internal.c
./stdio-common/vfscanf.c
./sysdeps/ieee754/ldbl-opt/nldbl-iovfscanf.c
./sysdeps/ieee754/ldbl-opt/nldbl-isoc99_vfscanf.c
./sysdeps/ieee754/ldbl-opt/nldbl-vfscanf.c
And decided to check ./stdio-common/vfscanf.c, that in fact contained stub to the internal function:
% cat ./stdio-common/vfscanf.c
int
___vfscanf (FILE *s, const char *format, va_list argptr)
{
return __vfscanf_internal (s, format, argptr, 0);
}
Going forward, I've looked thru the file, and reached format parser:
% cat ./stdio-common/vfscanf-internal.c | head -n 1390 | tail -n 20
}
break;
case L_('x'): /* Hexadecimal integer. */
case L_('X'): /* Ditto. */
base = 16;
goto number;
case L_('o'): /* Octal integer. */
base = 8;
goto number;
case L_('u'): /* Unsigned decimal integer. */
base = 10;
goto number;
case L_('d'): /* Signed decimal integer. */
base = 10;
flags |= NUMBER_SIGNED;
goto number;
I've looked at the end of file, and found some finishing case label:
% cat ./stdio-common/vfscanf-internal.c | tail -n 60
++done;
}
}
break;
case L_('p'): /* Generic pointer. */
base = 16;
/* A PTR must be the same size as a `long int'. */
flags &= ~(SHORT|LONGDBL);
if (need_long)
flags |= LONG;
flags |= READ_POINTER;
goto number;
default:
/* If this is an unknown format character punt. */
conv_error ();
}
}
/* The last thing we saw int the format string was a white space.
Consume the last white spaces. */
if (skip_space)
{
do
c = inchar ();
while (ISSPACE (c));
ungetc (c, s);
}
errout:
/* Unlock stream. */
UNLOCK_STREAM (s);
scratch_buffer_free (&charbuf.scratch);
if (__glibc_unlikely (done == EOF))
{
if (__glibc_unlikely (ptrs_to_free != NULL))
{
struct ptrs_to_free *p = ptrs_to_free;
while (p != NULL)
{
for (size_t cnt = 0; cnt < p->count; ++cnt)
{
free (*p->ptrs[cnt]);
*p->ptrs[cnt] = NULL;
}
p = p->next;
ptrs_to_free = p;
}
}
}
else if (__glibc_unlikely (strptr != NULL))
{
free (*strptr);
*strptr = NULL;
}
return done;
}
And the code that finished the function. This means, all format specifiers are constant for one of scanf-family functions, and this implies that you can't register new handler without messing with the large clusterf..k in glibc source (that of course won't be portable).

Related

Why does my program keep getting stuck while running the mandelbrot brainf*** program?

I wanted to improve my C skills, so I search some program's ideas.
Someone propose to create a simple Brainf*** interpreter and then a compiler. So here I am.
I created the interpreter and it works as expected, except with the Mandelbrot program:
A mandelbrot set fractal viewer in brainfuck written by Erik Bosman
+++++++++++++[->++>>>+++++>++>+<<<<<<]>>>>>++++++>--->>>>>>>>>>+++++++++++++++[[
>>>>>>>>>]+[<<<<<<<<<]>>>>>>>>>-]+[>>>>>>>>[-]>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+
<<<<<<<+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>>+>>>>>>>>>>>>>>>>>>>>>>>>>>
>+<<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+[>>>>>>[>>>>>>>[-]>>]<<<<<<<<<[<<<<<<<<<]>>
>>>>>[-]+<<<<<<++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>+<<<<<<+++++++[-[->>>
>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[[-]>>>>>>[>>>>>
>>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>
[>>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<
<<]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]>>>>>>>>>+++++++++++++++[[
>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[
>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>[
-<<+>>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<
<<[>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<
[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>
>>>>[>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+
<<<<<<[->>>[-<<<+>>>]<<<[->>>+>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>
>>>>>>>]<<<<<<<<<[>>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<<]>>[->>>>>>>>>+<<<<<<<<<]<<
+>>>>>>>>]<<<<<<<<<[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<
<]<+<<<<<<<<<]>>>>>>>>>[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>
>>>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+>>>>>>>>>>>>>>>>>>>>>+<<<[<<<<<<
<<<]>>>>>>>>>[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<
<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-<<<+>>>]<<<[->
>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<
<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]<<<<<<<[->+>>>-<<<<]>>>>>>>>>+++++++++++++++++++
+++++++>>[-<<<<+>>>>]<<<<[->>>>+<<[-]<<]>>[<<<<<<<+<[-<+>>>>+<<[-]]>[-<<[->+>>>-
<<<<]>>>]>>>>>>>>>>>>>[>>[-]>[-]>[-]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>>>>>>[>>>>>
[-<<<<+>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>[-<<<<<<<<
<+>>>>>>>>>]>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>>>>>>]+>[-
]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>+>>>>>>>>]<<<
<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<[->>[-<<+>>]<
<[->>+>+<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[->>>>
>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[-]<->>>
[-<<<+>[<->-<<<<<<<+>>>>>>>]<[->+<]>>>]<<[->>+<<]<+<<<<<<<<<]>>>>>>>>>[>>>>>>[-<
<<<<+>>>>>]<<<<<[->>>>>+<<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>+>>>>>>>>
]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<[->>[-<<+
>>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>
[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[-
]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>>>>>
[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>++++++++
+++++++[[>>>>>>>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>>>>>>>>[-<<<<<<<+
>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[
-]>>>]<<<<<<<<<[<<<<<<<<<]>>>>+>[-<-<<<<+>>>>>]>[-<<<<<<[->>>>>+<++<<<<]>>>>>[-<
<<<<+>>>>>]<->+>]<[->+<]<<<<<[->>>>>+<<<<<]>>>>>>[-]<<<<<<+>>>>[-<<<<->>>>]+<<<<
[->>>>->>>>>[>>[-<<->>]+<<[->>->[-<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]
+>>>>>>[>>>>>>>>>]>+<]]+>>>[-<<<->>>]+<<<[->>>-<[-<<+>>]<<[->>+<<<<<<<<<<<[<<<<<
<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<
[<<<<<<<<<]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>>>>>>>]<<<<<
<<<+<[>[->>>>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>>[->>>+<<<]<]>[->>>-<<<<<<<<<
<<<<<+>>>>>>>>>>>]<<]>[->>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>>+<<<]<<
<<<<<<<<<<]>>>>[-]<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>[-<->]<[->+<]>>>>>>>>]<<<
<<<<<+<[>[->>>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>[->>>>+<<<<]>]<[->>>>-<<<<<<<
<<<<<<<+>>>>>>>>>>]<]>>[->>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>]>]<[->>>>+<<<<
]<<<<<<<<<<<]>>>>>>+<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>>>>>>>>>]<<<<<<<<<
[>[->>>>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>>[->>>+<<<]<]>[->>>-<<<<<<<<<<<<<<
+>>>>>>>>>>>]<<]>[->>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>>+<<<]<<<<<<<
<<<<<]]>[-]>>[-]>[-]>>>>>[>>[-]>[-]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-<
<<<+>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[
[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+
[>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>
[-<<+>>]<<[->>+>+<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<
<[>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[
>[-]<->>>[-<<<+>[<->-<<<<<<<+>>>>>>>]<[->+<]>>>]<<[->>+<<]<+<<<<<<<<<]>>>>>>>>>[
>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>
>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>[-]>>>>+++++++++++++++[[>>>>>>>>>]<<<<<<<<<-<<<<<
<<<<[<<<<<<<<<]>>>>>>>>>-]+[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<
<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-
<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>
>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>>>
[-<<<->>>]<<<[->>>+<<<]>>>>>>>>]<<<<<<<<+<[>[->+>[-<-<<<<<<<<<<+>>>>>>>>>>>>[-<<
+>>]<]>[-<<-<<<<<<<<<<+>>>>>>>>>>>>]<<<]>>[-<+>>[-<<-<<<<<<<<<<+>>>>>>>>>>>>]<]>
[-<<+>>]<<<<<<<<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>
>>>>>>]<<<<<<<<+<[>[->+>>[-<<-<<<<<<<<<<+>>>>>>>>>>>[-<+>]>]<[-<-<<<<<<<<<<+>>>>
>>>>>>>]<<]>>>[-<<+>[-<-<<<<<<<<<<+>>>>>>>>>>>]>]<[-<+>]<<<<<<<<<<<<]>>>>>+<<<<<
]>>>>>>>>>[>>>[-]>[-]>[-]>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>[-]>>>>>[>>>>>>>[-<<<<<
<+>>>>>>]<<<<<<[->>>>>>+<<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>+>[-<-<<<<+>>>>
>]>>[-<<<<<<<[->>>>>+<++<<<<]>>>>>[-<<<<<+>>>>>]<->+>>]<<[->>+<<]<<<<<[->>>>>+<<
<<<]+>>>>[-<<<<->>>>]+<<<<[->>>>->>>>>[>>>[-<<<->>>]+<<<[->>>-<[-<<+>>]<<[->>+<<
<<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>[-<<->>]+<<[->>->[-<<<+>>>]<
<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<
<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>[-<->]<[->+
<]>>>>>>>>]<<<<<<<<+<[>[->>>>+<<[->>-<<<<<<<<<<<<<+>>>>>>>>>>[->>>+<<<]>]<[->>>-
<<<<<<<<<<<<<+>>>>>>>>>>]<]>>[->>+<<<[->>>-<<<<<<<<<<<<<+>>>>>>>>>>]>]<[->>>+<<<
]<<<<<<<<<<<]>>>>>[-]>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]]>>>>[-<<<<+>
>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>>>>>>>]<<<<<<<<+<[>[->>>>+<<<[->>>-
<<<<<<<<<<<<<+>>>>>>>>>>>[->>+<<]<]>[->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<<]>[->>>+<<[
->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>+<<]<<<<<<<<<<<<]]>>>>[-]<<<<]>>>>[-<<<<+>>
>>]<<<<[->>>>+>[-]>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]>>>>>>>>>[>>>>>>
>>>]<<<<<<<<<[>[->>>>+<<<[->>>-<<<<<<<<<<<<<+>>>>>>>>>>>[->>+<<]<]>[->>-<<<<<<<<
<<<<<+>>>>>>>>>>>]<<]>[->>>+<<[->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>+<<]<<<<<<<<
<<<<]]>>>>>>>>>[>>[-]>[-]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>[-]>>>>>[>>>>>[-<<<<+
>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<+>>>>>
]<<<<<[->>>>>+<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>
>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>+>>
>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>[-<<+
>>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>
[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[-
]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>>>>>
[>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<
<<[->>>[-<<<+>>>]<<<[->>>+>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>
>>>]<<<<<<<<<[>>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<<]>>[->>>>>>>>>+<<<<<<<<<]<<+>>>
>>>>>]<<<<<<<<<[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+
<<<<<<<<<]>>>>>>>>>[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>>>>>
>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+>>>>>>>>>>>>>>>>>>>>>+<<<[<<<<<<<<<]
>>>>>>>>>[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<
]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-<<<+>>>]<<<[->>>+<
<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>
>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>->>[-<<<<+>>>>]<<<<[->>>>+<<[-]<<]>>]<<+>>>>[-<<<<
->>>>]+<<<<[->>>>-<<<<<<.>>]>>>>[-<<<<<<<.>>>>>>>]<<<[-]>[-]>[-]>[-]>[-]>[-]>>>[
>[-]>[-]>[-]>[-]>[-]>[-]>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-]>>>>]<<<<<<<<<
[<<<<<<<<<]>+++++++++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>+>>>>>>>>>+<<<<<<<<
<<<<<<[<<<<<<<<<]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+[-]>>[>>>>>>>>>]<<<<<
<<<<[>>>>>>>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<[<<<<<<<<<]>>>>>>>[-]+>>>]<<<<
<<<<<<]]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+>>[>+>>>>[-<<<<->>>>]<<<<[->>>
>+<<<<]>>>>>>>>]<<+<<<<<<<[>>>>>[->>+<<]<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<
<<<<[>[-]<->>>>>>>[-<<<<<<<+>[<->-<<<+>>>]<[->+<]>>>>>>>]<<<<<<[->>>>>>+<<<<<<]<
+<<<<<<<<<]>>>>>>>-<<<<[-]+<<<]+>>>>>>>[-<<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>->>[>>
>>>[->>+<<]>>>>]<<<<<<<<<[>[-]<->>>>>>>[-<<<<<<<+>[<->-<<<+>>>]<[->+<]>>>>>>>]<<
<<<<[->>>>>>+<<<<<<]<+<<<<<<<<<]>+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>+<<<
<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-<<<<<->>>>>]+<<<<<[->>>>>->>[-<<<<<<<+>>>>>>>]<<<<
<<<[->>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>>>>[-<
<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>-<<[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<<<<<<<<<[<<<
<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<
<<[<<<<<<<<<]>>>>[-]<<<+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>-<<<<<[<<<<<<<
<<]]>>>]<<<<.>>>>>>>>>>[>>>>>>[-]>>>]<<<<<<<<<[<<<<<<<<<]>++++++++++[-[->>>>>>>>
>+<<<<<<<<<]>>>>>>>>>]>>>>>+>>>>>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-<<<<<<
<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+[-]>[>>>>>>>>>]<<<<<<<<<[>>>>>>>>[-<<<<<<<+>>>>>>
>]<<<<<<<[->>>>>>>+<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+>>]<<<<<<<<<<]]>>>>>>>>[-<<<<<
<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+>[>+>>>>>[-<<<<<->>>>>]<<<<<[->>>>>+<<<<<]>>>>>>
>>]<+<<<<<<<<[>>>>>>[->>+<<]<<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[-]<-
>>>>>>>>[-<<<<<<<<+>[<->-<<+>>]<[->+<]>>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<]<+<<<<<<
<<<]>>>>>>>>-<<<<<[-]+<<<]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<<<<<[->>>>>>>>->[>>>
>>>[->>+<<]>>>]<<<<<<<<<[>[-]<->>>>>>>>[-<<<<<<<<+>[<->-<<+>>]<[->+<]>>>>>>>>]<<
<<<<<[->>>>>>>+<<<<<<<]<+<<<<<<<<<]>+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>
+>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<<->>>>>>]+<
<<<<<[->>>>>>->>[-<<<<<<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+<<<<<<<<<<<<<<<<<[<<<<<<<
<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<<<<<[->>>>>>>>
-<<[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>
>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-]<<<++++
+[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>->>>>>>>>>>>>>>>>>>>>>>>>>>>-<<<<<<[<<<<
<<<<<]]>>>]
I don't understand why, but my program keeps getting stuck in some sort of endless loop. I try to debug it using gdb but it's hard to find the right breakpoint in order to see why it stuck.
The program is as follows:
#include <stdio.h>
#include <stdlib.h>
// Brainfuck instructions
// > Math stuff
#define INCR '+' // +1 on current MS
#define DECR '-' // -1 on current MS
// > Memory slot stuff
#define FORW '>' // Go to next MS
#define BACK '<' // Go to previous MS
// > Logic stuff
#define SJMP '[' // Loop till current MS value is equal to zero
#define EJMP ']' // Jump to the beginning of the loop
// > I/O stuff
#define PRTC '.' // Print character with MS value as ASCII code
#define GETC ',' // Get an user input ASCII character code
typedef unsigned char byte;
// The brainfuck program struct
typedef struct {
byte *values;
int size;
int index;
byte *loops_starts;
int loop_size;
int loop_index;
} BrainfuckProgram;
void initialize(BrainfuckProgram *bfp) {
bfp->values = malloc(bfp->size * sizeof(*bfp->values));
bfp->loops_starts = malloc(bfp->size * sizeof(*bfp->loops_starts));
}
int allocate_values(BrainfuckProgram *bfp) {
byte *newMem = realloc(bfp->values, bfp->size * sizeof(byte));
if (!newMem) {
return 1;
}
bfp->values = newMem;
return 0;
}
int allocate_new_loop(BrainfuckProgram *bfp) {
byte *newMem = realloc(bfp->loops_starts, bfp->loop_size * sizeof(byte));
if (!newMem) {
return 1;
}
bfp->loops_starts = newMem;
return 0;
}
void set_value(BrainfuckProgram *bfp, byte value) {
int tempValue = value < 0 ? 255: value % 256;
*(bfp->values + bfp->index) = tempValue;
}
int get_value(BrainfuckProgram *bfp) {
return *(bfp->values + bfp->index);
}
// FILE functions
int get_file_name(int argc, char *argv[], char** fname) {
if (argc == 1) {
printf("File name is missing\n");
return 1;
}
*fname = argv[1];
return 0;
}
int get_file_size(FILE *file) {
fseek(file, 0L, SEEK_END);
int size = ftell(file);
rewind(file);
return size;
}
// Main function
int main(int argc, char *argv[]) {
// Vector part
BrainfuckProgram bfp = {
.values = NULL,
.size = 1,
.index = 0,
.loops_starts = NULL,
.loop_index = 0,
.loop_size = 0
};
initialize(&bfp);
// FILE Part
char* fname = NULL;
int error = get_file_name(argc, argv, &fname);
if (error) {
goto exit;
}
// Create file variable
FILE *fin = NULL;
fin = fopen(fname, "r");
int size = get_file_size(fin);
// Create a char array of the right size
byte *prog = NULL;
prog = malloc(size * sizeof(*prog));
// Read 1 byte size times
fread(prog, 1, size, fin);
for (int i = 0; i < size; i++) {
byte current = *(prog+i);
switch (current) {
case INCR:
set_value(&bfp, get_value(&bfp) + 1);
break;
case DECR:
set_value(&bfp, get_value(&bfp) - 1);
break;
case FORW:
// if index+1 == size then we are at the
// last element of the vector cause
// size = index - 1
if (bfp.index+1 == bfp.size) {
bfp.size++;
int error = allocate_values(&bfp);
if (error) {
printf("an error occured while forwarding pointer");
goto close;
}
}
bfp.index++;
break;
case BACK:
// bfp.index == 0 then !bfp.index == true
if (!bfp.index) {
printf("can go back from index 0\n");
goto close;
}
bfp.index--;
break;
case SJMP:
if (bfp.loop_index == bfp.size) {
bfp.loop_size++;
int error = allocate_new_loop(&bfp);
if (error) {
printf("an error occured while forwarding pointer");
goto close;
}
}
bfp.loop_index++;
*(bfp.loops_starts + bfp.loop_index) = i;
break;
case EJMP:
if (bfp.loop_index == -1) {
printf("cannot go back");
goto close;
}
if (get_value(&bfp) != 0) {
i = *(bfp.loops_starts + bfp.loop_index);
} else {
bfp.loop_index--;
}
break;
case PRTC:
printf("%c", get_value(&bfp));
break;
case GETC:
; // Semicolon here because of the label error
byte buf;
scanf("%c", &buf);
set_value(&bfp, buf);
break;
}
}
close:
fclose(fin);
exit:
;
return 0;
}
I'd like to have some C related advice on what I have done wrong too.
The Mandelbrot program takes a decent time to run on a good interpreter. Yours, well, it isn't that good. That's why it "hangs" at the start.
Some good ideas that you had, performance-wise:
precalculating loops
Some bad ideas, performance-wise:
Using abstracted allocation functions instead of calling realloc
using scanf and printf instead of getchar and putchar
Some odd things that you did:
Manually truncating an unsigned char when wraparound is implicit
checking if an unsigned char is less than 0
using *(x + y) syntax instead of array indexing x[y]
I don't think you actually use those precalculated loops, if you do then probably not correctly
You also probably create a new precalculated loop every time you go over the loop again
Using the get_value and set_value functions instead of pointers (this will be a performance issue if you don't compile with optimizations)
A couple suggestions:
Try to avoid calling functions when you don't need to as much as possible.
Write a BrainFuck->C compiler using this reference.
On second thought, maybe you should try to debug this program instead.
You may also use my interpreter as a reference if you're OK with GPLv3. Note that it doesn't precalculate loops.

Removing Flag Bits stored in an Array

I currently have the transmitter array that stores 01111110 0110111 01111110
I want the receiver array to store 0110111. I want to eliminate all the 01111110 bits.
But I am receiving 0110111 01111110. Why is it that my code is only removing the first 01111110 bits in the transmitter array?
My attempted code is as below:
#define nosbits 23
#include<stdio.h>
#include <stdlib.h>
#include<stdbool.h>
int main()
{
unsigned transmitter[nosbits] = { 0,1,1,1,1,1,1,0,0,1,1,0,1,1,1,0,1,1,1,1,1,1,0 };
unsigned receiver[nosbits];
int count = 0;
int outputreceivercount = 0;
bool flag = false;
for (int i = 0; i < nosbits; i++)
{
if (transmitter[i] == 1)
{
count++;
}
else
{
count = 0;
}
receiver[outputreceivercount++] = transmitter[i];
//After 5 consecutive 1s, if the next two bits are '10', then the flag is detected.
if ((transmitter[i + 1] == 1) && (transmitter[i + 2] == 0) && count == 5)
{
if (!(flag))
{
flag = true;
i = i + 2;
outputreceivercount = 0;
count = 0;
}
}
}
printf("Bitstream before removing flag bits:\n");
for (int i = 0; i < nosbits; i++)
{
printf("%d", transmitter[i]);
}
printf("\n\n");
printf("Bitstream after removing flag bits:\n");
for (int i = 0; i < outputreceivercount; i++)
{
printf("%d", receiver[i]);
}
printf("\n");
system("pause");
return 0;
}
Actually you don't need the "flag" variable to detect the flag.
Replace the following code and see if it helps.
//After 5 consecutive 1s, if the next two bits are '10', then the flag is detected.
if ((transmitter[i + 1] == 1) && (transmitter[i + 2] == 0) && count == 5)
{
i = i + 2;
outputreceivercount -= (count+1);
count = 0;
}
This can be optimized more if needed.
1) if you need to detect flags in multiple of 8bit, you had better to use characters, so when you detect the byte 0x7e, then eliminate it. This is applicable when you are using the flat character in asynchronous lines, that transmit only 8bit bytes. (Your sample data has only seven bits of data between flags, so I'll assume this is not the case.)
2) if you need to detect the flag on a per bit basis, then you face the HDLC framing problem, that has two parts: a) the flag is detected when you detect 6 joint 1 bits, and b) transmitter inserts a 0 bits if more than 5 1 bits are in sequence (to ensure transparency). For this second part you need also to delete the 6th 0 bit after a sequence of 5 1 bits also. I don't know if you want this, but your flag seems extremely similar to an HDLC flag to assume you are not actually studying this protocol.
This problem can be faced with a finite automaton. The NFA equivalent, to detect this is:
0,1
,--.
| /
| /
|v 1 1 1 1 1 0
(0)--->(1P)--->(2P)--->(3P)--->(4P)--->(5)--->(6D)
| | _
. . / \ 1
\ \ 1 | V
\0 `-->(7B)
\
\ 1 1 1 1 1 0
(8)--->(9)--->(10)--->(11)--->(12)--->(13)--->(14F)
Where
([1-4]P) Accepting state, print the number of 1 chars shown in the state number, (e.g. for state (3P) print 111.)
(6D) Accepting state, print 11111.
(7B) Accepting state. BREAK condition detected.
(14F) Accepting state. Flag detected.
All others are not accepting states. The automaton has to continue
matching states until no more accepting states can be reached, to output
the string of the last accepting state visited as output (e.g. if the last accepting state was 6D, then it has to output '11111'. In case the last state visited includes several accepting states, the priority order is:
14F, 7B, 6D, 4P, 3P, 2P, 1P
This NFA recognises 8 kinds of strings (I'll express them as regexps), namely: 0, 01111110, 1, 11, 111, 1111, 111110, and 11111111*. If a flag is accepted, you have to check also if the number of bits is a multiple of 8, as you can have arbitrary bit sequences with this protocol. Probably you don't, as the sample data you posted includes only seven bits. It could be represented by the following lex(1) pattern:
%%
0 ECHO;
01111110 putchar('F');
1111111* putchar('B');
1 |
11 |
111 |
1111 ECHO;
111110 fputs("11111", stdout);
. ;
%%
NOTE
Below is a complete DFA that converts the input bits into the following
alphabet (for your problem, it only needs to substitute the "F" and "B" strings with empty ones ""):
/*
* DFA to implement.
*/
#include <stdio.h>
#include <string.h>
#define F(x) __FILE__":%d:%s: " x, __LINE__, __func__
#ifndef DEBUG
#define DEBUG 0
#endif
#if DEBUG
#define D(...) fprintf(stderr, __VA_ARGS__)
#else
#define D(...)
#endif
#define E(...) fprintf(stderr, __VA_ARGS__)
char *names[] = {
"START" , "ST0" , "ST_1" , "ST01" ,
"ST_11" , "ST011" , "ST_111" , "ST0111" ,
"ST_1111" , "ST01111" , "ST_11111" , "ST011111" ,
"ST1111111", "ST" , "ST0111111", "ST1" ,
"ST11" , "ST111" , "ST1111" , "ST11111" ,
};
static enum st {
START , ST0 , ST_1 , ST01 , ST_11 ,
ST011 , ST_111 , ST0111 , ST_1111 , ST01111 ,
ST_11111 , ST011111 , ST1111111, ST , ST0111111,
ST1 , ST11 , ST111 , ST1111 , ST11111 ,
} state = START;
char flag[] = "F";
char brk[] = "B";
struct tab_entry {
enum st t_next;
char *t_insert;
} tab[][2] = {
/* INPUT */
/* STATE 0/OUTPUT | 1/OUTPUT */
/* ========================+================ */
/* START */ ST0, 0, ST_1, 0,
/* ST0 */ ST0, "0", ST01, 0,
/* ST_1 */ ST0, 0, ST_11, 0,
/* ST01 */ ST0, "01", ST011, 0,
/* ST_11 */ ST0, 0, ST_111, 0,
/* ST011 */ ST0, "011", ST0111, 0,
/* ST_111 */ ST0, 0, ST_1111, 0,
/* ST0111 */ ST0, "0111", ST01111, 0,
/* ST_1111 */ ST0, 0, ST_11111, 0,
/* ST01111 */ ST0, "01111", ST011111, 0,
/* ST_11111 */ ST0, 0, ST1111111, 0, /* break */
/* ST011111 */ ST, "011111", ST0111111, 0,
/* ST1111111 */ ST0, brk, ST1111111, 0,
/* ST */ ST0, 0, ST1, 0,
/* ST0111111 */ ST , flag, ST1111111, 0, /* break */
/* ST1 */ ST0, "1", ST11, 0,
/* ST11 */ ST0, "11", ST111, 0,
/* ST111 */ ST0, "111", ST1111, 0,
/* ST1111 */ ST0, "1111", ST11111, 0,
/* ST11111 */ ST, "11111", ST1111111, 0, /* break */
};
void hdlc_rst()
{
state = START;
}
char *hdlc_dec(char *out, int outsz, char *in)
{
char *res = out;
int c;
while ((c = *in++) != 0) {
switch(c) {
case '0': case '1':;
struct tab_entry *entry = &tab[state][c - '0'];
if (state != START) fputs("", stderr);
D(F("State: %s(%d), Input: '%c'\n"),
names[state], state, c);
if (entry->t_insert) {
int n = snprintf(out, outsz,
"%s", entry->t_insert);
D(F("Append \"%s\"\n"), entry->t_insert);
out += n;
outsz -= n;
}
D(F("State %s(%d) -> %s(%d)\n"),
names[state], state,
names[entry->t_next], entry->t_next);
state = entry->t_next;
break;
default:
E(F("Invalid character '%c' in input string\n"), c);
break;
} /* switch */
} /* while */
char *p = tab[state][0].t_insert;
snprintf(out, outsz, "%s", p ? p : "");
return res;
} /* hdlc_dec */
char *hdlc_enc(char *out, int outsz, char *in)
{
char *res = out;
char c;
int n_ones = 0;
while ((c = *in++) != 0) {
int n = 0;
switch(c) {
case 'F': case 'f':
n = snprintf(out, outsz, "01111110");
n_ones = 0;
break;
case 'B': case 'b':
n = snprintf(out, outsz, "1111111");
n_ones = 0;
break;
case '0':
n = snprintf(out, outsz, "0");
n_ones = 0;
break;
case '1':
n = snprintf(out, outsz, "1");
n_ones++;
if (n_ones == 5) {
n += snprintf(out+1, outsz-1, "0");
n_ones = 0;
}
break;
default:
D(F("Invalid character '%c' in input string\n"), c);
break;
} /* switch */
outsz -= n;
out += n;
} /* while */
return res;
} /* hdlc_enc */
int main(int argc, char **argv)
{
static char linea[10240], out[10240];
char *(*hdlc)(char *out, int outsz, char *in) = hdlc_dec;
if (strcmp(argv[0], "hdlc_dec") == 0)
hdlc = hdlc_dec;
else if (strcmp(argv[0], "hdlc_enc") == 0)
hdlc = hdlc_enc;
while(fgets(linea, sizeof linea, stdin)) {
int l = strlen(linea);
if (linea[l-1] == '\n') linea[--l] = '\0';
hdlc(out, sizeof out, linea);
D(F("%s ==> %s\n"), linea, out);
printf("%s\n", out);
} /* while */
} /* main */
To compile, use the following command:
cc -o hdlc_enc hdlc.c
ln hdlc_enc hdlc_dec
or, if you want debug traces of how the automaton works, use
cc -o hdlc_enc -DDEBUG=1 hdlc.c
ln hdlc_enc hdlc_dec
and you'll have both commands hdlc_enc to encode standard input, and hdlc_dec to decode it. To encode, use F for flag, B for BREAK, 0 and 1 (no restrictions) It will make 0 insertions at the proper places. To decode, just feed a sequence of bits, and it will transform flags into F, BREAKs into B and eliminate spureous 0s inserted by encoder. (after five 1 bits a 0 is inserted, to ensure transparency)
I have compiled the automaton by hand, so probably it's not optimum in the number of states, but 18 states is not too much.
The states names stand for the prefix ST followed by what has been read too far and not yet output because we cannot decide if it is a flag, break or a simple data bit sequence. States anchored to the stream beginning are prefixed by ST_.
NOTE 2
A DFA that, in addition recognises only multiple of 8 bit patterns between flags is far out of the scope of this answer. You can count the bits between flags and see if they are multiple of eight bits on flag recognition, as the DFA should have N1xN2 states (around 80 states) and this makes it no worth to implement.
To answer your specific question, you check the state of flag before you perform what looks to be your "remove" section - you require flag to be false before you "remove" the bits. The first time such a flag is detected you set flag to true. It then stays true for all subsequent loops, so your "remove" section can never execute again.
In more general terms, I'm somewhat confused by your "remove" section - every time a "flag" is detected, you start overwriting receiver from the 0th element? What happens in a string such as "0111111001101110111111010101010" - what would you expect your output to be?

How to store chars read from serial port into buffer for processing?

Right now I have some code that is printing out data read from a serial port with putch(out). But I need to store it into an array and process it to get floating point values out.
Here is my code just for talking to the serial port, with the calculations omitted:
#include <bios.h>
#include <conio.h>
#define COM1 0
#define DATA_READY 0x100
// set the baud rate, parity bit, data width...
#define SETTINGS ( 0xE0 | 0x03 | 0x00 | 0x00)
int main(void)
{
int in, out, status,i;
char dataRead[21];
float roll, pitch;
bioscom(0, SETTINGS, COM1); /*initialize the port*/
clrscr();
cprintf("Data sent to you: ");
while (1)
{
status = bioscom(3, 0, COM1); // reading the data here
if (status & DATA_READY)
if ((out = bioscom(2, 0, COM1) & 0 7F) != 0)
putch(out); // printing read value
if (kbhit( )) // If Esc is hit. it breaks and exit.
{
if ((in = getch( )) == ‘ 1B’) // 1B = Esc
DONE = TRUE;
bioscom(1, in, COM1); // data write. I am not making use of it.
}
}
return 0;
}
The incoming data encodes the roll and pitch, as something like "R:+XXX.XX P:-YYY.YY\r\n".
Instead of just printing this data out, I want to store it in the dataRead[] array and interpret it into float values. For instance, dataRead[2] to dataRead[8] encodes a float value for the "roll" as characters +XXX.XX.
How do I store these characters in the array and get the floating point number from it?
If you could write down some code for serial port which does exactly what i want then it would be really helpful. Please make sure it is written in 'C'.
I am not familiar with Dev C++ but in C++ you have the strtod function which converts string to double (float). You need to:
collect all characters from the serial port in one text line
parse the line
First is easy, just wait until reach "\n". Something like:
char line [MAX_LINE];
if(out == '\n')
parse_line(line. ....)
else
line[n_readed++] = out;
The second part is more tricky. You can use some text processing library for parsing or write your
own parse function using strtod. Since your case is simple I would rather do the second. Here is an example of the parse function which reads your text lines:
const char* line = "R:+123.56P:-767.77\r\n";
// return true on success
bool parse_line(const char* line, double* R, double* P)
{
const char* p = line;
if(*p++ != 'R')
return false;
if(*p++ != ':')
return false;
if(*p == '+') // + sign is optional
p++ ;
char* pEnd;
*R = strtod (p, &pEnd);
if(pEnd == p)
return false;
p = pEnd;
if(*p++ != 'P')
return false;
if(*p++ != ':')
return false;
*P = strtod (p, &pEnd);
if(pEnd == p)
return false;
return true;
}
int main()
{
double R,P;
if(!parse_line(line, &R, &P))
printf("error\n");
else
printf("sucessfully readed: %f\t%f\n", R,P);
return 0;
}
You need to declare two float arrays and to fill them with the parsed float values when the parsing function returns true. Otherwise there have been some error, probably because of damaged data. Also you can change all doubles with floats.
I hope this to help you.

UTF-8 to unicode converter for embeded system display

I have an embedded system that gets UTF-8 encoded data to display via UPNP. The display device has the ability to display characters. I need a way to convert the UTF-8 data I recieve via UPNP to unicode. The display is on a PIC, and it is sent data via a UPNP bridge running linux. Is there a simple way to do the conversion before I send it to the display board in linux?
If you have a real operating system and hosted C environment at your disposal, the best approach would be to simply ensure that your program runs in a locale that uses UTF-8 as its encoding and use mbrtowc or mbtowc to convert UTF-8 sequences to Unicode codepoint values (wchar_t is a Unicode codepoint number on Linux and any C implementation that defines __STDC_ISO_10646__).
If you do want to skip the system library routines and do UTF-8 decoding yourself, be careful. I once did a casual survey using Google code search and found that somewhere between 1/3 and 2/3 of the UTF-8 code out in the wild was dangerously wrong. Here is a fully correct, fast, and simple implementation I would highly recommend:
http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
My implementation in musl is somewhat smaller in binary size and seems to be faster, but it's also a bit harder to understand.
To convert an array of bytes encoded as UFT-8 into an array of Unicode code points:
The trick is to detect various encoding mistakes.
#include <limits.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
typedef struct {
uint32_t UnicodePoint; // Accumulated code point
uint32_t Min; // Minimum acceptable codepoint
int i; // Index of char/wchar_t remaining
bool e; // Error flag
} UTF_T;
static bool IsSurrogate(unsigned c) {
return (c >= 0xD800) && (c <= 0xDFFF);
}
// Return true if more bytes needed to complete codepoint
static bool Put8(UTF_T *U, unsigned ch) {
ch &= 0xFF;
if (U->i == 0) {
if (ch <= 0x7F) {
U->UnicodePoint = ch;
return false; /* No more needed */
} else if (ch <= 0xBF) {
goto fail;
} else if (ch <= 0xDF) {
U->Min = 0x80;
U->UnicodePoint = ch & 0x1F;
U->i = 1;
} else if (ch <= 0xEF) {
U->Min = 0x800;
U->UnicodePoint = ch & 0x0F;
U->i = 2;
} else if (ch <= 0xF7) {
U->Min = 0x10000;
U->UnicodePoint = ch & 0x07;
U->i = 3;
} else {
goto fail;
}
return true; /* More needed */
}
// If expected continuation character missing ...
if ((ch & (~0x3F)) != 0x80) {
goto fail;
}
U->UnicodePoint <<= 6;
U->UnicodePoint |= (ch & 0x3F);
// If last continuation character ...
if (--(U->i) == 0) {
// If codepoint out of range ...
if ((U->UnicodePoint < U->Min) || (U->UnicodePoint > 0x10FFFF)
|| IsSurrogate(U->UnicodePoint)) {
goto fail;
}
return false /* No more needed */;
}
return true; /* More needed */
fail:
U->UnicodePoint = -1;
U->i = 0;
U->e = true;
return false /* No more needed */;
}
/* return 0:OK, else error */
bool ConvertUTF8toUnicodeCodepoints(const char *UTF8, size_t Length,
uint32_t *CodePoints, size_t *OutLen) {
UTF_T U = { 0 };
*OutLen = 0;
for (size_t i = 0; i < Length;) {
while (Put8(&U, UTF8[i++])) {
// Needed bytes not available?
if (i >= Length) {
return true;
}
}
if (U.e) break;
CodePoints[(*OutLen)++] = U.UnicodePoint;
}
return U.e;
}
This is based on some old code, please advise as it may not be up to current standards.
Not the prettiest with goto and magic numbers.
What is nice about this approach is rather than CodePoints[(*OutLen)++] = U.UnicodePoint for consuming the codepoint, if one wanted to extract UTF16 (BE or LE), one could easily write consumer code for the UTF_T block and not need to change to the UTF8 -> codepoint part.
I would use the Unicode manipulation functions of GLib, a LGPL-licensed utility library. It sounds like g_utf8_to_ucs4() is what you are looking for.

encountered strange situation-variable value

I am programming on some device and I encountered
rather strange situation.
The same variable - for the first time has correct value,
but the SAME variable on a different place in code,
has a DIFFERENT value.
What can be causing this? I am pretty sure I didn't modify
the variable in between, I am also pretty sure I didn't
modify the variable using some pointers accidentally.
What can be causing this? I am really confused?
Can it be related that I for example used whole available stack
space of some function - and because of this compiler automatically
0-ifies my variable(or something similar)?
I have some long code inside a single function f.
Here's whole details on usage of pointsEntered variable in my code (how it is used).
/* Let the user input points */
s32 pointsEntered = 0;
int pointsCounter = 0;
while(1)
{
if(pointsCounter == 3)
return; // User entered wrong points 3 times, exit function
bool retStatus = false;
retStatus = inputPoints(&pointsEntered);
if(false == retStatus) // If user didn't enter amount, exit this function
return;
if(pointsEntered>atoi(userAmount)){
PromptBox(false, 0, "Points should not be more\n than current points");
pointsCounter++;
continue;
}
break;
}
// PROBLEM: pointsEntered - is OK here but as it will be shown below, it gets modified down the way
// even though I don't change it directly
char intTest1[50];
sprintf(intTest1, "1pentered %d", pointsEntered); // Here the value is OK! It shows value that I entered, e.g., 220
PromptBox(false, 0, intTest1);
/* Let the user enter 4 digit pin code */
u8 pinEntered[5] = {0};
bool retStatus1 = false;
retStatus1 = inputPin(pinEntered);
pinEntered[5]='\0';
if(false == retStatus1) // If user didn't enter amount, exit this function
return;
char intTest2[50];
sprintf(intTest2, "2pentered %d", pointsEntered); // Here pointsEnetered is OK
PromptBox(false, 0, intTest2);
/* Compute hash of pin code*/
s32 siRet1 = 0;
u8 pinVerify[25]={0};
u8 hashResult[16] = {0};
memcpy(pinVerify,pinEntered,4);
memcpy(&pinVerify[4],"XXXX",21);
siRet1 = sdkMD5(hashResult,pinVerify,25);
char intTest3[50];
sprintf(intTest3, "3pentered %d", pointsEntered); // Here pointsEntered has changed!!!
PromptBox(false, 0, intTest3);
/* convert string hash code to byte array */
unsigned char val[16] = {0};
unsigned char * pos = pinHash;
size_t count = 0;
// WARNING: no sanitization or error-checking whatsoever
for(count = 0; count < sizeof(val)/sizeof(val[0]); count++)
{
sscanf(pos, "%2hhx", &val[count]);
pos += 2 * sizeof(char);
}
char intTest4[50];
sprintf(intTest4, "4pentered %d", pointsEntered);
PromptBox(false, 0, intTest4);
/* Does the pin hash match ? */
if (siRet == SDK_OK && (!memcmp(hashResult,val,16)))
{
MsgBox("PIN OK","",0,SDK_KEY_MASK_ESC | SDK_KEY_MASK_ENTER);
}
else
{
MsgBox("PIN doesn't match-exiting","",0,SDK_KEY_MASK_ESC | SDK_KEY_MASK_ENTER);
return;
}
char intTest[50];
sprintf(intTest, "pentered %d", pointsEntered);
PromptBox(false, 0, intTest);
These two lines may cause it (as it's undefined behavior):
u8 pinEntered[5] = {0};
...
pinEntered[5]='\0';
Here you declare an array of five entries, but then you assign to a sixth item. This will most likely overwrite any previous variable on the stack.

Resources