Rev 6536 | Rev 9952 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 6536 | Rev 6664 | ||
---|---|---|---|
1 | /* |
1 | /* |
2 | * crtdll.c |
2 | * crtdll.c |
3 | * This file has no copyright assigned and is placed in the Public Domain. |
3 | * This file has no copyright assigned and is placed in the Public Domain. |
4 | * This file is a part of the mingw-runtime package. |
4 | * This file is a part of the mingw-runtime package. |
5 | * No warranty is given; refer to the file DISCLAIMER within the package. |
5 | * No warranty is given; refer to the file DISCLAIMER within the package. |
6 | * |
6 | * |
7 | * Source code for the shared libc startup proceedures. This code is compiled |
7 | * Source code for the shared libc startup proceedures. This code is compiled |
8 | * to make libc.dll, which should be located in the library path. |
8 | * to make libc.dll, which should be located in the library path. |
9 | * |
9 | * |
10 | */ |
10 | */ |
11 | 11 | ||
12 | #include <_ansi.h> |
12 | #include <_ansi.h> |
13 | #include |
13 | #include |
14 | #include |
14 | #include |
15 | #include |
15 | #include |
16 | #include |
16 | #include |
17 | #include |
17 | #include |
18 | #include |
18 | #include |
19 | #include |
19 | #include |
20 | #include |
20 | #include |
21 | 21 | ||
22 | struct app_hdr |
22 | struct app_hdr |
23 | { |
23 | { |
24 | char banner[8]; |
24 | char banner[8]; |
25 | int version; |
25 | int version; |
26 | int start; |
26 | int start; |
27 | int iend; |
27 | int iend; |
28 | int memsize; |
28 | int memsize; |
29 | int stacktop; |
29 | int stacktop; |
30 | char *cmdline; |
30 | char *cmdline; |
31 | char *path; |
31 | char *path; |
32 | int __subsystem__; |
32 | int __subsystem__; |
33 | void *__idata_start; |
33 | void *__idata_start; |
34 | void *__idata_end; |
34 | void *__idata_end; |
35 | int (*main)(int argc, char **argv, char **envp); |
35 | int (*main)(int argc, char **argv, char **envp); |
36 | }; |
36 | }; |
37 | 37 | ||
38 | extern void _pei386_runtime_relocator (void); |
38 | extern void _pei386_runtime_relocator (void); |
39 | extern void init_loader(void *libc_image); |
39 | extern void init_loader(void *libc_image); |
40 | extern void init_reent(void); |
40 | extern void init_global_reent(void); |
41 | extern void init_stdio(void); |
41 | extern void init_stdio(void); |
42 | 42 | ||
43 | extern void __init_conio(void); |
43 | extern void __init_conio(void); |
44 | extern void __fini_conio(void); |
44 | extern void __fini_conio(void); |
45 | extern int link_app(void); |
45 | extern int link_app(void); |
46 | extern void* get_entry_point(void *raw); |
46 | extern void* get_entry_point(void *raw); |
47 | 47 | ||
48 | extern void tls_init(void); |
48 | extern void tls_init(void); |
49 | 49 | ||
50 | char* __appenv; |
50 | char* __appenv; |
51 | int __appenv_size; |
51 | int __appenv_size; |
52 | 52 | ||
53 | 53 | ||
54 | char * __libc_getenv(const char *name) |
54 | char * __libc_getenv(const char *name) |
55 | { |
55 | { |
56 | return NULL; |
56 | return NULL; |
57 | } |
57 | } |
58 | 58 | ||
59 | static int split_cmdline(char *cmdline, char **argv) |
59 | static int split_cmdline(char *cmdline, char **argv) |
60 | { |
60 | { |
61 | enum quote_state |
61 | enum quote_state |
62 | { |
62 | { |
63 | QUOTE_NONE, /* no " active in current parm */ |
63 | QUOTE_NONE, /* no " active in current parm */ |
64 | QUOTE_DELIMITER, /* " was first char and must be last */ |
64 | QUOTE_DELIMITER, /* " was first char and must be last */ |
65 | QUOTE_STARTED /* " was seen, look for a match */ |
65 | QUOTE_STARTED /* " was seen, look for a match */ |
66 | }; |
66 | }; |
67 | 67 | ||
68 | enum quote_state state; |
68 | enum quote_state state; |
69 | unsigned int argc; |
69 | unsigned int argc; |
70 | char *p = cmdline; |
70 | char *p = cmdline; |
71 | char *new_arg, *start; |
71 | char *new_arg, *start; |
72 | 72 | ||
73 | argc = 0; |
73 | argc = 0; |
74 | 74 | ||
75 | for(;;) |
75 | for(;;) |
76 | { |
76 | { |
77 | /* skip over spaces and tabs */ |
77 | /* skip over spaces and tabs */ |
78 | if ( *p ) |
78 | if ( *p ) |
79 | { |
79 | { |
80 | while (*p == ' ' || *p == '\t') |
80 | while (*p == ' ' || *p == '\t') |
81 | ++p; |
81 | ++p; |
82 | } |
82 | } |
83 | 83 | ||
84 | if (*p == '\0') |
84 | if (*p == '\0') |
85 | break; |
85 | break; |
86 | 86 | ||
87 | state = QUOTE_NONE; |
87 | state = QUOTE_NONE; |
88 | if( *p == '\"' ) |
88 | if( *p == '\"' ) |
89 | { |
89 | { |
90 | p++; |
90 | p++; |
91 | state = QUOTE_DELIMITER; |
91 | state = QUOTE_DELIMITER; |
92 | } |
92 | } |
93 | new_arg = start = p; |
93 | new_arg = start = p; |
94 | for (;;) |
94 | for (;;) |
95 | { |
95 | { |
96 | if( *p == '\"' ) |
96 | if( *p == '\"' ) |
97 | { |
97 | { |
98 | p++; |
98 | p++; |
99 | if( state == QUOTE_NONE ) |
99 | if( state == QUOTE_NONE ) |
100 | { |
100 | { |
101 | state = QUOTE_STARTED; |
101 | state = QUOTE_STARTED; |
102 | } |
102 | } |
103 | else |
103 | else |
104 | { |
104 | { |
105 | state = QUOTE_NONE; |
105 | state = QUOTE_NONE; |
106 | } |
106 | } |
107 | continue; |
107 | continue; |
108 | } |
108 | } |
109 | 109 | ||
110 | if( *p == ' ' || *p == '\t' ) |
110 | if( *p == ' ' || *p == '\t' ) |
111 | { |
111 | { |
112 | if( state == QUOTE_NONE ) |
112 | if( state == QUOTE_NONE ) |
113 | { |
113 | { |
114 | break; |
114 | break; |
115 | } |
115 | } |
116 | } |
116 | } |
117 | 117 | ||
118 | if( *p == '\0' ) |
118 | if( *p == '\0' ) |
119 | break; |
119 | break; |
120 | 120 | ||
121 | if( *p == '\\' ) |
121 | if( *p == '\\' ) |
122 | { |
122 | { |
123 | if( p[1] == '\"' ) |
123 | if( p[1] == '\"' ) |
124 | { |
124 | { |
125 | ++p; |
125 | ++p; |
126 | if( p[-2] == '\\' ) |
126 | if( p[-2] == '\\' ) |
127 | { |
127 | { |
128 | continue; |
128 | continue; |
129 | } |
129 | } |
130 | } |
130 | } |
131 | } |
131 | } |
132 | if( argv ) |
132 | if( argv ) |
133 | { |
133 | { |
134 | *(new_arg++) = *p; |
134 | *(new_arg++) = *p; |
135 | } |
135 | } |
136 | ++p; |
136 | ++p; |
137 | }; |
137 | }; |
138 | 138 | ||
139 | if( argv ) |
139 | if( argv ) |
140 | { |
140 | { |
141 | argv[ argc ] = start; |
141 | argv[ argc ] = start; |
142 | ++argc; |
142 | ++argc; |
143 | 143 | ||
144 | /* |
144 | /* |
145 | The *new = '\0' is req'd in case there was a \" to " |
145 | The *new = '\0' is req'd in case there was a \" to " |
146 | translation. It must be after the *p check against |
146 | translation. It must be after the *p check against |
147 | '\0' because new and p could point to the same char |
147 | '\0' because new and p could point to the same char |
148 | in which case the scan would be terminated too soon. |
148 | in which case the scan would be terminated too soon. |
149 | */ |
149 | */ |
150 | 150 | ||
151 | if( *p == '\0' ) |
151 | if( *p == '\0' ) |
152 | { |
152 | { |
153 | *new_arg = '\0'; |
153 | *new_arg = '\0'; |
154 | break; |
154 | break; |
155 | } |
155 | } |
156 | *new_arg = '\0'; |
156 | *new_arg = '\0'; |
157 | ++p; |
157 | ++p; |
158 | } |
158 | } |
159 | else |
159 | else |
160 | { |
160 | { |
161 | ++argc; |
161 | ++argc; |
162 | if( *p == '\0' ) |
162 | if( *p == '\0' ) |
163 | { |
163 | { |
164 | break; |
164 | break; |
165 | } |
165 | } |
166 | ++p; |
166 | ++p; |
167 | } |
167 | } |
168 | } |
168 | } |
169 | 169 | ||
170 | return argc; |
170 | return argc; |
171 | }; |
171 | }; |
172 | 172 | ||
173 | __attribute__((noreturn)) |
173 | __attribute__((noreturn)) |
174 | void libc_crt_startup (void *libc_base) |
174 | void libc_crt_startup (void *libc_base) |
175 | { |
175 | { |
176 | struct app_hdr *header = NULL; |
176 | struct app_hdr *header = NULL; |
177 | int retval = 0; |
177 | int retval = 0; |
178 | 178 | ||
179 | char **argv; |
179 | char **argv; |
180 | int argc; |
180 | int argc; |
181 | 181 | ||
182 | _pei386_runtime_relocator(); |
182 | _pei386_runtime_relocator(); |
183 | 183 | ||
184 | tls_init(); |
184 | tls_init(); |
185 | init_reent(); |
185 | init_global_reent(); |
186 | init_stdio(); |
186 | init_stdio(); |
187 | 187 | ||
188 | if(header->__subsystem__ == 3) |
188 | if(header->__subsystem__ == 3) |
189 | __init_conio(); |
189 | __init_conio(); |
190 | 190 | ||
191 | // __appenv = load_file("/sys/system.env", &__appenv_size); |
191 | // __appenv = load_file("/sys/system.env", &__appenv_size); |
192 | 192 | ||
193 | init_loader(libc_base); |
193 | init_loader(libc_base); |
194 | 194 | ||
195 | if( link_app() == 0) |
195 | if( link_app() == 0) |
196 | goto done; |
196 | goto done; |
197 | 197 | ||
198 | if( header->cmdline[0] != 0) |
198 | if( header->cmdline[0] != 0) |
199 | { |
199 | { |
200 | argc = split_cmdline(header->cmdline, NULL) + 1; |
200 | argc = split_cmdline(header->cmdline, NULL) + 1; |
201 | argv = alloca((argc+1)*sizeof(char*)); |
201 | argv = alloca((argc+1)*sizeof(char*)); |
202 | argv[0] = header->path; |
202 | argv[0] = header->path; |
203 | 203 | ||
204 | split_cmdline(header->cmdline, argv + 1); |
204 | split_cmdline(header->cmdline, argv + 1); |
205 | } |
205 | } |
206 | else |
206 | else |
207 | { |
207 | { |
208 | argc = 1; |
208 | argc = 1; |
209 | argv = alloca((argc+1)*sizeof(char*)); |
209 | argv = alloca((argc+1)*sizeof(char*)); |
210 | argv[0] = header->path; |
210 | argv[0] = header->path; |
211 | } |
211 | } |
212 | argv[argc] = NULL; |
212 | argv[argc] = NULL; |
213 | 213 | ||
214 | retval = header->main(argc, argv, NULL); |
214 | retval = header->main(argc, argv, NULL); |
215 | done: |
215 | done: |
216 | if(header->__subsystem__ == 3) |
216 | if(header->__subsystem__ == 3) |
217 | __fini_conio(); |
217 | __fini_conio(); |
218 | 218 | ||
219 | exit (retval); |
219 | exit (retval); |
220 | } |
220 | } |