]> Nishi Git Mirror - libw3.git/commitdiff
tcl binding
authornishi <nishi@d27a3e52-49c5-7645-884c-6793ebffc270>
Tue, 6 Feb 2024 08:25:52 +0000 (08:25 +0000)
committernishi <nishi@d27a3e52-49c5-7645-884c-6793ebffc270>
Tue, 6 Feb 2024 08:25:52 +0000 (08:25 +0000)
git-svn-id: file:///raid/svn-main/nishi-libw3/trunk@175 d27a3e52-49c5-7645-884c-6793ebffc270

Example/w3b/w3b.c
Library/DNS.c
Library/Tcl.c
Library/W3Core.h

index 8a91a0557520306a652a642211a88dfebd2d8438..877595425549b20602a7aecc958c2d0599731134 100644 (file)
@@ -345,13 +345,13 @@ void render_site() {
                style = false;
                if(ctype != NULL && strcasecmp(ctype, "text/html") == 0) {
                        W3_Tag_Parse(databuf, datalen, html_handler, text_handler);
-               }else{
+               } else {
                        int i;
-                       for(i = 0; i < datalen; i++){
-                               if(databuf[i] == '\n'){
+                       for(i = 0; i < datalen; i++) {
+                               if(databuf[i] == '\n') {
                                        if(nl >= start && (nl - start) <= termh - 1) write(1, databuf + i, 1);
                                        nl++;
-                               }else if(nl >= start && (nl - start) <= termh - 1){
+                               } else if(nl >= start && (nl - start) <= termh - 1) {
                                        write(1, databuf + i, 1);
                                }
                        }
@@ -424,7 +424,7 @@ int main(int argc, char** argv) {
                }
                if(c != '\n' && c != '\r') {
                        printf("\x1b[%d;1H(O)pen, (Q)uit", termh);
-                       if(acc){
+                       if(acc) {
                                printf(", Go (u)p, Go (d)own");
                        }
                        printf("? ");
index bcaadb7739b82a75f467e9a27df0f3ff71f8e7fe..c5323a49bb0a7fb40cf450c868fd327d2a81bcad 100644 (file)
@@ -9,13 +9,13 @@
 #ifdef __MINGW32__
 #include <windows.h>
 #include <winsock2.h>
-#include <ws2tcpip.h>
 #include <ws2def.h>
+#include <ws2tcpip.h>
 #else
+#include <arpa/inet.h>
 #include <netdb.h>
-#include <sys/socket.h>
 #include <netinet/tcp.h>
-#include <arpa/inet.h>
+#include <sys/socket.h>
 #endif
 
 #include <stdbool.h>
index e40296835180695486a8605bb2fae48b58744f37..93688d594b4cc3133f0871c1a6100adaed80c02b 100644 (file)
 
 #include <tcl.h>
 
-#include "W3Util.h"
 #include "W3Core.h"
+#include "W3Util.h"
 
+#include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
-#include <ctype.h>
 
 extern int strcasecmp(const char* s1, const char* s2);
 
 void** __dictionary;
+void** __files;
+
+void tcl_w3_data_handler(struct W3* w3, char* data, size_t size) {
+       int i;
+       for(i = 0; __dictionary[i] != NULL; i += 2) {
+               if(__dictionary[i + 1] == w3) {
+                       if(w3->tcl_data != NULL) {
+                               Tcl_ObjSetVar2(w3->tcl_in, Tcl_NewStringObj("event_size", 10), NULL, Tcl_NewLongObj(size), 0);
+                               Tcl_ObjSetVar2(w3->tcl_in, Tcl_NewStringObj("event_data", 10), NULL, Tcl_NewStringObj(data, size), 0);
+                               char* data1 = malloc(size + 1);
+                               memcpy(data1, data, size);
+                               data1[size] = 0;
+                               Tcl_ObjSetVar2(w3->tcl_in, Tcl_NewStringObj("event_data_nulend", 17), NULL, Tcl_NewStringObj(data1, size + 1), 0);
+                               if(Tcl_Eval(w3->tcl_in, w3->tcl_data) == TCL_ERROR) {
+                                       const char* errmsg = Tcl_GetStringResult(w3->tcl_in);
+                                       fprintf(stderr, "Tcl error: %s\n", errmsg);
+                               }
+                               free(data1);
+                               Tcl_UnsetVar(w3->tcl_in, "event_data_nulend", 0);
+                               Tcl_UnsetVar(w3->tcl_in, "event_size", 0);
+                               Tcl_UnsetVar(w3->tcl_in, "event_data", 0);
+                       }
+               }
+       }
+}
 
-int Tcl_W3Cmd(ClientData dummy, Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]){
-       if(objc < 2){
+void tcl_w3_header_handler(struct W3* w3, char* key, char* value) {
+       int i;
+       for(i = 0; __dictionary[i] != NULL; i += 2) {
+               if(__dictionary[i + 1] == w3) {
+                       if(w3->tcl_header != NULL) {
+                               Tcl_ObjSetVar2(w3->tcl_in, Tcl_NewStringObj("event_key", 9), NULL, Tcl_NewStringObj(key, strlen(key) + 1), 0);
+                               Tcl_ObjSetVar2(w3->tcl_in, Tcl_NewStringObj("event_value", 11), NULL, Tcl_NewStringObj(value, strlen(value) + 1), 0);
+                               if(Tcl_Eval(w3->tcl_in, w3->tcl_header) == TCL_ERROR) {
+                                       const char* errmsg = Tcl_GetStringResult(w3->tcl_in);
+                                       fprintf(stderr, "Tcl error: %s\n", errmsg);
+                               }
+                               Tcl_UnsetVar(w3->tcl_in, "event_value", 0);
+                               Tcl_UnsetVar(w3->tcl_in, "event_key", 0);
+                       }
+               }
+       }
+}
+
+void tcl_w3_status_handler(struct W3* w3, int status) {
+       int i;
+       for(i = 0; __dictionary[i] != NULL; i += 2) {
+               if(__dictionary[i + 1] == w3) {
+                       if(w3->tcl_status != NULL) {
+                               char* status_text = Tcl_Alloc(17);
+                               sprintf(status_text, "%d", status);
+                               Tcl_ObjSetVar2(w3->tcl_in, Tcl_NewStringObj("event_status", 12), NULL, Tcl_NewStringObj(status_text, strlen(status_text) + 1), 0);
+                               if(Tcl_Eval(w3->tcl_in, w3->tcl_status) == TCL_ERROR) {
+                                       const char* errmsg = Tcl_GetStringResult(w3->tcl_in);
+                                       fprintf(stderr, "Tcl error: %s\n", errmsg);
+                               }
+                               Tcl_UnsetVar(w3->tcl_in, "event_status", 0);
+                               Tcl_Free(status_text);
+                       }
+               }
+       }
+}
+
+int Tcl_W3FIOCmd(ClientData dummy, Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]) {
+       if(objc < 2) {
+               const char* errmsg = "argument error: arguments should be \"w3fio subcommand arg1 arg2 ...\"";
+               Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
+               return TCL_ERROR;
+       }
+       char* subcommand = Tcl_GetString(objv[1]);
+       if(strcasecmp(subcommand, "open") == 0) {
+               if(objc != 5) {
+                       const char* errmsg = "argument error: arguments should be \"w3fio open name filename mode\"";
+                       Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
+                       return TCL_ERROR;
+               }
+               char* name = Tcl_GetString(objv[2]);
+               FILE* fp = fopen(Tcl_GetString(objv[3]), Tcl_GetString(objv[4]));
+               if(fp == NULL) {
+                       const char* errmsg = "connect error: failed to open";
+                       Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
+                       return TCL_ERROR;
+               } else {
+                       int len = 0;
+                       if(__files == NULL) {
+                               __files = malloc(sizeof(*__files) * (len + 3));
+                               __files[len] = __W3_Strdup(name);
+                               __files[len + 1] = fp;
+                               int i;
+                               for(i = 0; ((char*)__files[len])[i] != 0; i++) {
+                                       ((char*)__files[len])[i] = tolower(((char*)__files[len])[i]);
+                               }
+                               __files[len + 2] = NULL;
+                       } else {
+                               for(len = 0; __files[len] != NULL; len++)
+                                       ;
+                               void** __files2 = __files;
+                               __files = malloc(sizeof(*__files) * (len + 3));
+                               for(len = 0; __files2[len] != NULL; len++) {
+                                       __files[len] = __files2[len];
+                               }
+                               __files[len] = __W3_Strdup(name);
+                               __files[len + 1] = fp;
+                               __files[len + 2] = NULL;
+                               int i;
+                               for(i = 0; ((char*)__files[len])[i] != 0; i++) {
+                                       ((char*)__files[len])[i] = tolower(((char*)__files[len])[i]);
+                               }
+                               free(__files2);
+                       }
+                       Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
+               }
+       } else if(strcasecmp(subcommand, "write") == 0) {
+               if(objc != 5) {
+                       const char* errmsg = "argument error: arguments should be \"w3fio write name data size\"";
+                       Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
+                       return TCL_ERROR;
+               }
+               char* name = Tcl_GetString(objv[2]);
+               if(__files == NULL) {
+                       const char* errmsg = "argument error: a file handler named that does not exist";
+                       Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
+               } else {
+                       int i;
+                       for(i = 0; __files[i] != NULL; i += 2) {
+                               if(strcasecmp((char*)__files[i], name) == 0) {
+                                       fwrite(objv[3]->bytes, atoi(Tcl_GetString(objv[4])), 1, __files[i + 1]);
+                                       Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
+                                       return TCL_OK;
+                               }
+                       }
+                       const char* errmsg = "argument error: a file handler named that does not exist";
+                       Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
+               }
+       } else if(strcasecmp(subcommand, "close") == 0) {
+               if(objc != 3) {
+                       const char* errmsg = "argument error: arguments should be \"w3fio close name\"";
+                       Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
+                       return TCL_ERROR;
+               }
+               char* name = Tcl_GetString(objv[2]);
+               if(__files == NULL) {
+                       const char* errmsg = "argument error: a file handler named that does not exist";
+                       Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
+               } else {
+                       int i;
+                       int except = -1;
+                       int len = 0;
+                       for(i = 0; __files[i] != NULL; i += 2) {
+                               if(strcasecmp((char*)__files[i], name) == 0) {
+                                       fclose(__files[i + 1]);
+                                       free(__files[i]);
+                                       except = i;
+                                       break;
+                               }
+                       }
+                       for(len = 0; __files[len] != NULL; len++)
+                               ;
+                       if(except != -1) {
+                               void** oldfiles = __files;
+                               __files = malloc(sizeof(*__files) * (len - 1));
+                               int incr = 0;
+                               for(i = 0; oldfiles[i] != NULL; i += 2) {
+                                       if(except == i) continue;
+                                       __files[incr] = oldfiles[incr];
+                                       __files[incr + 1] = oldfiles[incr + 1];
+                                       incr += 2;
+                                       printf("woo");
+                               }
+                               oldfiles[incr] = NULL;
+                               Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
+                               return TCL_OK;
+                       }
+                       const char* errmsg = "argument error: a file handler named that does not exist";
+                       Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
+               }
+       } else {
+               const char* errmsg = "argument error: invalid subcommand";
+               Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
+               return TCL_ERROR;
+       }
+       return TCL_OK;
+}
+
+int Tcl_W3Cmd(ClientData dummy, Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]) {
+       if(objc < 2) {
                const char* errmsg = "argument error: arguments should be \"w3 subcommand arg1 arg2 ...\"";
                Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
                return TCL_ERROR;
        }
        char* subcommand = Tcl_GetString(objv[1]);
-       if(strcasecmp(subcommand, "create") == 0){
-               if(objc != 6){
+       if(strcasecmp(subcommand, "create") == 0) {
+               if(objc != 6) {
                        const char* errmsg = "argument error: arguments should be \"w3 create name protocol hostname port\"";
                        Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
                        return TCL_ERROR;
@@ -32,11 +215,13 @@ int Tcl_W3Cmd(ClientData dummy, Tcl_Interp* interp, int objc, Tcl_Obj* CONST obj
                char* hostname = Tcl_GetString(objv[4]);
                int port = atoi(Tcl_GetString(objv[5]));
                struct W3* w3 = W3_Create(protocol, hostname, port);
-               if(w3 == NULL){
+               w3->tcl_in = interp;
+               w3->tcl_data = NULL;
+               if(w3 == NULL) {
                        const char* errmsg = "connect error: failed to connect";
                        Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
                        return TCL_ERROR;
-               }else{
+               } else {
                        int len = 0;
                        if(__dictionary == NULL) {
                                __dictionary = malloc(sizeof(*__dictionary) * (len + 3));
@@ -66,28 +251,28 @@ int Tcl_W3Cmd(ClientData dummy, Tcl_Interp* interp, int objc, Tcl_Obj* CONST obj
                        }
                        Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
                }
-       }else if(strcasecmp(subcommand, "set_method") == 0 || strcasecmp(subcommand, "set_path") == 0){
-               if(objc != 4){
-                       if(strcasecmp(subcommand, "set_method") == 0){
+       } else if(strcasecmp(subcommand, "set_method") == 0 || strcasecmp(subcommand, "set_path") == 0) {
+               if(objc != 4) {
+                       if(strcasecmp(subcommand, "set_method") == 0) {
                                const char* errmsg = "argument error: arguments should be \"w3 set_method name method\"";
                                Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
-                       }else{
+                       } else {
                                const char* errmsg = "argument error: arguments should be \"w3 set_path name path\"";
                                Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
                        }
                        return TCL_ERROR;
                }
                char* name = Tcl_GetString(objv[2]);
-               if(__dictionary == NULL){
+               if(__dictionary == NULL) {
                        const char* errmsg = "argument error: a client named that does not exist";
                        Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
-               }else{
+               } else {
                        int i;
-                       for(i = 0; __dictionary[i] != NULL; i += 2){
-                               if(strcasecmp((char*)__dictionary[i], name) == 0){
-                                       if(strcasecmp(subcommand, "set_method") == 0){
+                       for(i = 0; __dictionary[i] != NULL; i += 2) {
+                               if(strcasecmp((char*)__dictionary[i], name) == 0) {
+                                       if(strcasecmp(subcommand, "set_method") == 0) {
                                                W3_Set_Method(__dictionary[i + 1], Tcl_GetString(objv[3]));
-                                       }else{
+                                       } else {
                                                W3_Set_Path(__dictionary[i + 1], Tcl_GetString(objv[3]));
                                        }
                                        Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
@@ -97,20 +282,55 @@ int Tcl_W3Cmd(ClientData dummy, Tcl_Interp* interp, int objc, Tcl_Obj* CONST obj
                        const char* errmsg = "argument error: a client named that does not exist";
                        Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
                }
-       }else if(strcasecmp(subcommand, "send_request") == 0){
-               if(objc != 3){
+       } else if(strcasecmp(subcommand, "set_data_handler") == 0 || strcasecmp(subcommand, "set_header_handler") == 0 || strcasecmp(subcommand, "set_status_handler") == 0) {
+               if(objc != 4) {
+                       const char* errmsg = "argument error: arguments should be \"w3 set_*_handler name handler\"";
+                       Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
+                       return TCL_ERROR;
+               }
+               char* name = Tcl_GetString(objv[2]);
+               char* handler = Tcl_GetString(objv[3]);
+               if(__dictionary == NULL) {
+                       const char* errmsg = "argument error: a client named that does not exist";
+                       Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
+               } else {
+                       int i;
+                       for(i = 0; __dictionary[i] != NULL; i += 2) {
+                               if(strcasecmp((char*)__dictionary[i], name) == 0) {
+                                       if(strcasecmp(subcommand, "set_header_handler") == 0) {
+                                               if(((struct W3*)__dictionary[i + 1])->tcl_header != NULL) free(((struct W3*)__dictionary[i + 1])->tcl_header);
+                                               ((struct W3*)__dictionary[i + 1])->tcl_header = __W3_Strdup(handler);
+                                               W3_On(__dictionary[i + 1], "header", tcl_w3_header_handler);
+                                       } else if(strcasecmp(subcommand, "set_status_handler") == 0) {
+                                               if(((struct W3*)__dictionary[i + 1])->tcl_status != NULL) free(((struct W3*)__dictionary[i + 1])->tcl_status);
+                                               ((struct W3*)__dictionary[i + 1])->tcl_status = __W3_Strdup(handler);
+                                               W3_On(__dictionary[i + 1], "status", tcl_w3_status_handler);
+                                       } else {
+                                               if(((struct W3*)__dictionary[i + 1])->tcl_data != NULL) free(((struct W3*)__dictionary[i + 1])->tcl_data);
+                                               ((struct W3*)__dictionary[i + 1])->tcl_data = __W3_Strdup(handler);
+                                               W3_On(__dictionary[i + 1], "data", tcl_w3_data_handler);
+                                       }
+                                       Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
+                                       return TCL_OK;
+                               }
+                       }
+                       const char* errmsg = "argument error: a client named that does not exist";
+                       Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
+               }
+       } else if(strcasecmp(subcommand, "send_request") == 0) {
+               if(objc != 3) {
                        const char* errmsg = "argument error: arguments should be \"w3 send_request name\"";
                        Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
                        return TCL_ERROR;
                }
                char* name = Tcl_GetString(objv[2]);
-               if(__dictionary == NULL){
+               if(__dictionary == NULL) {
                        const char* errmsg = "argument error: a client named that does not exist";
                        Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
-               }else{
+               } else {
                        int i;
-                       for(i = 0; __dictionary[i] != NULL; i += 2){
-                               if(strcasecmp((char*)__dictionary[i], name) == 0){
+                       for(i = 0; __dictionary[i] != NULL; i += 2) {
+                               if(strcasecmp((char*)__dictionary[i], name) == 0) {
                                        W3_Send_Request(__dictionary[i + 1]);
                                        Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
                                        return TCL_OK;
@@ -119,7 +339,7 @@ int Tcl_W3Cmd(ClientData dummy, Tcl_Interp* interp, int objc, Tcl_Obj* CONST obj
                        const char* errmsg = "argument error: a client named that does not exist";
                        Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
                }
-       }else{
+       } else {
                const char* errmsg = "argument error: invalid subcommand";
                Tcl_SetObjResult(interp, Tcl_NewStringObj(errmsg, strlen(errmsg)));
                return TCL_ERROR;
@@ -127,12 +347,15 @@ int Tcl_W3Cmd(ClientData dummy, Tcl_Interp* interp, int objc, Tcl_Obj* CONST obj
        return TCL_OK;
 }
 
-int W3_Init(Tcl_Interp* interp){
+int W3_Init(Tcl_Interp* interp) {
        __W3_Debug("Tcl", "Initializing the binding");
        W3_Library_Init();
        __dictionary = malloc(sizeof(*__dictionary));
        __dictionary[0] = NULL;
+       __files = malloc(sizeof(*__files));
+       __files[0] = NULL;
        Tcl_CreateObjCommand(interp, "w3", Tcl_W3Cmd, NULL, NULL);
+       Tcl_CreateObjCommand(interp, "w3fio", Tcl_W3FIOCmd, NULL, NULL);
        __W3_Debug("Tcl", "Initialized the binding");
        return TCL_OK;
 }
index 6240fbebd6c0e6be606592a69a530fa66c80d695..5e513685af35fbf53315d806f0f633f238fa3096 100644 (file)
@@ -12,24 +12,26 @@ extern "C" {
 #include "W3Version.h"
 
 struct W3 {
-       int sock;        /* Socket */
-       int port;        /* Port */
-       char* protocol;  /* As you can read from its name */
-       char* method;    /* Used in HTTP        */
-       char* path;      /* As you can read from its name */
-       char* hostname;  /* As you can read from its name */
-       char** headers;  /* As you can read from its name */
-       void** events;   /* As you can read from its name */
-       int status;      /* As you can read from its name */
-       char* data;      /* As you can read from its name */
-       size_t size;     /* Size of the data */
-       size_t readsize; /* Read buffer size, default is 512 */
-       char** props;    /* Properties */
-       void* generic;   /* Depends on the protocol */
-#ifdef SSL_SUPPORT
-       void* ssl;     /* Actually SSL*, NULL if no SSL */
-       void* ssl_ctx; /* Actually SSL_CTX* */
-#endif
+       int sock;         /* Socket */
+       int port;         /* Port */
+       char* protocol;   /* As you can read from its name */
+       char* method;     /* Used in HTTP       */
+       char* path;       /* As you can read from its name */
+       char* hostname;   /* As you can read from its name */
+       char** headers;   /* As you can read from its name */
+       void** events;    /* As you can read from its name */
+       int status;       /* As you can read from its name */
+       char* data;       /* As you can read from its name */
+       size_t size;      /* Size of the data */
+       size_t readsize;  /* Read buffer size, default is 512 */
+       char** props;     /* Properties */
+       void* generic;    /* Depends on the protocol */
+       char* tcl_header; /* Used in Tcl */
+       char* tcl_data;   /* Used in Tcl */
+       char* tcl_status; /* Used in Tcl */
+       void* tcl_in;     /* Used in Tcl */
+       void* ssl;        /* Actually SSL*, NULL if no SSL */
+       void* ssl_ctx;    /* Actually SSL_CTX* */
 };
 
 int W3_Library_Init(void);                                                 /* Initialize the Library */