static int os_buf_to_tmp_file_windows(Buf *contents, Buf *suffix, Buf *out_tmp_path) { char tmp_dir[MAX_PATH + 1]; if (GetTempPath(MAX_PATH, tmp_dir) == 0) { zig_panic("GetTempPath failed"); } buf_init_from_str(out_tmp_path, tmp_dir); const char base64[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"; assert(array_length(base64) == 64 + 1); for (int i = 0; i < 8; i += 1) { buf_append_char(out_tmp_path, base64[rand() % 64]); } buf_append_buf(out_tmp_path, suffix); FILE *f = fopen(buf_ptr(out_tmp_path), "wb"); if (!f) { zig_panic("unable to open %s: %s", buf_ptr(out_tmp_path), strerror(errno)); } size_t amt_written = fwrite(buf_ptr(contents), 1, buf_len(contents), f); if (amt_written != (size_t)buf_len(contents)) { zig_panic("write failed: %s", strerror(errno)); } if (fclose(f)) { zig_panic("fclose failed"); } return 0; }
static int os_buf_to_tmp_file_posix(Buf *contents, Buf *suffix, Buf *out_tmp_path) { const char *tmp_dir = getenv("TMPDIR"); if (!tmp_dir) { tmp_dir = P_tmpdir; } buf_resize(out_tmp_path, 0); buf_appendf(out_tmp_path, "%s/XXXXXX%s", tmp_dir, buf_ptr(suffix)); int fd = mkstemps(buf_ptr(out_tmp_path), buf_len(suffix)); if (fd < 0) { return ErrorFileSystem; } FILE *f = fdopen(fd, "wb"); if (!f) { zig_panic("fdopen failed"); } size_t amt_written = fwrite(buf_ptr(contents), 1, buf_len(contents), f); if (amt_written != (size_t)buf_len(contents)) zig_panic("write failed: %s", strerror(errno)); if (fclose(f)) zig_panic("close failed"); return 0; }
void os_write_file(Buf *full_path, Buf *contents) { FILE *f = fopen(buf_ptr(full_path), "wb"); if (!f) { zig_panic("open failed"); } size_t amt_written = fwrite(buf_ptr(contents), 1, buf_len(contents), f); if (amt_written != (size_t)buf_len(contents)) zig_panic("write failed: %s", strerror(errno)); if (fclose(f)) zig_panic("close failed"); }
int os_path_real(Buf *rel_path, Buf *out_abs_path) { #if defined(ZIG_OS_WINDOWS) buf_resize(out_abs_path, 4096); if (_fullpath(buf_ptr(out_abs_path), buf_ptr(rel_path), buf_len(out_abs_path)) == nullptr) { zig_panic("_fullpath failed"); } buf_resize(out_abs_path, strlen(buf_ptr(out_abs_path))); return ErrorNone; #elif defined(ZIG_OS_POSIX) buf_resize(out_abs_path, PATH_MAX + 1); char *result = realpath(buf_ptr(rel_path), buf_ptr(out_abs_path)); if (!result) { int err = errno; if (err == EACCES) { return ErrorAccess; } else if (err == ENOENT) { return ErrorFileNotFound; } else if (err == ENOMEM) { return ErrorNoMem; } else { return ErrorFileSystem; } } buf_resize(out_abs_path, strlen(buf_ptr(out_abs_path))); return ErrorNone; #else #error "missing os_path_real implementation" #endif }
static int os_exec_process_posix(const char *exe, ZigList<const char *> &args, int *return_code, Buf *out_stderr, Buf *out_stdout) { int stdin_pipe[2]; int stdout_pipe[2]; int stderr_pipe[2]; int err; if ((err = pipe(stdin_pipe))) zig_panic("pipe failed"); if ((err = pipe(stdout_pipe))) zig_panic("pipe failed"); if ((err = pipe(stderr_pipe))) zig_panic("pipe failed"); pid_t pid = fork(); if (pid == -1) zig_panic("fork failed"); if (pid == 0) { // child if (dup2(stdin_pipe[0], STDIN_FILENO) == -1) zig_panic("dup2 failed"); if (dup2(stdout_pipe[1], STDOUT_FILENO) == -1) zig_panic("dup2 failed"); if (dup2(stderr_pipe[1], STDERR_FILENO) == -1) zig_panic("dup2 failed"); const char **argv = allocate<const char *>(args.length + 2); argv[0] = exe; argv[args.length + 1] = nullptr; for (int i = 0; i < args.length; i += 1) { argv[i + 1] = args.at(i); } execvp(exe, const_cast<char * const *>(argv)); if (errno == ENOENT) { return ErrorFileNotFound; } else { zig_panic("execvp failed: %s", strerror(errno)); } } else { // parent close(stdin_pipe[0]); close(stdout_pipe[1]); close(stderr_pipe[1]); waitpid(pid, return_code, 0); os_fetch_file(fdopen(stdout_pipe[0], "rb"), out_stdout); os_fetch_file(fdopen(stderr_pipe[0], "rb"), out_stderr); return 0; } }
static void os_spawn_process_posix(const char *exe, ZigList<const char *> &args, int *return_code) { pid_t pid = fork(); if (pid == -1) zig_panic("fork failed"); if (pid == 0) { // child const char **argv = allocate<const char *>(args.length + 2); argv[0] = exe; argv[args.length + 1] = nullptr; for (int i = 0; i < args.length; i += 1) { argv[i + 1] = args.at(i); } execvp(exe, const_cast<char * const *>(argv)); zig_panic("execvp failed: %s", strerror(errno)); } else { // parent waitpid(pid, return_code, 0); } }
static void os_spawn_process_posix(const char *exe, ZigList<const char *> &args, Termination *term) { pid_t pid = fork(); if (pid == -1) zig_panic("fork failed"); if (pid == 0) { // child const char **argv = allocate<const char *>(args.length + 2); argv[0] = exe; argv[args.length + 1] = nullptr; for (size_t i = 0; i < args.length; i += 1) { argv[i + 1] = args.at(i); } execvp(exe, const_cast<char * const *>(argv)); zig_panic("execvp failed: %s", strerror(errno)); } else { // parent int status; waitpid(pid, &status, 0); populate_termination(term, status); } }
int os_get_cwd(Buf *out_cwd) { #if defined(ZIG_OS_WINDOWS) buf_resize(out_cwd, 4096); if (GetCurrentDirectory(buf_len(out_cwd), buf_ptr(out_cwd)) == 0) { zig_panic("GetCurrentDirectory failed"); } return 0; #elif defined(ZIG_OS_POSIX) int err = ERANGE; buf_resize(out_cwd, 512); while (err == ERANGE) { buf_resize(out_cwd, buf_len(out_cwd) * 2); err = getcwd(buf_ptr(out_cwd), buf_len(out_cwd)) ? 0 : errno; } if (err) zig_panic("unable to get cwd: %s", strerror(err)); return 0; #else #error "missing os_get_cwd implementation" #endif }
static int os_exec_process_windows(const char *exe, ZigList<const char *> &args, int *return_code, Buf *out_stderr, Buf *out_stdout) { Buf command_line = BUF_INIT; buf_resize(&command_line, 0); buf_append_char(&command_line, '\"'); buf_append_str(&command_line, exe); buf_append_char(&command_line, '\"'); for (int arg_i = 0; arg_i < args.length; arg_i += 1) { buf_append_str(&command_line, " \""); const char *arg = args.at(arg_i); int arg_len = strlen(arg); for (int c_i = 0; c_i < arg_len; c_i += 1) { if (arg[c_i] == '\"') { zig_panic("TODO"); } buf_append_char(&command_line, arg[c_i]); } buf_append_char(&command_line, '\"'); } HANDLE g_hChildStd_IN_Rd = NULL; HANDLE g_hChildStd_IN_Wr = NULL; HANDLE g_hChildStd_OUT_Rd = NULL; HANDLE g_hChildStd_OUT_Wr = NULL; HANDLE g_hChildStd_ERR_Rd = NULL; HANDLE g_hChildStd_ERR_Wr = NULL; SECURITY_ATTRIBUTES saAttr; saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0)) { zig_panic("StdoutRd CreatePipe"); } if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) { zig_panic("Stdout SetHandleInformation"); } if (!CreatePipe(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, &saAttr, 0)) { zig_panic("stderr CreatePipe"); } if (!SetHandleInformation(g_hChildStd_ERR_Rd, HANDLE_FLAG_INHERIT, 0)) { zig_panic("stderr SetHandleInformation"); } if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) { zig_panic("Stdin CreatePipe"); } if (!SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0)) { zig_panic("Stdin SetHandleInformation"); } PROCESS_INFORMATION piProcInfo = {0}; STARTUPINFO siStartInfo = {0}; siStartInfo.cb = sizeof(STARTUPINFO); siStartInfo.hStdError = g_hChildStd_ERR_Wr; siStartInfo.hStdOutput = g_hChildStd_OUT_Wr; siStartInfo.hStdInput = g_hChildStd_IN_Rd; siStartInfo.dwFlags |= STARTF_USESTDHANDLES; BOOL success = CreateProcess(exe, buf_ptr(&command_line), nullptr, nullptr, TRUE, 0, nullptr, nullptr, &siStartInfo, &piProcInfo); if (!success) { if (GetLastError() == ERROR_FILE_NOT_FOUND) { CloseHandle(piProcInfo.hProcess); CloseHandle(piProcInfo.hThread); return ErrorFileNotFound; } zig_panic("CreateProcess failed. exe: %s command_line: %s", exe, buf_ptr(&command_line)); } if (!CloseHandle(g_hChildStd_IN_Wr)) { zig_panic("stdinwr closehandle"); } CloseHandle(g_hChildStd_IN_Rd); CloseHandle(g_hChildStd_ERR_Wr); CloseHandle(g_hChildStd_OUT_Wr); static const int BUF_SIZE = 4 * 1024; { DWORD dwRead; char chBuf[BUF_SIZE]; buf_resize(out_stdout, 0); for (;;) { success = ReadFile( g_hChildStd_OUT_Rd, chBuf, BUF_SIZE, &dwRead, NULL); if (!success || dwRead == 0) break; buf_append_mem(out_stdout, chBuf, dwRead); } CloseHandle(g_hChildStd_OUT_Rd); } { DWORD dwRead; char chBuf[BUF_SIZE]; buf_resize(out_stderr, 0); for (;;) { success = ReadFile( g_hChildStd_ERR_Rd, chBuf, BUF_SIZE, &dwRead, NULL); if (!success || dwRead == 0) break; buf_append_mem(out_stderr, chBuf, dwRead); } CloseHandle(g_hChildStd_ERR_Rd); } WaitForSingleObject(piProcInfo.hProcess, INFINITE); DWORD exit_code; if (!GetExitCodeProcess(piProcInfo.hProcess, &exit_code)) { zig_panic("GetExitCodeProcess failed"); } *return_code = exit_code; CloseHandle(piProcInfo.hProcess); CloseHandle(piProcInfo.hThread); return 0; }
int get_c_type_size_in_bits(const ZigTarget *target, CIntType id) { switch (target->os) { case ZigLLVM_UnknownOS: zig_unreachable(); case ZigLLVM_Linux: case ZigLLVM_Darwin: switch (id) { case CIntTypeShort: case CIntTypeUShort: return 16; case CIntTypeInt: case CIntTypeUInt: return 32; case CIntTypeLong: case CIntTypeULong: return get_arch_pointer_bit_width(target->arch.arch); case CIntTypeLongLong: case CIntTypeULongLong: return 64; case CIntTypeCount: zig_unreachable(); } case ZigLLVM_Win32: switch (id) { case CIntTypeShort: case CIntTypeUShort: return 16; case CIntTypeInt: case CIntTypeUInt: case CIntTypeLong: case CIntTypeULong: return 32; case CIntTypeLongLong: case CIntTypeULongLong: return 64; case CIntTypeCount: zig_unreachable(); } case ZigLLVM_CloudABI: case ZigLLVM_DragonFly: case ZigLLVM_FreeBSD: case ZigLLVM_IOS: case ZigLLVM_KFreeBSD: case ZigLLVM_Lv2: case ZigLLVM_MacOSX: case ZigLLVM_NetBSD: case ZigLLVM_OpenBSD: case ZigLLVM_Solaris: case ZigLLVM_Haiku: case ZigLLVM_Minix: case ZigLLVM_RTEMS: case ZigLLVM_NaCl: case ZigLLVM_CNK: case ZigLLVM_Bitrig: case ZigLLVM_AIX: case ZigLLVM_CUDA: case ZigLLVM_NVCL: case ZigLLVM_AMDHSA: case ZigLLVM_PS4: zig_panic("TODO c type size in bits for this target"); } zig_unreachable(); }
static void render_node(AstRender *ar, AstNode *node) { assert(node->type == NodeTypeRoot || *node->parent_field == node); switch (node->type) { case NodeTypeRoot: for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) { AstNode *child = node->data.root.top_level_decls.at(i); print_indent(ar); render_node(ar, child); if (child->type == NodeTypeImport || child->type == NodeTypeVariableDeclaration || child->type == NodeTypeTypeDecl || child->type == NodeTypeErrorValueDecl || child->type == NodeTypeFnProto) { fprintf(ar->f, ";"); } fprintf(ar->f, "\n"); } break; case NodeTypeRootExportDecl: zig_panic("TODO"); case NodeTypeFnProto: { const char *fn_name = buf_ptr(&node->data.fn_proto.name); const char *pub_str = visib_mod_string(node->data.fn_proto.visib_mod); const char *extern_str = extern_string(node->data.fn_proto.is_extern); const char *inline_str = inline_string(node->data.fn_proto.is_inline); fprintf(ar->f, "%s%s%sfn %s(", pub_str, inline_str, extern_str, fn_name); int arg_count = node->data.fn_proto.params.length; bool is_var_args = node->data.fn_proto.is_var_args; for (int arg_i = 0; arg_i < arg_count; arg_i += 1) { AstNode *param_decl = node->data.fn_proto.params.at(arg_i); assert(param_decl->type == NodeTypeParamDecl); const char *arg_name = buf_ptr(¶m_decl->data.param_decl.name); if (buf_len(¶m_decl->data.param_decl.name) > 0) { const char *noalias_str = param_decl->data.param_decl.is_noalias ? "noalias " : ""; fprintf(ar->f, "%s%s: ", noalias_str, arg_name); } render_node(ar, param_decl->data.param_decl.type); if (arg_i + 1 < arg_count || is_var_args) { fprintf(ar->f, ", "); } } if (is_var_args) { fprintf(ar->f, "..."); } fprintf(ar->f, ")"); AstNode *return_type_node = node->data.fn_proto.return_type; if (!is_node_void(return_type_node)) { fprintf(ar->f, " -> "); render_node(ar, return_type_node); } break; } case NodeTypeFnDef: if (node->data.fn_def.fn_proto->data.fn_proto.directives) { for (int i = 0; i < node->data.fn_def.fn_proto->data.fn_proto.directives->length; i += 1) { render_node(ar, node->data.fn_def.fn_proto->data.fn_proto.directives->at(i)); } } render_node(ar, node->data.fn_def.fn_proto); fprintf(ar->f, " "); render_node(ar, node->data.fn_def.body); break; case NodeTypeFnDecl: zig_panic("TODO"); case NodeTypeParamDecl: zig_panic("TODO"); case NodeTypeBlock: fprintf(ar->f, "{\n"); ar->indent += ar->indent_size; for (int i = 0; i < node->data.block.statements.length; i += 1) { AstNode *statement = node->data.block.statements.at(i); print_indent(ar); render_node(ar, statement); } ar->indent -= ar->indent_size; fprintf(ar->f, "\n"); print_indent(ar); fprintf(ar->f, "}"); break; case NodeTypeDirective: fprintf(ar->f, "#%s(", buf_ptr(&node->data.directive.name)); render_node(ar, node->data.directive.expr); fprintf(ar->f, ")\n"); break; case NodeTypeReturnExpr: zig_panic("TODO"); case NodeTypeDefer: zig_panic("TODO"); case NodeTypeVariableDeclaration: { const char *pub_str = visib_mod_string(node->data.variable_declaration.visib_mod); const char *extern_str = extern_string(node->data.variable_declaration.is_extern); const char *var_name = buf_ptr(&node->data.variable_declaration.symbol); const char *const_or_var = const_or_var_string(node->data.variable_declaration.is_const); fprintf(ar->f, "%s%s%s %s", pub_str, extern_str, const_or_var, var_name); if (node->data.variable_declaration.type) { fprintf(ar->f, ": "); render_node(ar, node->data.variable_declaration.type); } if (node->data.variable_declaration.expr) { fprintf(ar->f, " = "); render_node(ar, node->data.variable_declaration.expr); } break; } case NodeTypeTypeDecl: { const char *pub_str = visib_mod_string(node->data.type_decl.visib_mod); const char *var_name = buf_ptr(&node->data.type_decl.symbol); fprintf(ar->f, "%stype %s = ", pub_str, var_name); render_node(ar, node->data.type_decl.child_type); break; } case NodeTypeErrorValueDecl: zig_panic("TODO"); case NodeTypeBinOpExpr: fprintf(ar->f, "("); render_node(ar, node->data.bin_op_expr.op1); fprintf(ar->f, " %s ", bin_op_str(node->data.bin_op_expr.bin_op)); render_node(ar, node->data.bin_op_expr.op2); fprintf(ar->f, ")"); break; case NodeTypeUnwrapErrorExpr: zig_panic("TODO"); case NodeTypeNumberLiteral: switch (node->data.number_literal.kind) { case NumLitUInt: fprintf(ar->f, "%" PRIu64, node->data.number_literal.data.x_uint); break; case NumLitFloat: fprintf(ar->f, "%f", node->data.number_literal.data.x_float); break; } break; case NodeTypeStringLiteral: if (node->data.string_literal.c) { fprintf(ar->f, "c"); } fprintf(ar->f, "\"%s\"", buf_ptr(&node->data.string_literal.buf)); break; case NodeTypeCharLiteral: { uint8_t c = node->data.char_literal.value; if (is_printable(c)) { fprintf(ar->f, "'%c'", c); } else { fprintf(ar->f, "'\\x%x'", (int)c); } break; } case NodeTypeSymbol: { TypeTableEntry *override_type = node->data.symbol_expr.override_type_entry; if (override_type) { fprintf(ar->f, "%s", buf_ptr(&override_type->name)); } else { fprintf(ar->f, "%s", buf_ptr(&node->data.symbol_expr.symbol)); } } break; case NodeTypePrefixOpExpr: { PrefixOp op = node->data.prefix_op_expr.prefix_op; fprintf(ar->f, "%s", prefix_op_str(op)); render_node(ar, node->data.prefix_op_expr.primary_expr); break; } case NodeTypeFnCallExpr: if (node->data.fn_call_expr.is_builtin) { fprintf(ar->f, "@"); } fprintf(ar->f, "("); render_node(ar, node->data.fn_call_expr.fn_ref_expr); fprintf(ar->f, ")("); for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) { AstNode *param = node->data.fn_call_expr.params.at(i); if (i != 0) { fprintf(ar->f, ", "); } render_node(ar, param); } fprintf(ar->f, ")"); break; case NodeTypeArrayAccessExpr: zig_panic("TODO"); case NodeTypeSliceExpr: zig_panic("TODO"); case NodeTypeFieldAccessExpr: { AstNode *lhs = node->data.field_access_expr.struct_expr; Buf *rhs = &node->data.field_access_expr.field_name; render_node(ar, lhs); fprintf(ar->f, ".%s", buf_ptr(rhs)); break; } case NodeTypeImport: zig_panic("TODO"); case NodeTypeCImport: zig_panic("TODO"); case NodeTypeBoolLiteral: zig_panic("TODO"); case NodeTypeNullLiteral: zig_panic("TODO"); case NodeTypeUndefinedLiteral: zig_panic("TODO"); case NodeTypeIfBoolExpr: zig_panic("TODO"); case NodeTypeIfVarExpr: zig_panic("TODO"); case NodeTypeWhileExpr: zig_panic("TODO"); case NodeTypeForExpr: zig_panic("TODO"); case NodeTypeSwitchExpr: zig_panic("TODO"); case NodeTypeSwitchProng: zig_panic("TODO"); case NodeTypeSwitchRange: zig_panic("TODO"); case NodeTypeLabel: zig_panic("TODO"); case NodeTypeGoto: zig_panic("TODO"); case NodeTypeBreak: zig_panic("TODO"); case NodeTypeContinue: zig_panic("TODO"); case NodeTypeAsmExpr: zig_panic("TODO"); case NodeTypeStructDecl: { const char *struct_name = buf_ptr(&node->data.struct_decl.name); const char *pub_str = visib_mod_string(node->data.struct_decl.visib_mod); const char *container_str = container_string(node->data.struct_decl.kind); fprintf(ar->f, "%s%s %s {\n", pub_str, container_str, struct_name); ar->indent += ar->indent_size; for (int field_i = 0; field_i < node->data.struct_decl.fields.length; field_i += 1) { AstNode *field_node = node->data.struct_decl.fields.at(field_i); assert(field_node->type == NodeTypeStructField); const char *field_name = buf_ptr(&field_node->data.struct_field.name); print_indent(ar); fprintf(ar->f, "%s", field_name); if (!is_node_void(field_node->data.struct_field.type)) { fprintf(ar->f, ": "); render_node(ar, field_node->data.struct_field.type); } fprintf(ar->f, ",\n"); } ar->indent -= ar->indent_size; fprintf(ar->f, "}"); break; } case NodeTypeStructField: zig_panic("TODO"); case NodeTypeContainerInitExpr: fprintf(ar->f, "("); render_node(ar, node->data.container_init_expr.type); fprintf(ar->f, "){"); assert(node->data.container_init_expr.entries.length == 0); fprintf(ar->f, "}"); break; case NodeTypeStructValueField: zig_panic("TODO"); case NodeTypeArrayType: { fprintf(ar->f, "["); if (node->data.array_type.size) { render_node(ar, node->data.array_type.size); } fprintf(ar->f, "]"); if (node->data.array_type.is_const) { fprintf(ar->f, "const "); } render_node(ar, node->data.array_type.child_type); break; } case NodeTypeErrorType: fprintf(ar->f, "error"); break; case NodeTypeTypeLiteral: fprintf(ar->f, "type"); break; } }