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.
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
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;
| ^~~
$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
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.
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
Also please read the $CPROTO help file section for another alternative.
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 ...
"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."
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.