BCX Basic Forum

You must log on, to access files that were uploaded by BCX forum members. => Questions & Answers => Topic started by: Saleh on September 29, 2025, 05:02:32 AM

Title: Aggressive BASIC Parsing in $RAW Blocks
Post by: Saleh on September 29, 2025, 05:02:32 AM
Hi all,
BCX Parser Fails on Standard C Syntax: "if (condition) {" inside $RAW block leads to "If Without THEN" error.
The BCX translator incorrectly applies BASIC syntax rules to C/C++ code, even when that code is enclosed within a $RAW block which is intended to be processed as raw text and inserted directly into the generated C file.

Specifically, when a C if statement has its opening brace { on the same line as the condition, BCX misidentifies the structure as a missing THEN clause required by BASIC syntax.
 
Quote[Line ###]: If Without THEN
The following C structure is standard and valid C/C++, but is rejected by BCX:
// C/C++ code inside a $RAW block in the .bas file
int compare_bigint(const BigInt *a, const BigInt *b)
{
    // ...
    while (i >= 0)
    {
        if (a->data[i] != b->data[i]) {  // <--- The problematic line
            return (a->data[i] > b->data[i]) ? 1 : -1;
        }
        i--;
    }
    // ...
}

It maybe, This indicates the $RAW directive is not fully disabling the BASIC parser for keyword detection, or the C block handling logic is flawed.
Title: Re: Aggressive BASIC Parsing in $RAW Blocks
Post by: MrBcx on September 29, 2025, 07:23:27 AM
Hi Saleh,

That's not a lot for me to go on.

There is no $RAW directive in BCX - use $CCODE or the "!" to wrap your C/C++ code

"DATA" is a reserved BCX keyword and might cause problems, if used as a member of a struct 

One option you can consider -- converting your code to BCX BASIC using one of the AI's

for example:

TYPE BigInt
    data[256] AS UINT32   ' <-- adjust size and type as needed
    length    AS INT
END TYPE


FUNCTION compare_bigint(a AS BigInt PTR, b AS BigInt PTR) AS INT
    DIM i AS INT

    ' Start comparing from the most significant index
    i = a->length - 1
    IF b->length - 1 > i THEN
        i = b->length - 1
    END IF

    WHILE i >= 0
        IF a->data <> b->data THEN
            IF a->data > b->data THEN
                FUNCTION = 1
            ELSE
                FUNCTION = -1
            END IF
            EXIT FUNCTION
        END IF
        i = i - 1
    WEND

    FUNCTION = 0
END FUNCTION

Title: Re: Aggressive BASIC Parsing in $RAW Blocks
Post by: Saleh on September 29, 2025, 12:19:05 PM
Hi Kevin, thank you for your attention and response.

By the way, Gemini AI helped me design this code. When I asked what $RAW does, it told me that in newer versions of BCX, it behaves the same as $CCODE. I admit I was a bit lazy and took its word for it, assuming that since the code was compiled with Clang, this directive was supported and part of an updated feature set.

In short, Gemini said this might be a bug—and suggested I report it to you. 🙂

Anyway, this is the final version of the code, but it throws too many errors when compiled with MinGW—and honestly, I'm too old now to keep handling all these issues.
BCX BASIC to C/C++ Translator (c) 1999-2025 by Kevin Diggins
Version 8.2.9 (09/25/2025) Compiled using LLVM-Clang (21.1.1) for 64-bit Windows
[Lines In: 368 ] [Lines Out: 834 ] [Statements: 307 ] [Time: 0.04 Sec's]
BCX translated [File_2.Bas] to [File_2.C] for a C Compiler
**************************************************************************
MinGW g++ is compiling [ "D:\Share\prv2pbk\File_2" ] as a 64-bit CONSOLE application.
D:\Share\prv2pbk\File_2.c: In function 'void init_bigint(BigInt*, ULONG)':
D:\Share\prv2pbk\File_2.c:410:3: error: 'MEMSET' was not declared in this scope
410 |   MEMSET x->data,0,sizeof(x->data);
|   ^~~~~~
D:\Share\prv2pbk\File_2.c:410:3: note: the macro 'MEMSET' had not yet been defined
D:\Share\prv2pbk\File_2.c:796: note: it was later defined here
796 |   #define MEMSET(dest, val, count) memset((dest), (val), (count))
|
D:\Share\prv2pbk\File_2.c: In function 'void copy_bigint(BigInt*, BigInt*)':
D:\Share\prv2pbk\File_2.c:416:3: error: 'MEMCOPY' was not declared in this scope
416 |   MEMCOPY dest->data,src->data,sizeof(src->data);
|   ^~~~~~~
D:\Share\prv2pbk\File_2.c:416:3: note: the macro 'MEMCOPY' had not yet been defined
D:\Share\prv2pbk\File_2.c:797: note: it was later defined here
797 |   #define MEMCOPY(dest, src, count) memcpy((dest), (src), (count))
|
D:\Share\prv2pbk\File_2.c: In function 'void ptx_u256Add(BigInt*, BigInt*, BigInt*)':
D:\Share\prv2pbk\File_2.c:476:3: error: 'QWORD' was not declared in this scope
476 |   QWORD  carry={0};
|   ^~~~~
D:\Share\prv2pbk\File_2.c:476:3: note: the macro 'QWORD' had not yet been defined
D:\Share\prv2pbk\File_2.c:789: note: it was later defined here
789 |   #define QWORD uint64_t
|
D:\Share\prv2pbk\File_2.c:477:8: error: expected ';' before 'sum'
477 |   QWORD  sum={0};
|        ^ ~~~
|        ;
D:\Share\prv2pbk\File_2.c:479:3: error: 'carry' was not declared in this scope
479 |   carry=0;
|   ^~~~~
D:\Share\prv2pbk\File_2.c:482:7: error: 'sum' was not declared in this scope
482 |       sum=a->data+b->data+carry;
|       ^~~
D:\Share\prv2pbk\File_2.c:483:20: error: 'LOWDWORD' was not declared in this scope
483 |       res->data=LOWDWORD(sum);
|                    ^~~~~~~~
D:\Share\prv2pbk\File_2.c:483:20: note: the macro 'LOWDWORD' had not yet been defined
D:\Share\prv2pbk\File_2.c:795: note: it was later defined here
795 |   #define LOWDWORD(x) ((DWORD)(x))
|
D:\Share\prv2pbk\File_2.c: In function 'void ptx_u256Sub(BigInt*, BigInt*, BigInt*)':
D:\Share\prv2pbk\File_2.c:491:3: error: 'QWORD' was not declared in this scope
491 |   QWORD  diff={0};
|   ^~~~~
D:\Share\prv2pbk\File_2.c:491:3: note: the macro 'QWORD' had not yet been defined
D:\Share\prv2pbk\File_2.c:789: note: it was later defined here
789 |   #define QWORD uint64_t
|
D:\Share\prv2pbk\File_2.c:496:7: error: 'diff' was not declared in this scope
496 |       diff=a->data-b->data-borrow;
|       ^~~~
D:\Share\prv2pbk\File_2.c:497:20: error: 'LOWDWORD' was not declared in this scope
497 |       res->data=LOWDWORD(diff);
|                    ^~~~~~~~
D:\Share\prv2pbk\File_2.c:497:20: note: the macro 'LOWDWORD' had not yet been defined
D:\Share\prv2pbk\File_2.c:795: note: it was later defined here
795 |   #define LOWDWORD(x) ((DWORD)(x))
|
D:\Share\prv2pbk\File_2.c: In function 'void multiply_bigint_by_const(BigInt*, ULONG, ULONG*)':
D:\Share\prv2pbk\File_2.c:504:14: error: 'AS' was not declared in this scope
504 |   int carry(*AS)QWORD={0};
|              ^~
D:\Share\prv2pbk\File_2.c:511:17: error: 'LOWDWORD' was not declared in this scope
511 |       result=LOWDWORD(prod);
|                 ^~~~~~~~
D:\Share\prv2pbk\File_2.c:511:17: note: the macro 'LOWDWORD' had not yet been defined
D:\Share\prv2pbk\File_2.c:795: note: it was later defined here
795 |   #define LOWDWORD(x) ((DWORD)(x))
|
D:\Share\prv2pbk\File_2.c:512:17: warning: right shift count >= width of type [-Wshift-count-overflow]
512 |       carry=prod>>32;
|             ~~~~^~~~
D:\Share\prv2pbk\File_2.c:514:13: error: 'LOWDWORD' was not declared in this scope
514 |   result[8]=LOWDWORD(carry);
|             ^~~~~~~~
D:\Share\prv2pbk\File_2.c:514:13: note: the macro 'LOWDWORD' had not yet been defined
D:\Share\prv2pbk\File_2.c:795: note: it was later defined here
795 |   #define LOWDWORD(x) ((DWORD)(x))
|
D:\Share\prv2pbk\File_2.c: In function 'void shift_left_word(BigInt*, ULONG*)':
D:\Share\prv2pbk\File_2.c:519:10: error: 'AS' was not declared in this scope
519 |   int i(*AS)int={0};
|          ^~
D:\Share\prv2pbk\File_2.c: In function 'void add_9word(ULONG*, ULONG*)':
D:\Share\prv2pbk\File_2.c:529:14: error: 'AS' was not declared in this scope
529 |   int carry(*AS)QWORD={0};
|              ^~
D:\Share\prv2pbk\File_2.c:536:12: error: 'LOWDWORD' was not declared in this scope
536 |       r=LOWDWORD(sum);
|            ^~~~~~~~
D:\Share\prv2pbk\File_2.c:536:12: note: the macro 'LOWDWORD' had not yet been defined
D:\Share\prv2pbk\File_2.c:795: note: it was later defined here
795 |   #define LOWDWORD(x) ((DWORD)(x))
|
D:\Share\prv2pbk\File_2.c:537:16: warning: right shift count >= width of type [-Wshift-count-overflow]
537 |       carry=sum>>32;
|             ~~~^~~~
D:\Share\prv2pbk\File_2.c: In function 'void convert_9word_to_bigint(ULONG*, BigInt*)':
D:\Share\prv2pbk\File_2.c:543:10: error: 'AS' was not declared in this scope
543 |   int i(*AS)int={0};
|          ^~
D:\Share\prv2pbk\File_2.c: In function 'void mul_mod_old(BigInt*, BigInt*, BigInt*, BigInt*)':
D:\Share\prv2pbk\File_2.c:553:3: error: 'QWORD' was not declared in this scope
553 |   QWORD  carry={0};
|   ^~~~~
D:\Share\prv2pbk\File_2.c:553:3: note: the macro 'QWORD' had not yet been defined
D:\Share\prv2pbk\File_2.c:789: note: it was later defined here
789 |   #define QWORD uint64_t
|
D:\Share\prv2pbk\File_2.c:554:8: error: expected ';' before 'tmp'
554 |   QWORD  tmp={0};
|        ^ ~~~
|        ;
D:\Share\prv2pbk\File_2.c:567:3: error: 'MEMSET' was not declared in this scope
567 |   MEMSET prod,0,sizeof(prod);
|   ^~~~~~
D:\Share\prv2pbk\File_2.c:567:3: note: the macro 'MEMSET' had not yet been defined
D:\Share\prv2pbk\File_2.c:796: note: it was later defined here
796 |   #define MEMSET(dest, val, count) memset((dest), (val), (count))
|
D:\Share\prv2pbk\File_2.c:570:7: error: 'carry' was not declared in this scope
570 |       carry=0;
|       ^~~~~
D:\Share\prv2pbk\File_2.c:573:11: error: 'tmp' was not declared in this scope; did you mean 'tm'?
573 |           tmp=prod[i+j]+a->data*b->data[j]+carry;
|           ^~~
|           tm
D:\Share\prv2pbk\File_2.c:574:21: error: 'LOWDWORD' was not declared in this scope
574 |           prod[i+j]=LOWDWORD(tmp);
|                     ^~~~~~~~
D:\Share\prv2pbk\File_2.c:574:21: note: the macro 'LOWDWORD' had not yet been defined
D:\Share\prv2pbk\File_2.c:795: note: it was later defined here
795 |   #define LOWDWORD(x) ((DWORD)(x))
|
D:\Share\prv2pbk\File_2.c:577:49: error: 'LOWDWORD' was not declared in this scope
577 |       prod[i+BIGINT_WORDS]=prod[i+BIGINT_WORDS]+LOWDWORD(carry);
|                                                 ^~~~~~~~
D:\Share\prv2pbk\File_2.c:577:49: note: the macro 'LOWDWORD' had not yet been defined
D:\Share\prv2pbk\File_2.c:795: note: it was later defined here
795 |   #define LOWDWORD(x) ((DWORD)(x))
|
D:\Share\prv2pbk\File_2.c: In function 'void init_point_jac(ECPointJac*, BOOL)':
D:\Share\prv2pbk\File_2.c:657:3: error: 'MEMSET' was not declared in this scope
657 |   MEMSET p,0,sizeof(ECPointJac);
|   ^~~~~~
D:\Share\prv2pbk\File_2.c:657:3: note: the macro 'MEMSET' had not yet been defined
D:\Share\prv2pbk\File_2.c:796: note: it was later defined here
796 |   #define MEMSET(dest, val, count) memset((dest), (val), (count))
|
D:\Share\prv2pbk\File_2.c: In function 'void copy_point_jac(ECPointJac*, ECPointJac*)':
D:\Share\prv2pbk\File_2.c:666:3: error: 'MEMCOPY' was not declared in this scope
666 |   MEMCOPY dest,src,sizeof(ECPointJac);
|   ^~~~~~~
D:\Share\prv2pbk\File_2.c:666:3: note: the macro 'MEMCOPY' had not yet been defined
D:\Share\prv2pbk\File_2.c:797: note: it was later defined here
797 |   #define MEMCOPY(dest, src, count) memcpy((dest), (src), (count))
|
D:\Share\prv2pbk\File_2.c: In function 'void batch_inverse(BigInt*, BigInt**, ULONG, BigInt*)':
D:\Share\prv2pbk\File_2.c:678:21: error: 'batch_temp_products' was not declared in this scope; did you mean 'dimbatch_temp_products'?
678 |       init_bigint(&(batch_temp_products[0]),1);
|                     ^~~~~~~~~~~~~~~~~~~
|                     dimbatch_temp_products
D:\Share\prv2pbk\File_2.c:682:21: error: 'batch_temp_products' was not declared in this scope; did you mean 'dimbatch_temp_products'?
682 |       copy_bigint(&(batch_temp_products[0]),values[0]);
|                     ^~~~~~~~~~~~~~~~~~~
|                     dimbatch_temp_products
D:\Share\prv2pbk\File_2.c:687:25: error: 'batch_temp_products' was not declared in this scope; did you mean 'dimbatch_temp_products'?
687 |           copy_bigint(&(batch_temp_products),&(batch_temp_products[i-1]));
|                         ^~~~~~~~~~~~~~~~~~~
|                         dimbatch_temp_products
D:\Share\prv2pbk\File_2.c:691:25: error: 'batch_temp_products' was not declared in this scope; did you mean 'dimbatch_temp_products'?
691 |           mul_mod_old(&(batch_temp_products),&(batch_temp_products[i-1]),values,p);
|                         ^~~~~~~~~~~~~~~~~~~
|                         dimbatch_temp_products
D:\Share\prv2pbk\File_2.c:694:16: error: 'batch_temp_products' was not declared in this scope; did you mean 'dimbatch_temp_products'?
694 |   if(is_zero(&(batch_temp_products[count-1]))){
|                ^~~~~~~~~~~~~~~~~~~
|                dimbatch_temp_products
D:\Share\prv2pbk\File_2.c:709:59: error: 'batch_temp_products' was not declared in this scope; did you mean 'dimbatch_temp_products'?
709 |           mul_mod_old(&(inverses),&(current_inverse),&(batch_temp_products[i-1]),p);
|                                                           ^~~~~~~~~~~~~~~~~~~
|                                                           dimbatch_temp_products
D:\Share\prv2pbk\File_2.c: In function 'int BCX_Main()':
D:\Share\prv2pbk\File_2.c:764:40: error: 'secp256k1_p' was not declared in this scope; did you mean 'externsecp256k1_p'?
764 |   scalar_multiply_jac(&(R),&(G),&(k),&(secp256k1_p));
|                                        ^~~~~~~~~~~
|                                        externsecp256k1_p
D:\Share\prv2pbk\File_2.c:764:3: error: 'scalar_multiply_jac' was not declared in this scope
764 |   scalar_multiply_jac(&(R),&(G),&(k),&(secp256k1_p));
|   ^~~~~~~~~~~~~~~~~~~
D:\Share\prv2pbk\File_2.c:767:3: error: 'bigint_to_hex' was not declared in this scope
767 |   bigint_to_hex(&(X_affine[0]),hex);
|   ^~~~~~~~~~~~~
D:\Share\prv2pbk\File_2.c: At global scope:
D:\Share\prv2pbk\File_2.c:801:23: error: conflicting declaration 'const BigInt G_x'
801 |   extern const BigInt G_x;
|                       ^~~
D:\Share\prv2pbk\File_2.c:316:15: note: previous declaration as 'BigInt G_x'
316 | static BigInt G_x;
|               ^~~
D:\Share\prv2pbk\File_2.c:802:23: error: conflicting declaration 'const BigInt G_y'
802 |   extern const BigInt G_y;
|                       ^~~
D:\Share\prv2pbk\File_2.c:317:15: note: previous declaration as 'BigInt G_y'
317 | static BigInt G_y;
|               ^~~

Title: Re: Aggressive BASIC Parsing in $RAW Blocks
Post by: Saleh on September 29, 2025, 12:20:29 PM
$CCODE

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>


#ifndef QWORD
#define QWORD uint64_t
#endif
#ifndef DWORD
#define DWORD uint32_t
#endif

#define LOWDWORD(x) ((DWORD)(x))
#define MEMSET(dest, val, count) memset((dest), (val), (count))
#define MEMCOPY(dest, src, count) memcpy((dest), (src), (count))


extern const BigInt secp256k1_p;
extern const BigInt G_x;
extern const BigInt G_y;

extern void scalar_multiply_jac(ECPointJac *res, const ECPointJac *G, const BigInt *k, const BigInt *p);
extern void bigint_to_hex(const BigInt *bi, char *hex_str);

$CCODE
TYPE BigInt
    data[8] AS DWORD
END TYPE

TYPE ECPointJac
    X AS BigInt
    Y AS BigInt
    Z AS BigInt
    infinity AS BOOL
END TYPE

CONST BIGINT_WORDS = 8
CONST NUM_BATCH = 40000

DIM EXTERN secp256k1_p AS BigInt, G_x AS BigInt, G_y AS BigInt

DIM GLOBAL batch_temp_products[NUM_BATCH] AS BigInt

SUB init_bigint(x AS BigInt PTR, val AS DWORD)
    DIM i AS INT
    MEMSET x->data, 0, SIZEOF(x->data)
    x->data[0] = val
END SUB

SUB copy_bigint(dest AS BigInt PTR, src AS BigInt PTR)
    MEMCOPY dest->data, src->data, SIZEOF(src->data)
END SUB

FUNCTION compare_bigint(a AS BigInt PTR, b AS BigInt PTR) AS INT
    DIM i AS INT
    FOR i = BIGINT_WORDS - 1 TO 0 STEP -1
        IF a->data[i] <> b->data[i] THEN
            IF a->data[i] > b->data[i] THEN RETURN 1 ELSE RETURN -1
        END IF
    NEXT
    RETURN 0
END FUNCTION

FUNCTION is_zero(a AS BigInt PTR) AS BOOL
    DIM i AS INT
    FOR i = 0 TO BIGINT_WORDS - 1
        IF a->data[i] THEN RETURN FALSE
    NEXT
    RETURN TRUE
END FUNCTION

FUNCTION get_bit(a AS BigInt PTR, i AS INT) AS INT
    DIM word_idx AS INT
    DIM bit_idx AS INT

    word_idx = i >> 5
    bit_idx = i AND 31
    IF word_idx < BIGINT_WORDS THEN
        RETURN (a->data[word_idx] >> bit_idx) AND 1
    ELSE
        RETURN 0
    END IF
END FUNCTION

SUB ptx_u256Add(res AS BigInt PTR, a AS BigInt PTR, b AS BigInt PTR)
    DIM carry AS QWORD
    DIM sum AS QWORD
    DIM i AS INT

    carry = 0
    FOR i = 0 TO BIGINT_WORDS - 1
        sum = a->data[i] + b->data[i] + carry
        res->data[i] = LOWDWORD(sum)
        carry = sum >> 32
    NEXT
END SUB

SUB ptx_u256Sub(res AS BigInt PTR, a AS BigInt PTR, b AS BigInt PTR)
    DIM borrow AS DWORD
    DIM diff AS QWORD
    DIM i AS INT

    borrow = 0
    FOR i = 0 TO BIGINT_WORDS - 1
        diff = a->data[i] - b->data[i] - borrow
        res->data[i] = LOWDWORD(diff)
        borrow = (diff >> 32) AND 1
    NEXT
END SUB

SUB multiply_bigint_by_const(a AS BigInt PTR, c AS DWORD, result BYREF AS DWORD)
    DIM carry AS QWORD
    DIM prod AS QWORD
    DIM i AS INT

    carry = 0
    FOR i = 0 TO BIGINT_WORDS - 1
        prod = a->data[i] * c + carry
        result[i] = LOWDWORD(prod)
        carry = prod >> 32
    NEXT
    result[8] = LOWDWORD(carry)
END SUB

SUB shift_left_word(a AS BigInt PTR, result BYREF AS DWORD)
    DIM i AS INT

    result[0] = 0
    FOR i = 0 TO BIGINT_WORDS - 1
        result[i + 1] = a->data[i]
    NEXT
END SUB

SUB add_9word(r BYREF AS DWORD, addend BYREF AS DWORD)
    DIM carry AS QWORD
    DIM sum AS QWORD
    DIM i AS INT

    carry = 0
    FOR i = 0 TO 8
        sum = r[i] + addend[i] + carry
        r[i] = LOWDWORD(sum)
        carry = sum >> 32
    NEXT
END SUB

SUB convert_9word_to_bigint(r BYREF AS DWORD, res AS BigInt PTR)
    DIM i AS INT

    FOR i = 0 TO BIGINT_WORDS - 1
        res->data[i] = r[i]
    NEXT
END SUB

SUB mul_mod_old(res AS BigInt PTR, a AS BigInt PTR, b AS BigInt PTR, p AS BigInt PTR)
    DIM prod[16] AS DWORD
    DIM carry AS QWORD
    DIM tmp AS QWORD
    DIM i AS INT
    DIM j AS INT
    DIM L AS BigInt, H AS BigInt
    DIM Rext[9] AS DWORD
    DIM H977[9] AS DWORD, Hshift[9] AS DWORD
    DIM extra[9] AS DWORD, extraBI AS BigInt
    DIM extra977[9] AS DWORD, extraShift[9] AS DWORD
    DIM R_temp AS BigInt

    MEMSET prod, 0, SIZEOF(prod)

    FOR i = 0 TO BIGINT_WORDS - 1
        carry = 0
        FOR j = 0 TO BIGINT_WORDS - 1
            tmp = prod[i + j] + a->data[i] * b->data[j] + carry
            prod[i + j] = LOWDWORD(tmp)
            carry = tmp >> 32
        NEXT
        prod[i + BIGINT_WORDS] = prod[i + BIGINT_WORDS] + LOWDWORD(carry)
    NEXT

    FOR i = 0 TO BIGINT_WORDS - 1
        L.data[i] = prod[i]
        H.data[i] = prod[i + BIGINT_WORDS]
    NEXT

    FOR i = 0 TO BIGINT_WORDS - 1
        Rext[i] = L.data[i]
    NEXT
    Rext[8] = 0

    CALL multiply_bigint_by_const(VARPTR(H), 977, H977)
    CALL shift_left_word(VARPTR(H), Hshift)
    CALL add_9word(Rext, H977)
    CALL add_9word(Rext, Hshift)

    IF Rext[8] THEN
        CALL init_bigint(VARPTR(extraBI), Rext[8])
        Rext[8] = 0

        CALL multiply_bigint_by_const(VARPTR(extraBI), 977, extra977)
        CALL shift_left_word(VARPTR(extraBI), extraShift)
        CALL add_9word(extra, extraShift)
        CALL add_9word(Rext, extra)
    END IF

    CALL convert_9word_to_bigint(Rext, VARPTR(R_temp))

    IF Rext[8] OR compare_bigint(VARPTR(R_temp), p) >= 0 THEN
        CALL ptx_u256Sub(VARPTR(R_temp), VARPTR(R_temp), p)
        IF compare_bigint(VARPTR(R_temp), p) >= 0 THEN
            CALL ptx_u256Sub(VARPTR(R_temp), VARPTR(R_temp), p)
        END IF
    END IF

    CALL copy_bigint(res, VARPTR(R_temp))
END SUB

SUB sub_mod(res AS BigInt PTR, a AS BigInt PTR, b AS BigInt PTR, p AS BigInt PTR)
    DIM temp AS BigInt
    DIM sum AS BigInt

    IF compare_bigint(a, b) < 0 THEN
        CALL ptx_u256Add(VARPTR(sum), a, p)
        CALL ptx_u256Sub(VARPTR(temp), VARPTR(sum), b)
    ELSE
        CALL ptx_u256Sub(VARPTR(temp), a, b)
    END IF
    CALL copy_bigint(res, VARPTR(temp))
END SUB

SUB modexp(res AS BigInt PTR, base AS BigInt PTR, exp AS BigInt PTR, p AS BigInt PTR)
    DIM result AS BigInt, b AS BigInt, temp AS BigInt
    DIM i AS INT

    CALL init_bigint(VARPTR(result), 1)
    CALL copy_bigint(VARPTR(b), base)
    FOR i = 0 TO 255
        IF get_bit(exp, i) THEN
            CALL mul_mod_old(VARPTR(temp), VARPTR(result), VARPTR(b), p)
            CALL copy_bigint(VARPTR(result), VARPTR(temp))
        END IF
        CALL mul_mod_old(VARPTR(temp), VARPTR(b), VARPTR(b), p)
        CALL copy_bigint(VARPTR(b), VARPTR(temp))
    NEXT
    CALL copy_bigint(res, VARPTR(result))
END SUB

SUB mod_inverse(res AS BigInt PTR, a AS BigInt PTR, p AS BigInt PTR)
    DIM p_minus_2 AS BigInt, two AS BigInt

    CALL init_bigint(VARPTR(two), 2)
    CALL ptx_u256Sub(VARPTR(p_minus_2), p, VARPTR(two))
    CALL modexp(res, a, VARPTR(p_minus_2), p)
END SUB

SUB init_point_jac(p AS ECPointJac PTR, infinity AS BOOL)
    MEMSET p, 0, SIZEOF(ECPointJac)
    p->infinity = infinity
    IF NOT infinity THEN
        init_bigint(VARPTR(p->Z), 1)
    END IF
END SUB

SUB copy_point_jac(dest AS ECPointJac PTR, src AS ECPointJac PTR)
    MEMCOPY dest, src, SIZEOF(ECPointJac)
END SUB

SUB batch_inverse(inverses AS BigInt PTR, values AS BigInt PTR PTR, count AS DWORD, p AS BigInt PTR)
    DIM i AS DWORD
    DIM total_inverse AS BigInt
    DIM current_inverse AS BigInt

    IF count = 0 OR count > NUM_BATCH THEN EXIT SUB

    IF is_zero(values[0]) THEN
        CALL init_bigint(VARPTR(batch_temp_products[0]), 1)
    ELSE
        CALL copy_bigint(VARPTR(batch_temp_products[0]), values[0])
    END IF

    FOR i = 1 TO count - 1
        IF is_zero(values[i]) THEN
            CALL copy_bigint(VARPTR(batch_temp_products[i]), VARPTR(batch_temp_products[i - 1]))
        ELSE
            CALL mul_mod_old(VARPTR(batch_temp_products[i]), VARPTR(batch_temp_products[i - 1]), values[i], p)
        END IF
    NEXT

    IF is_zero(VARPTR(batch_temp_products[count - 1])) THEN
        CALL init_bigint(VARPTR(total_inverse), 0)
    ELSE
        CALL mod_inverse(VARPTR(total_inverse), VARPTR(batch_temp_products[count - 1]), p)
    END IF

    CALL copy_bigint(VARPTR(current_inverse), VARPTR(total_inverse))

    FOR i = count - 1 TO 1 STEP -1
        IF is_zero(values[i]) THEN
            CALL init_bigint(VARPTR(inverses[i]), 0)
        ELSE
            CALL mul_mod_old(VARPTR(inverses[i]), VARPTR(current_inverse), VARPTR(batch_temp_products[i - 1]), p)
            CALL mul_mod_old(VARPTR(current_inverse), VARPTR(current_inverse), values[i], p)
        END IF
    NEXT

    IF is_zero(values[0]) THEN
        CALL init_bigint(VARPTR(inverses[0]), 0)
    ELSE
        CALL copy_bigint(VARPTR(inverses[0]), VARPTR(current_inverse))
    END IF
END SUB

SUB batch_jacobian_to_affine_X_only(X_coords AS BigInt PTR, points AS ECPointJac PTR, count AS DWORD, p AS BigInt PTR)
    DIM i AS DWORD
    DIM Z_ptrs[NUM_BATCH] AS BigInt PTR
    DIM Z_inverses[NUM_BATCH] AS BigInt
    DIM Zinv2 AS BigInt

    IF count = 0 OR count > NUM_BATCH THEN EXIT SUB

    FOR i = 0 TO count - 1
        Z_ptrs[i] = VARPTR(points[i].Z)
    NEXT

    CALL batch_inverse(Z_inverses, Z_ptrs, count, p)

    FOR i = 0 TO count - 1
        IF points[i].infinity OR is_zero(Z_ptrs[i]) THEN
            CALL init_bigint(VARPTR(X_coords[i]), 0)
        ELSE
            CALL mul_mod_old(VARPTR(Zinv2), VARPTR(Z_inverses[i]), VARPTR(Z_inverses[i]), p)
            CALL mul_mod_old(VARPTR(X_coords[i]), VARPTR(points[i].X), VARPTR(Zinv2), p)
        END IF
    NEXT
END SUB

FUNCTION BCX_Main()
    DIM G AS ECPointJac
    DIM k AS BigInt
    DIM R AS ECPointJac
    DIM X_affine[1] AS BigInt
    DIM P[1] AS ECPointJac
    DIM hex$ AS STRING * 64

    PRINT "شروع تست عملیات منحنی بیضوی روی secp256k1..."

    CALL copy_bigint(VARPTR(G.X), VARPTR(G_x))
    CALL copy_bigint(VARPTR(G.Y), VARPTR(G_y))
    CALL init_bigint(VARPTR(G.Z), 1)
    G.infinity = FALSE

    CALL init_bigint(VARPTR(k), 7)

    CALL scalar_multiply_jac(VARPTR(R), VARPTR(G), VARPTR(k), VARPTR(secp256k1_p))

    CALL copy_point_jac(VARPTR(P[0]), VARPTR(R))
    CALL batch_jacobian_to_affine_X_only(X_affine, P, 1, VARPTR(secp256k1_p))

    CALL bigint_to_hex(VARPTR(X_affine[0]), hex$)

    PRINT "X : "
    PRINT hex$

    FUNCTION = 0
END FUNCTION
Title: Re: Aggressive BASIC Parsing in $RAW Blocks
Post by: MrBcx on September 29, 2025, 01:15:27 PM
Saleh,

This code is full of bugs that were generated by your AI assistant.

These are not BCX bugs, these are -YOUR- bugs.

Artificial Intelligence can be tremendously helpful but ultimately,
your code needs to be validated by you, not by AI.

Quote... and honestly, I'm too old now to keep handling all these issues.

FYI ...  We're all getting older. 

Title: Re: Aggressive BASIC Parsing in $RAW Blocks
Post by: Robert on September 29, 2025, 02:12:00 PM
Quote from: Saleh on September 29, 2025, 05:02:32 AMHi all,
BCX Parser Fails on Standard C Syntax: "if (condition) {" inside $RAW block leads to "If Without THEN" error.
The BCX translator incorrectly applies BASIC syntax rules to C/C++ code, even when that code is enclosed within a $RAW block which is intended to be processed as raw text and inserted directly into the generated C file.

Specifically, when a C if statement has its opening brace { on the same line as the condition, BCX misidentifies the structure as a missing THEN clause required by BASIC syntax.
Quote[Line ###]: If Without THEN
The following C structure is standard and valid C/C++, but is rejected by BCX:
// C/C++ code inside a $RAW block in the .bas file
int compare_bigint(const BigInt *a, const BigInt *b)
{
    // ...
    while (i >= 0)
    {
        if (a->data[i] != b->data[i]) {  // <--- The problematic line
            return (a->data[i] > b->data[i]) ? 1 : -1;
        }
        i--;
    }
    // ...
}

It maybe, This indicates the $RAW directive is not fully disabling the BASIC parser for keyword detection, or the C block handling logic is flawed.


Hi Saleh:

The correct syntax for enclosing a complete C function can be seen from the BCX Documentation index entry

$CCODE FUNCSUB directive.

Your C snippet would be

$CCODE FUNCSUB
int compare_bigint(const BigInt *a, const BigInt *b)
{
    // ...
    while (i >= 0)
    {
        if (a->data[i] != b->data[i]) {  // <--- The problematic line
            return (a->data[i] > b->data[i]) ? 1 : -1;
        }
        i--;
    }
    // ...
}
$CCODE

Here's a complete example

DIM a$
DIM b$

a$ = "    this  is    a    test      "

b$ = Remove_All_White_Space(a$)

PRINT b$

END PROGRAM

$CCODE FUNCSUB

char* Remove_All_White_Space(char* str1)
 {
  char *obuf,*nbuf;
  if (str1)
  {
    for (obuf=str1,nbuf=str1;*obuf;
    ++obuf)
    {
      if (!isspace(*obuf))
      *nbuf++=*obuf;
    }
  *nbuf=0;
  }
  return str1;
 }

$CCODE

Title: Re: Aggressive BASIC Parsing in $RAW Blocks
Post by: Robert on September 29, 2025, 02:38:21 PM
Also please read the $CPROTO help file section for another alternative.
Title: Re: Aggressive BASIC Parsing in $RAW Blocks
Post by: MrBcx on September 29, 2025, 05:09:28 PM
Saleh - I wanted to give you a few clues, in case you're not ready to throw in the towel just yet.

Many of the subs and functions contain elements of this working skeleton that I threw together for you.


TYPE BigInt
    dat[8] AS DWORD
END TYPE

DIM i AS BigInt

FOR INT z = 0 TO 7
    i.dat[z] = z  ' fill it with dummy data
NEXT

CALL foo (VARPTR(i))
PAUSE


SUB foo (a AS BigInt PTR)
    DIM b
    FOR INT j = 0 TO 7
        b = a->dat[j]
        PRINT b
    NEXT
END SUB


Next, you will find many occurrences of macro statements missing their enclosing parenthesis in your code:

MEMSET x->data, 0, SIZEOF(x->data)                --- should be ---  MEMSET(x->data, 0, SIZEOF(x->data))
MEMCOPY dest->data, src->data, SIZEOF(src->data)  --- should be ---  MEMCOPY dest->data, src->data, SIZEOF(src->data)
   
Why even use those macros when BCX allows you to use the C runtime functions directly?

memset(x->data, 0, SIZEOF(x->data))
memcpy(dest->data, src->data, SIZEOF(src->data))

In BCX_MAIN() you attempt to use a built-in BCX reserved function as a variable:  That is not allowed.

DIM hex$ AS STRING * 64

I'm certain this only scratches the surface but it gives you some specific things to start working through.

I suggest selectively commenting out blocks of code, in order to minimize the compiler errors down to
a manageable level.  When you get a clean compile with that subset, uncomment a bit more of your code
and rebuild.  Shampoo, Rinse, Repeat!

Hope that helps ...



Title: Re: Aggressive BASIC Parsing in $RAW Blocks
Post by: Saleh on September 30, 2025, 01:00:38 AM
"Alright, Kevin, thank you for your attention. I think I should start doubting my belief in artificial intelligence; it seems like it doesn't even know coding as much as a first‑grade elementary school student. I guess I'll have to rewrite the code myself."
Title: Re: Aggressive BASIC Parsing in $RAW Blocks
Post by: Saleh on September 30, 2025, 01:14:04 AM
Quote from: Robert on September 29, 2025, 02:38:21 PMAlso please read the $CPROTO help file section for another alternative.

Thank you robert, for your attentions.