plugins/sql.zc
Rama main · réplica de lectura del repositorio original.
import "../std/plugin.zc"
include <ctype.h>
include <stdio.h>
include <stdlib.h>
include <string.h>
fn skip_whitespace(p: char**) {
let ptr = *p;
while (ptr[0] != 0 && isspace((int)ptr[0])) {
ptr = &ptr[1];
}
*p = ptr;
}
fn match_kw(p: char**, kw: char*) -> int {
skip_whitespace(p);
let ptr = *p;
let len = strlen(kw);
if (strncasecmp(ptr, kw, (size_t)len) == 0 && !isalnum((int)ptr[len]) && ptr[len] != '_') {
*p = &ptr[len];
return 1;
}
return 0;
}
static let registered_tables: [char[64]; 16];
static let table_count = 0;
fn register_table(name: char*) {
if (table_count < 16) {
strncpy(®istered_tables[table_count][0], name, 63);
table_count = table_count + 1;
}
}
fn parse_create_table(p: char**, api: ZApi*) {
let out = api.out;
skip_whitespace(p);
let ptr = *p;
let name_start = ptr;
while (ptr[0] != 0 && (isalnum((int)ptr[0]) || ptr[0] == '_')) {
ptr = &ptr[1];
}
let name_len = (int)(ptr - name_start);
let table_name: [char; 64];
snprintf(&table_name[0], (size_t)(name_len + 1), "%s", name_start);
*p = ptr;
register_table(&table_name[0]);
skip_whitespace(p);
ptr = *p;
if (ptr[0] == '(') ptr = &ptr[1];
*p = ptr;
fputs(f"typedef struct {{ \n", out);
ptr = *p;
while (ptr[0] != 0 && ptr[0] != ')') {
skip_whitespace(&ptr);
let col_start = ptr;
while (ptr[0] != 0 && (isalnum((int)ptr[0]) || ptr[0] == '_')) ptr = &ptr[1];
let col_len = (int)(ptr - col_start);
if (col_len == 0) break;
let col_name: [char; 64];
snprintf(&col_name[0], (size_t)(col_len + 1), "%s", col_start);
skip_whitespace(&ptr);
let type_start = ptr;
while (ptr[0] != 0 && isalnum((int)ptr[0])) ptr = &ptr[1];
let type_len = (int)(ptr - type_start);
if (strncasecmp(type_start, "INTEGER", (size_t)type_len) == 0) {
fputs(" long ", out);
} else {
fputs(" const char* ", out);
}
fputs(&col_name[0], out); fputs(";\n", out);
skip_whitespace(&ptr);
if (ptr[0] == ',') ptr = &ptr[1];
}
if (ptr[0] == ')') ptr = &ptr[1];
*p = ptr;
fputs(f"""}} Row_{table_name};
static Row_{table_name} table_{table_name}[128];
static int count_{table_name} = 0;
""", out);
}
fn parse_insert(p: char**, api: ZApi*) {
let out = api.out;
match_kw(p, "INTO");
skip_whitespace(p);
let ptr = *p;
let name_start = ptr;
while (ptr[0] != 0 && (isalnum((int)ptr[0]) || ptr[0] == '_')) ptr = &ptr[1];
let name_len = (int)(ptr - name_start);
let table_name: [char; 64];
snprintf(&table_name[0], (size_t)(name_len + 1), "%s", name_start);
*p = ptr;
skip_whitespace(p);
if (!match_kw(p, "VALUES")) {
api.error(api, "Expected VALUES in INSERT");
return;
}
skip_whitespace(p);
ptr = *p;
if (ptr[0] == '(') ptr = &ptr[1];
*p = ptr;
fprintf(out, f"if (count_{table_name} < 128) {{ \n");
fprintf(out, f" table_{table_name}[count_{table_name}] = (Row_{table_name}){{ ");
ptr = *p;
while (ptr[0] != 0 && ptr[0] != ')') {
skip_whitespace(&ptr);
if (ptr[0] == 34 || ptr[0] == 39) {
let quote = ptr[0];
ptr = &ptr[1];
fputs("\"", out);
while (ptr[0] != 0 && ptr[0] != quote) {
if (ptr[0] == '\\' && ptr[1] != 0) {
fputc((int)ptr[0], out);
ptr = &ptr[1];
}
fputc((int)ptr[0], out);
ptr = &ptr[1];
}
fputs("\"", out);
if (ptr[0] == quote) ptr = &ptr[1];
} else {
let start = ptr;
while (ptr[0] != 0 && ptr[0] != ',' && ptr[0] != ')') ptr = &ptr[1];
fwrite(start, 1, (size_t)(ptr - start), out);
}
skip_whitespace(&ptr);
if (ptr[0] == ',') {
fputs(", ", out);
ptr = &ptr[1];
}
}
if (ptr[0] == ')') ptr = &ptr[1];
*p = ptr;
fprintf(out, f" }};\n count_{table_name}++;\n}} \n");
}
fn sql_transpile(body: char*, api: ZApi*) {
let p = body;
while (p[0] != 0) {
skip_whitespace(&p);
if (p[0] == 0) break;
if (match_kw(&p, "CREATE")) {
match_kw(&p, "TABLE");
parse_create_table(&p, api);
} else if (match_kw(&p, "INSERT")) {
parse_insert(&p, api);
} else {
while (p[0] != 0 && p[0] != ';') p = &p[1];
if (p[0] == ';') p = &p[1];
}
}
}
let sql_plugin = ZPlugin { name: "sql", handler: sql_transpile };
@export
fn z_plugin_init() -> ZPlugin* { return &sql_plugin; }