+#if __DYNAMIC__
+struct ProgramVars
+{
+ void* mh;
+ int* NXArgcPtr;
+ char*** NXArgvPtr;
+ char*** environPtr;
+ char** __prognamePtr;
+};
+
+
+#define SUPPORT_PRE_GM_10_5_EXECUTABLES (__ppc__ || __i386__)
+
+
+/*
+ * dyld calls libSystem_initializer() and passes it a ProgramVars struct
+ * containing pointers to the main executable's NXArg* global variables.
+ * libSystem_initializer() calls _libc_initializer() which calls
+ * _program_vars_init() passing the ProgramVars parameter.
+ */
+void __attribute__((visibility("hidden")))
+_program_vars_init(const struct ProgramVars* vars) {
+#if SUPPORT_PRE_GM_10_5_EXECUTABLES
+ // to support transitional 10.5 main executables that don't have extended __dyld section and instead call _NSSetProgramVars,
+ // don't overwrite values set by _NSSetProgramVars()
+ if ( NXArgv_pointer != NULL )
+ return;
+#endif
+ NXArgv_pointer = vars->NXArgvPtr;
+ NXArgc_pointer = vars->NXArgcPtr;
+ environ_pointer = vars->environPtr;
+ __progname_pointer = vars->__prognamePtr;
+ _mh_execute_header_pointer = vars->mh;
+}
+
+#if SUPPORT_PRE_GM_10_5_EXECUTABLES
+/*
+ * This is only called by main executables built with pre 10-5 GM crt1.10.5.o. In those programs,
+ * there is no extended __dyld section, dyld cannot tell _program_vars_init() where the real program
+ * variables are, so they get temp values and are set for real here.
+ */
+void _NSSetProgramVars(int* crt_argc, char*** crt_argv, char*** crt_environ, struct mach_header* crt_mh, char** crt_progname) {
+ NXArgv_pointer = crt_argv;
+ NXArgc_pointer = crt_argc;
+ environ_pointer = crt_environ;
+ __progname_pointer = crt_progname;
+ _mh_execute_header_pointer = crt_mh;
+}
+#endif
+#endif /* __DYNAMIC__ */
+
+#if __ppc__