Page MenuHomeDevCentral

Ensure fbsql still compile with C23 standard
Open, LowPublic

Description

 Current context

We fixed compilation errors, but there is still one warning:

$ make
cc  -O2 -pipe -Wall -fPIC -I/usr/local/include/mysql -I/usr/local/include/mysql/mysql -I/usr/local/include/tcl8.6 -c fbsql.c -o fbsql.o
fbsql.c:556:19: warning: cast to smaller integer type 'int' from 'ClientData' (aka 'void *') [-Wvoid-pointer-to-int-cast]
  556 |         int sql_number = (int)sql_word;
      |                          ^~~~~~~~~~~~~
fbsql.c:599:1: warning: a function definition without a prototype is deprecated in all versions of C and is not supported in C23 [-Wdeprecated-non-prototype]
  599 | WaitVariableProc(clientData, interp, name1, name2, flags)
      | ^
fbsql.c:610:5: warning: a function definition without a prototype is deprecated in all versions of C and is not supported in C23 [-Wdeprecated-non-prototype]
  610 | int fbWaitCmd(clientData, interp, argc, argv)
      |     ^
fbsql.c:680:53: warning: cast to 'ClientData' (aka 'void *') from smaller integer type 'int' [-Wint-to-void-pointer-cast]
  680 |                         Tcl_CreateCommand (interp, command_name, SqlCmd, (ClientData) i, (Tcl_CmdDeleteProc*) NULL);
      |                                                                          ^~~~~~~~~~~~~~
4 warnings generated.

See T2213#34389 for suggestions to fix it.


 Historical context

When we opened the task, before D3910 fix, the compiler error was:

$ gmake                                                                                                                
cc -Wall -fPIC -I/home/local/include -I/usr/local/include/mysql -I/usr/local/include/tcl8.6   -c -o fbsql.o fbsql.c                                                                                                                            
fbsql.c:556:19: warning: cast to smaller integer type 'int' from 'ClientData' (aka 'void *') [-Wvoid-pointer-to-int-cast]                                                                                                                      
  556 |         int sql_number = (int)sql_word;                                                                                                                                                                                                
      |                          ^~~~~~~~~~~~~                                                                         
fbsql.c:599:1: warning: a function definition without a prototype is deprecated in all versions of C and is not supported in C23 [-Wdeprecated-non-prototype]                                                                                  
  599 | WaitVariableProc(clientData, interp, name1, name2, flags)                                                                                                                                                                              
      | ^                                                                                                                                                                                                                                      
fbsql.c:610:5: warning: a function definition without a prototype is deprecated in all versions of C and is not supported in C23 [-Wdeprecated-non-prototype]                                                                                  
  610 | int fbWaitCmd(clientData, interp, argc, argv)                                                                                                                                                                                          
      |     ^                                                                                                          
fbsql.c:667:36: error: incompatible function pointer types passing 'int (ClientData, Tcl_Interp *, int, char **)' (aka 'int (void *, struct Tcl_Interp *, int, char **)') to parameter of type 'Tcl_CmdProc *' (aka 'int (*)(void *, struct Tcl
_Interp *, int, const char **)') [-Wincompatible-function-pointer-types]                                                                                                                                                                       
  667 |         Tcl_CreateCommand (interp, "sql", SqlCmd, (ClientData) 0, (Tcl_CmdDeleteProc*) NULL);                  
      |                                           ^~~~~~                                                                                                                                                                                       
/usr/local/include/tcl8.6/tclDecls.h:303:39: note: passing argument to parameter 'proc' here                                                                                                                                                   
  303 |                                 const char *cmdName, Tcl_CmdProc *proc,                                        
      |                                                                   ^                                                                                                                                                                    
fbsql.c:680:53: warning: cast to 'ClientData' (aka 'void *') from smaller integer type 'int' [-Wint-to-void-pointer-cast]                                                                                                                      
  680 |                         Tcl_CreateCommand (interp, command_name, SqlCmd, (ClientData) i, (Tcl_CmdDeleteProc*) NULL);                                                                                                                   
      |                                                                          ^~~~~~~~~~~~~~                                                                                                                                                
fbsql.c:680:45: error: incompatible function pointer types passing 'int (ClientData, Tcl_Interp *, int, char **)' (aka 'int (void *, struct Tcl_Interp *, int, char **)') to parameter of type 'Tcl_CmdProc *' (aka 'int (*)(void *, struct Tcl
_Interp *, int, const char **)') [-Wincompatible-function-pointer-types]                                                                                                                                                                       
  680 |                         Tcl_CreateCommand (interp, command_name, SqlCmd, (ClientData) i, (Tcl_CmdDeleteProc*) NULL);                                                                                                                   
      |                                                                  ^~~~~~                                        
