Rev 6536 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4349 | Serge | 1 | /* |
2 | * crt1.c |
||
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. |
||
5 | * No warranty is given; refer to the file DISCLAIMER within the package. |
||
6 | * |
||
7 | * Source code for the startup proceedures used by all programs. This code |
||
8 | * is compiled to make crt1.o, which should be located in the library path. |
||
9 | * |
||
10 | */ |
||
11 | |||
12 | /* Hide the declaration of _fmode with dllimport attribute in stdlib.h to |
||
13 | avoid problems with older GCC. */ |
||
14 | |||
15 | #include |
||
16 | |||
6068 | serge | 17 | struct app_hdr |
18 | { |
||
19 | char banner[8]; |
||
20 | int version; |
||
21 | int start; |
||
22 | int iend; |
||
23 | int memsize; |
||
24 | int stacktop; |
||
25 | char *cmdline; |
||
26 | char *path; |
||
6074 | serge | 27 | int __subsystem__; |
6068 | serge | 28 | }; |
4349 | Serge | 29 | |
6664 | serge | 30 | extern void init_global_reent(); |
6536 | serge | 31 | extern void init_stdio(); |
32 | extern void __init_conio(); |
||
33 | extern void __fini_conio(); |
||
6074 | serge | 34 | |
6536 | serge | 35 | extern void tls_init(void); |
6068 | serge | 36 | extern int main (int, char **, char **); |
4349 | Serge | 37 | |
38 | /* NOTE: The code for initializing the _argv, _argc, and environ variables |
||
39 | * has been moved to a separate .c file which is included in both |
||
40 | * crt1.c and dllcrt1.c. This means changes in the code don't have to |
||
41 | * be manually synchronized, but it does lead to this not-generally- |
||
42 | * a-good-idea use of include. */ |
||
43 | |||
6068 | serge | 44 | char* __appenv; |
45 | int __appenv_size; |
||
4349 | Serge | 46 | |
6068 | serge | 47 | char * __libc_getenv(const char *name) |
48 | { |
||
49 | return NULL; |
||
50 | } |
||
4349 | Serge | 51 | |
6068 | serge | 52 | static int split_cmdline(char *cmdline, char **argv) |
53 | { |
||
54 | enum quote_state |
||
55 | { |
||
56 | QUOTE_NONE, /* no " active in current parm */ |
||
57 | QUOTE_DELIMITER, /* " was first char and must be last */ |
||
58 | QUOTE_STARTED /* " was seen, look for a match */ |
||
59 | }; |
||
4349 | Serge | 60 | |
6068 | serge | 61 | enum quote_state state; |
62 | unsigned int argc; |
||
63 | char *p = cmdline; |
||
64 | char *new_arg, *start; |
||
4349 | Serge | 65 | |
6068 | serge | 66 | argc = 0; |
4349 | Serge | 67 | |
6068 | serge | 68 | for(;;) |
69 | { |
||
70 | /* skip over spaces and tabs */ |
||
71 | if ( *p ) |
||
72 | { |
||
73 | while (*p == ' ' || *p == '\t') |
||
74 | ++p; |
||
75 | } |
||
4349 | Serge | 76 | |
6068 | serge | 77 | if (*p == '\0') |
78 | break; |
||
4349 | Serge | 79 | |
6068 | serge | 80 | state = QUOTE_NONE; |
81 | if( *p == '\"' ) |
||
82 | { |
||
83 | p++; |
||
84 | state = QUOTE_DELIMITER; |
||
85 | } |
||
86 | new_arg = start = p; |
||
87 | for (;;) |
||
88 | { |
||
89 | if( *p == '\"' ) |
||
90 | { |
||
91 | p++; |
||
92 | if( state == QUOTE_NONE ) |
||
93 | { |
||
94 | state = QUOTE_STARTED; |
||
95 | } |
||
96 | else |
||
97 | { |
||
98 | state = QUOTE_NONE; |
||
99 | } |
||
100 | continue; |
||
101 | } |
||
4349 | Serge | 102 | |
6068 | serge | 103 | if( *p == ' ' || *p == '\t' ) |
104 | { |
||
105 | if( state == QUOTE_NONE ) |
||
106 | { |
||
107 | break; |
||
108 | } |
||
109 | } |
||
4349 | Serge | 110 | |
6068 | serge | 111 | if( *p == '\0' ) |
112 | break; |
||
4349 | Serge | 113 | |
6068 | serge | 114 | if( *p == '\\' ) |
115 | { |
||
116 | if( p[1] == '\"' ) |
||
117 | { |
||
118 | ++p; |
||
119 | if( p[-2] == '\\' ) |
||
120 | { |
||
121 | continue; |
||
122 | } |
||
123 | } |
||
124 | } |
||
125 | if( argv ) |
||
126 | { |
||
127 | *(new_arg++) = *p; |
||
128 | } |
||
129 | ++p; |
||
130 | }; |
||
131 | |||
132 | if( argv ) |
||
133 | { |
||
134 | argv[ argc ] = start; |
||
135 | ++argc; |
||
136 | |||
137 | /* |
||
138 | The *new = '\0' is req'd in case there was a \" to " |
||
139 | translation. It must be after the *p check against |
||
140 | '\0' because new and p could point to the same char |
||
141 | in which case the scan would be terminated too soon. |
||
142 | */ |
||
143 | |||
144 | if( *p == '\0' ) |
||
145 | { |
||
146 | *new_arg = '\0'; |
||
147 | break; |
||
148 | } |
||
149 | *new_arg = '\0'; |
||
150 | ++p; |
||
151 | } |
||
152 | else |
||
153 | { |
||
154 | ++argc; |
||
155 | if( *p == '\0' ) |
||
156 | { |
||
157 | break; |
||
158 | } |
||
159 | ++p; |
||
160 | } |
||
4349 | Serge | 161 | } |
162 | |||
6068 | serge | 163 | return argc; |
164 | }; |
||
165 | |||
4349 | Serge | 166 | void __attribute__((noreturn)) |
6536 | serge | 167 | __libc_init (void) |
4349 | Serge | 168 | { |
6068 | serge | 169 | struct app_hdr *header = NULL; |
170 | int retval = 0; |
||
4349 | Serge | 171 | |
6068 | serge | 172 | char **argv; |
173 | int argc; |
||
4349 | Serge | 174 | |
6536 | serge | 175 | tls_init(); |
6664 | serge | 176 | init_global_reent(); |
6068 | serge | 177 | init_stdio(); |
4349 | Serge | 178 | |
6074 | serge | 179 | if(header->__subsystem__ == 3) |
180 | __init_conio(); |
||
4349 | Serge | 181 | |
6068 | serge | 182 | if( header->cmdline[0] != 0) |
183 | { |
||
184 | argc = split_cmdline(header->cmdline, NULL) + 1; |
||
185 | argv = alloca((argc+1)*sizeof(char*)); |
||
186 | argv[0] = header->path; |
||
4349 | Serge | 187 | |
6068 | serge | 188 | split_cmdline(header->cmdline, argv + 1); |
189 | } |
||
190 | else |
||
4349 | Serge | 191 | { |
6068 | serge | 192 | argc = 1; |
193 | argv = alloca((argc+1)*sizeof(char*)); |
||
194 | argv[0] = header->path; |
||
195 | } |
||
196 | argv[argc] = NULL; |
||
4349 | Serge | 197 | |
6068 | serge | 198 | retval = main(argc, argv, NULL); |
199 | done: |
||
6074 | serge | 200 | if(header->__subsystem__ == 3) |
201 | __fini_conio(); |
||
202 | |||
6068 | serge | 203 | exit (retval); |
4349 | Serge | 204 | } |
205 |