summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/codegen/codegen_decl.c19
-rw-r--r--src/codegen/compat.h47
-rw-r--r--src/main.c8
-rw-r--r--src/utils/utils.c223
-rw-r--r--src/zprep.h1
5 files changed, 207 insertions, 91 deletions
diff --git a/src/codegen/codegen_decl.c b/src/codegen/codegen_decl.c
index 11cdece..31513ef 100644
--- a/src/codegen/codegen_decl.c
+++ b/src/codegen/codegen_decl.c
@@ -91,14 +91,8 @@ void emit_preamble(ParserContext *ctx, FILE *out)
fputs("static inline const char* _z_bool_str(_Bool b) { return b ? \"true\" : "
"\"false\"; }\n",
out);
- fputs("#define _z_str(x) _Generic((x), _Bool: \"%s\", char: \"%c\", "
- "signed char: \"%c\", unsigned char: \"%u\", short: \"%d\", "
- "unsigned short: \"%u\", int: \"%d\", unsigned int: \"%u\", "
- "long: \"%ld\", unsigned long: \"%lu\", long long: \"%lld\", "
- "unsigned long long: \"%llu\", float: \"%f\", double: \"%f\", "
- "char*: \"%s\", void*: \"%p\")\n",
- out);
- fputs("#define _z_arg(x) _Generic((x), _Bool: _z_bool_str(x), default: (x))\n", out);
+ fputs(ZC_C_GENERIC_STR, out);
+ fputs(ZC_C_ARG_GENERIC_STR, out);
}
fputs("typedef size_t usize;\ntypedef char* string;\n", out);
@@ -108,12 +102,11 @@ void emit_preamble(ParserContext *ctx, FILE *out)
fputs("typedef struct { pthread_t thread; void *result; } Async;\n", out);
}
fputs("typedef struct { void *func; void *ctx; } z_closure_T;\n", out);
- fputs("#define U0 void\n#define I8 int8_t\n#define U8 uint8_t\n#define I16 "
- "int16_t\n#define U16 uint16_t\n",
+ fputs("typedef void U0;\ntypedef int8_t I8;\ntypedef uint8_t U8;\ntypedef "
+ "int16_t I16;\ntypedef uint16_t U16;\n",
out);
- fputs("#define I32 int32_t\n#define U32 uint32_t\n#define I64 "
- "int64_t\n#define U64 "
- "uint64_t\n",
+ fputs("typedef int32_t I32;\ntypedef uint32_t U32;\ntypedef int64_t I64;\ntypedef "
+ "uint64_t U64;\n",
out);
fputs("#define F32 float\n#define F64 double\n", out);
diff --git a/src/codegen/compat.h b/src/codegen/compat.h
index 26b0df5..63a5af5 100644
--- a/src/codegen/compat.h
+++ b/src/codegen/compat.h
@@ -53,6 +53,27 @@
"#endif\n" \
"#endif\n"
+/* Generic selection string for C mode */
+#define ZC_C_GENERIC_STR \
+ "#ifdef __OBJC__\n" \
+ "#define _z_objc_map ,id: \"%s\", Class: \"%s\", SEL: \"%s\"\n" \
+ "#define _z_objc_arg_map(x) ,id: [(id)(x) description].UTF8String, Class: " \
+ "class_getName((Class)(x)), SEL: sel_getName((SEL)(x))\n" \
+ "#else\n" \
+ "#define _z_objc_map\n" \
+ "#define _z_objc_arg_map(x)\n" \
+ "#endif\n" \
+ "\n" \
+ "#define _z_str(x) _Generic((x), _Bool: \"%s\", char: \"%c\", " \
+ "signed char: \"%c\", unsigned char: \"%u\", short: \"%d\", " \
+ "unsigned short: \"%u\", int: \"%d\", unsigned int: \"%u\", " \
+ "long: \"%ld\", unsigned long: \"%lu\", long long: \"%lld\", " \
+ "unsigned long long: \"%llu\", float: \"%f\", double: \"%f\", " \
+ "char*: \"%s\", void*: \"%p\" _z_objc_map)\n"
+
+#define ZC_C_ARG_GENERIC_STR \
+ "#define _z_arg(x) _Generic((x), _Bool: _z_bool_str(x) _z_objc_arg_map(x), default: (x))\n"
+
#ifdef __cplusplus
#include <type_traits>
@@ -126,6 +147,32 @@ inline const char *_zc_fmt(void *)
}
#define _z_str(x) _zc_fmt(x)
+
+#ifdef __OBJC__
+#include <objc/objc.h>
+#include <objc/runtime.h>
+#include <objc/message.h> // for direct calls if needed, but [x description] is fine
+
+inline const char *_zc_fmt(id x)
+{
+ return [[x description] UTF8String];
+}
+inline const char *_zc_fmt(Class x)
+{
+ return class_getName(x);
+}
+inline const char *_zc_fmt(SEL x)
+{
+ return sel_getName(x);
+}
+// BOOL is signed char usually, already handled?
+// "typedef signed char BOOL;" on standard apple headers.
+// If it maps to signed char, `_zc_fmt(signed char)` handles it ("%c").
+// We might want "YES"/"NO" for BOOL.
+// But we can't distinguish typedefs in C++ function overloads easily if underlying type is same.
+// We'll leave BOOL as %c or %d for now to avoid ambiguity errors.
+#endif
+
#endif
#endif
diff --git a/src/main.c b/src/main.c
index b6392cc..f5d8c1b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -172,6 +172,10 @@ int main(int argc, char **argv)
g_config.use_cuda = 1;
g_config.use_cpp = 1; // CUDA implies C++ mode.
}
+ else if (strcmp(arg, "--objc") == 0)
+ {
+ g_config.use_objc = 1;
+ }
else if (strcmp(arg, "--check") == 0)
{
g_config.mode_check = 1;
@@ -304,6 +308,10 @@ int main(int argc, char **argv)
{
temp_source_file = "out.cpp";
}
+ else if (g_config.use_objc)
+ {
+ temp_source_file = "out.m";
+ }
// Codegen to C/C++/CUDA
FILE *out = fopen(temp_source_file, "w");
diff --git a/src/utils/utils.c b/src/utils/utils.c
index 56a7690..d6d9853 100644
--- a/src/utils/utils.c
+++ b/src/utils/utils.c
@@ -533,9 +533,81 @@ char g_cflags[MAX_FLAGS_SIZE] = "";
int g_warning_count = 0;
CompilerConfig g_config = {0};
+// Helper for environment expansion
+static void expand_env_vars(char *dest, size_t dest_size, const char *src)
+{
+ char *d = dest;
+ const char *s = src;
+ size_t remaining = dest_size - 1;
+
+ while (*s && remaining > 0)
+ {
+ if (*s == '$' && *(s + 1) == '{')
+ {
+ const char *end = strchr(s + 2, '}');
+ if (end)
+ {
+ char var_name[256];
+ int len = end - (s + 2);
+ if (len < 255)
+ {
+ strncpy(var_name, s + 2, len);
+ var_name[len] = 0;
+ char *val = getenv(var_name);
+ if (val)
+ {
+ size_t val_len = strlen(val);
+ if (val_len < remaining)
+ {
+ strcpy(d, val);
+ d += val_len;
+ remaining -= val_len;
+ s = end + 1;
+ continue;
+ }
+ }
+ }
+ }
+ }
+ *d++ = *s++;
+ remaining--;
+ }
+ *d = 0;
+}
+
+// Helper to determine active OS
+static int is_os_active(const char *os_name)
+{
+ if (0 == strcmp(os_name, "linux"))
+ {
+#ifdef __linux__
+ return 1;
+#else
+ return 0;
+#endif
+ }
+ else if (0 == strcmp(os_name, "windows"))
+ {
+#ifdef _WIN32
+ return 1;
+#else
+ return 0;
+#endif
+ }
+ else if (0 == strcmp(os_name, "macos") || 0 == strcmp(os_name, "darwin"))
+ {
+#ifdef __APPLE__
+ return 1;
+#else
+ return 0;
+#endif
+ }
+ return 0;
+}
+
void scan_build_directives(ParserContext *ctx, const char *src)
{
- (void)ctx; // Currently unused, reserved for future use
+ (void)ctx;
const char *p = src;
while (*p)
{
@@ -554,103 +626,113 @@ void scan_build_directives(ParserContext *ctx, const char *src)
len++;
}
- char line[2048];
+ char raw_line[2048];
if (len >= 2047)
{
len = 2047;
}
- strncpy(line, start, len);
- line[len] = 0;
+ strncpy(raw_line, start, len);
+ raw_line[len] = 0;
+
+ char line[2048];
+ expand_env_vars(line, sizeof(line), raw_line);
- if (0 == strncmp(line, "link:", 5))
+ char *directive = line;
+ char *colon = strchr(line, ':');
+ if (colon)
{
- char *val = line + 5;
- while (*val == ' ')
+ *colon = 0;
+ if (is_os_active(line))
+ {
+ directive = colon + 1;
+ while (*directive == ' ')
+ {
+ directive++;
+ }
+ }
+ else if (0 == strcmp(line, "linux") || 0 == strcmp(line, "windows") ||
+ 0 == strcmp(line, "macos"))
{
- val++;
+ goto next_line;
}
- if (strlen(g_link_flags) > 0)
+ else
{
- strcat(g_link_flags, " ");
+ *colon = ':';
+ directive = line;
}
- strcat(g_link_flags, val);
}
- else if (0 == strncmp(line, "cflags:", 7))
+
+ // Process Directive
+ if (0 == strncmp(directive, "link:", 5))
{
- char *val = line + 7;
- while (*val == ' ')
+ if (strlen(g_link_flags) > 0)
{
- val++;
+ strcat(g_link_flags, " ");
}
+ strcat(g_link_flags, directive + 5);
+ }
+ else if (0 == strncmp(directive, "cflags:", 7))
+ {
if (strlen(g_cflags) > 0)
{
strcat(g_cflags, " ");
}
- strcat(g_cflags, val);
+ strcat(g_cflags, directive + 7);
}
- else if (0 == strncmp(line, "include:", 8))
+ else if (0 == strncmp(directive, "include:", 8))
{
- char *val = line + 8;
- while (*val == ' ')
- {
- val++;
- }
char flags[2048];
- sprintf(flags, "-I%s", val);
+ sprintf(flags, "-I%s", directive + 8);
if (strlen(g_cflags) > 0)
{
strcat(g_cflags, " ");
}
strcat(g_cflags, flags);
}
- else if (strncmp(line, "lib:", 4) == 0)
+ else if (strncmp(directive, "lib:", 4) == 0)
{
- char *val = line + 4;
- while (*val == ' ')
- {
- val++;
- }
char flags[2048];
- sprintf(flags, "-L%s", val);
+ sprintf(flags, "-L%s", directive + 4);
if (strlen(g_link_flags) > 0)
{
strcat(g_link_flags, " ");
}
strcat(g_link_flags, flags);
}
- else if (strncmp(line, "define:", 7) == 0)
+ else if (strncmp(directive, "framework:", 10) == 0)
{
- char *val = line + 7;
- while (*val == ' ')
+ char flags[2048];
+ sprintf(flags, "-framework %s", directive + 10);
+ if (strlen(g_link_flags) > 0)
{
- val++;
+ strcat(g_link_flags, " ");
}
+ strcat(g_link_flags, flags);
+ }
+ else if (strncmp(directive, "define:", 7) == 0)
+ {
char flags[2048];
- sprintf(flags, "-D%s", val);
+ sprintf(flags, "-D%s", directive + 7);
if (strlen(g_cflags) > 0)
{
strcat(g_cflags, " ");
}
strcat(g_cflags, flags);
}
- else if (0 == strncmp(line, "shell:", 6))
+ else if (0 == strncmp(directive, "shell:", 6))
{
- char *cmd = line + 6;
- // printf("[zprep] Running shell: %s\n", cmd);
- int res = system(cmd);
- if (res != 0)
+ if (system(directive + 6) != 0)
{
- zwarn("Shell directive failed: %s", cmd);
+ zwarn("Shell directive failed: %s", directive + 6);
}
}
- else if (strncmp(line, "get:", 4) == 0)
+ else if (strncmp(directive, "get:", 4) == 0)
{
- char *url = line + 4;
+ char *url = directive + 4;
while (*url == ' ')
{
url++;
}
-
char *filename = strrchr(url, '/');
if (!filename)
{
@@ -660,8 +742,6 @@ void scan_build_directives(ParserContext *ctx, const char *src)
{
filename++;
}
-
- // Check if file exists to avoid redownloading.
FILE *f = fopen(filename, "r");
if (f)
{
@@ -669,16 +749,13 @@ void scan_build_directives(ParserContext *ctx, const char *src)
}
else
{
- printf("[zprep] Downloading %s...\n", filename);
char cmd[8192];
if (z_is_windows())
{
- // On Windows, try curl which is often built-in now
sprintf(cmd, "curl -s -L \"%s\" -o \"%s\"", url, filename);
}
else
{
- // Try wget, then curl.
sprintf(cmd, "wget -q \"%s\" -O \"%s\" || curl -s -L \"%s\" -o \"%s\"", url,
filename, url, filename);
}
@@ -688,40 +765,27 @@ void scan_build_directives(ParserContext *ctx, const char *src)
}
}
}
- else if (strncmp(line, "pkg-config:", 11) == 0)
+ else if (strncmp(directive, "pkg-config:", 11) == 0)
{
- char *libs = line + 11;
- while (*libs == ' ')
- {
- libs++;
- }
-
- if (z_is_windows())
- {
- zwarn("pkg-config is usually not available on Windows. Build directive "
- "'pkg-config:%s' might fail.",
- libs);
- }
-
+ char *libs = directive + 11;
char cmd[4096];
sprintf(cmd, "pkg-config --cflags %s", libs);
FILE *fp = popen(cmd, "r");
if (fp)
{
- char flags[4096];
- flags[0] = 0;
- if (fgets(flags, sizeof(flags), fp))
+ char buf[1024];
+ if (fgets(buf, sizeof(buf), fp))
{
- int len = strlen(flags);
- if (len > 0 && flags[len - 1] == '\n')
+ size_t l = strlen(buf);
+ if (l > 0 && buf[l - 1] == '\n')
{
- flags[len - 1] = 0;
+ buf[l - 1] = 0;
}
if (strlen(g_cflags) > 0)
{
strcat(g_cflags, " ");
}
- strcat(g_cflags, flags);
+ strcat(g_cflags, buf);
}
pclose(fp);
}
@@ -730,32 +794,35 @@ void scan_build_directives(ParserContext *ctx, const char *src)
fp = popen(cmd, "r");
if (fp)
{
- char flags[4096];
- flags[0] = 0;
- if (fgets(flags, sizeof(flags), fp))
+ char buf[1024];
+ if (fgets(buf, sizeof(buf), fp))
{
- int len = strlen(flags);
- if (len > 0 && flags[len - 1] == '\n')
+ size_t l = strlen(buf);
+ if (l > 0 && buf[l - 1] == '\n')
{
- flags[len - 1] = 0;
+ buf[l - 1] = 0;
}
if (strlen(g_link_flags) > 0)
{
strcat(g_link_flags, " ");
}
- strcat(g_link_flags, flags);
+ strcat(g_link_flags, buf);
}
pclose(fp);
}
}
+ else
+ {
+ zwarn("Unknown build directive: '%s'", directive);
+ }
p += len;
}
+ next_line:
while (*p && *p != '\n')
{
p++;
}
-
if (*p == '\n')
{
p++;
diff --git a/src/zprep.h b/src/zprep.h
index a943f3f..84400b3 100644
--- a/src/zprep.h
+++ b/src/zprep.h
@@ -359,6 +359,7 @@ typedef struct
int mode_transpile; ///< 1 if 'transpile' command (to C).
int use_cpp; ///< 1 if --cpp (emit C++ compatible code).
int use_cuda; ///< 1 if --cuda (emit CUDA-compatible code).
+ int use_objc; ///< 1 if --objc (emit Objective-C compatible code).
// GCC Flags accumulator.
char gcc_flags[4096]; ///< Flags passed to the backend compiler.