/usr/local/include/tcl8.6/tclDecls.h:303:39: note: passing argument to parameter 'proc' here                                                                                                                                                   
  303 |                                 const char *cmdName, Tcl_CmdProc *proc,                                        
      |                                                                   ^                                                                                                                                                                    
4 warnings and 2 errors generated.                                                                                                                                                                                                             
gmake: *** [<builtin>: fbsql.o] Error 1       

That's have been fixed

Event Timeline

dereckson triaged this task as High priority.Sat, Feb 7, 11:40
dereckson created this task.
dereckson moved this task from Backlog to Working on on the Dæghrefn board.
dereckson moved this task from Backlog to Eggdrop dev on the IRC board.
dereckson moved this task from Backlog to Services / Features on the DBA board.

Submitted the fbsql.c and compilation log to Claude Sonnet 4.5

Claude take is:

  • Old signature: int SqlCmd(ClientData, Tcl_Interp *, int, char **)
  • Expected signature: int SqlCmd(ClientData, Tcl_Interp *, int, const char **)

Claude only fixed the signature, leading to a lot of const char** -> char** warnings.

From there, I've updated every parameters extracted from argv to be a const char*

Seems to work fine:

$ tclsh
$ load ./fbsql.so
% sql connect 127.0.0.1
% sql "SELECT 1+1"
2
dereckson renamed this task from Ensure fbsql still compile for TCL 8.6.17 to Ensure fbsql still compile with C23 standard.Sat, Feb 7, 12:23
dereckson lowered the priority of this task from High to Low.
dereckson added a project: C.

The extension now compiles, links and works fine with D3910 and D3911.

There are still some warnings to fix:

cc  -O2 -pipe -Wall -fPIC -I/usr/local/include/mysql -I/usr/local/include/mysql/mysql -I/usr/local/include/tcl8.6 -c fbsql.c -o fbsql.o
fbsql.c:556:19: warning: cast to smaller integer type 'int' from 'ClientData' (aka 'void *') [-Wvoid-pointer-to-int-cast]
  556 |         int sql_number = (int)sql_word;
      |                          ^~~~~~~~~~~~~
fbsql.c:599:1: warning: a function definition without a prototype is deprecated in all versions of C and is not supported in C23 [-Wdeprecated-non-prototype]
  599 | WaitVariableProc(clientData, interp, name1, name2, flags)
      | ^
fbsql.c:610:5: warning: a function definition without a prototype is deprecated in all versions of C and is not supported in C23 [-Wdeprecated-non-prototype]
  610 | int fbWaitCmd(clientData, interp, argc, argv)
      |     ^
fbsql.c:680:53: warning: cast to 'ClientData' (aka 'void *') from smaller integer type 'int' [-Wint-to-void-pointer-cast]
  680 |                         Tcl_CreateCommand (interp, command_name, SqlCmd, (ClientData) i, (Tcl_CmdDeleteProc*) NULL);
      |                                                                          ^~~~~~~~~~~~~~
4 warnings generated.

Claude Sonnet 4.5 suggestions for a fix

Claude suggests two approaches:

  • A straightforward to use type intptr_t:
  • Or a more pedantic one to create a specific struct
Claude recommendation to use intptr_t
#include <stdint.h>

int sql_number = (int)(intptr_t)sql_word;  // Safe: pointer -> intptr_t -> int
Tcl_CreateCommand(..., (ClientData)(intptr_t)i, ...);  // Safe: int -> intptr_t -> pointer
Claude alternative recommendation
// At top of file, add:
typedef struct {
    int sql_number;
} SqlContext;

// In Fbsql_Init():
for (i = 0; i < SQL_COMMANDS; i++) {
    connection[i].CONNECTED = 0;
    connection[i].query_flag = 0;
    if (i > 0) {
        SqlContext *ctx = (SqlContext *)Tcl_Alloc(sizeof(SqlContext));
        ctx->sql_number = i;
        sprintf(command_name,"sql%d",i);
        Tcl_CreateCommand(interp, command_name, SqlCmd, (ClientData)ctx, 
                         SqlContextDeleteProc);
    }
}

// Add cleanup:
static void SqlContextDeleteProc(ClientData clientData) {
    Tcl_Free((char *)clientData);
}

// In SqlCmd:
SqlContext *ctx = (SqlContext *)sql_word;
int sql_number = ctx ? ctx->sql_number : 0;

(If you implement this, remember it's one or the other, not both)

dereckson added a project: good-first-issue.
dereckson moved this task from Backlog to General bug & features on the C board.
dereckson moved this task from Working on to Debt on the Dæghrefn board.
dereckson moved this task from Backlog to Dev on the good-first-issue board.