220 return NULL; |
220 return NULL; |
221 } |
221 } |
222 return recipe; |
222 return recipe; |
223 } |
223 } |
224 |
224 |
|
225 #ifdef HAS_GETCOMMANDLINE |
|
226 /* |
|
227 Get rid of the path to talon from a commandline string on windows find the |
|
228 -c (if it's there) and step past it to after the quote on the first command: |
|
229 |
|
230 "g:\program files\talon\talon.exe" -c "gcc -c . . ." |
|
231 ^------ Returns a pointer to here |
|
232 |
|
233 Take care of the possibilty that there might be spaces in the command |
|
234 if it is quoted. |
|
235 |
|
236 A state-machine is flexible but not all that easy to write. Should investigate |
|
237 the possiblity of using the Ragel state machine generator perhaps. |
|
238 |
|
239 */ |
|
240 #define CH_START 0 |
|
241 #define CH_PRE 1 |
|
242 #define CH_EXQUOTE 2 |
|
243 #define CH_INQUOTE 3 |
|
244 #define CH_POST 4 |
|
245 #define CH_MINUS 5 |
|
246 #define CH_C 6 |
|
247 #define CH_PRECOMMAND 7 |
|
248 #define CH_COMMAND 8 |
|
249 #define CH_ERR 9 |
|
250 |
|
251 char * chompCommand(char command[]) |
|
252 { |
|
253 char *result = command; |
|
254 int state = CH_START; |
|
255 |
|
256 while (state != CH_COMMAND && state != CH_ERR) |
|
257 { |
|
258 DEBUG(("startstate: %d, char %c ",state, *result)); |
|
259 switch (*result) |
|
260 { |
|
261 case ' ': |
|
262 switch (state) |
|
263 { |
|
264 case CH_START: |
|
265 case CH_PRE: |
|
266 state = CH_PRE; |
|
267 break; |
|
268 case CH_EXQUOTE: |
|
269 state = CH_POST; |
|
270 break; |
|
271 case CH_INQUOTE: |
|
272 break; |
|
273 case CH_POST: |
|
274 break; |
|
275 case CH_MINUS: |
|
276 state = CH_C; |
|
277 break; |
|
278 case CH_C: |
|
279 state = CH_PRECOMMAND; |
|
280 break; |
|
281 case CH_PRECOMMAND: |
|
282 break; |
|
283 default: |
|
284 state = CH_ERR; |
|
285 break; |
|
286 } |
|
287 break; |
|
288 case 'c': |
|
289 switch (state) |
|
290 { |
|
291 case CH_START: |
|
292 case CH_PRE: |
|
293 state = CH_EXQUOTE; |
|
294 break; |
|
295 case CH_EXQUOTE: |
|
296 case CH_INQUOTE: |
|
297 break; |
|
298 case CH_POST: |
|
299 state = CH_ERR; |
|
300 break; |
|
301 case CH_MINUS: |
|
302 state = CH_C; |
|
303 break; |
|
304 case CH_C: |
|
305 case CH_PRECOMMAND: |
|
306 default: |
|
307 state = CH_ERR; |
|
308 break; |
|
309 } |
|
310 break; |
|
311 case '-': |
|
312 switch (state) |
|
313 { |
|
314 case CH_START: |
|
315 case CH_PRE: |
|
316 state = CH_EXQUOTE; |
|
317 break; |
|
318 case CH_EXQUOTE: |
|
319 case CH_INQUOTE: |
|
320 break; |
|
321 case CH_POST: |
|
322 state = CH_MINUS; |
|
323 break; |
|
324 case CH_MINUS: |
|
325 case CH_C: |
|
326 case CH_PRECOMMAND: |
|
327 default: |
|
328 state = CH_ERR; |
|
329 break; |
|
330 } |
|
331 break; |
|
332 case '"': |
|
333 switch (state) |
|
334 { |
|
335 case CH_START: |
|
336 case CH_PRE: |
|
337 case CH_EXQUOTE: |
|
338 state = CH_INQUOTE; |
|
339 break; |
|
340 case CH_INQUOTE: |
|
341 state = CH_EXQUOTE; |
|
342 break; |
|
343 case CH_POST: |
|
344 case CH_MINUS: |
|
345 case CH_C: |
|
346 state = CH_ERR; |
|
347 break; |
|
348 case CH_PRECOMMAND: |
|
349 state = CH_COMMAND; |
|
350 break; |
|
351 default: |
|
352 state = CH_ERR; |
|
353 break; |
|
354 } |
|
355 |
|
356 break; |
|
357 default: |
|
358 switch (state) |
|
359 { |
|
360 case CH_START: |
|
361 case CH_PRE: |
|
362 state = CH_EXQUOTE; |
|
363 break; |
|
364 case CH_INQUOTE: |
|
365 case CH_EXQUOTE: |
|
366 break; |
|
367 default: |
|
368 state = CH_ERR; |
|
369 break; |
|
370 } |
|
371 break; |
|
372 } |
|
373 DEBUG((stderr,"endstate: %d\n",state)); |
|
374 result ++; |
|
375 |
|
376 } |
|
377 |
|
378 if (state == CH_ERR) |
|
379 return NULL; |
|
380 |
|
381 return result; |
|
382 } |
|
383 #endif |
|
384 |
225 int main(int argc, char *argv[]) |
385 int main(int argc, char *argv[]) |
226 { |
386 { |
227 /* find the argument to -c then strip the talon related front section */ |
387 /* find the argument to -c then strip the talon related front section */ |
228 |
388 |
229 char *recipe = NULL; |
389 char *recipe = NULL; |
230 int talon_returncode = 0; |
390 int talon_returncode = 0; |
231 |
391 |
232 #ifdef HAS_GETCOMMANDLINE |
392 #ifdef HAS_GETCOMMANDLINE |
233 char *commandline= GetCommandLine(); |
393 char *commandline= GetCommandLine(); |
234 DEBUG(("talon: commandline: %s\n", commandline)); |
|
235 /* |
394 /* |
236 * The command line should be either, |
395 * The command line should be either, |
237 * talon -c "some shell commands" |
396 * talon -c "some shell commands" |
238 * or |
397 * or |
239 * talon shell_script_file |
398 * talon shell_script_file |
240 * |
399 * |
241 * talon could be an absolute path and may have a .exe extension. |
400 * talon could be an absolute path and may have a .exe extension. |
242 */ |
401 */ |
243 recipe = strstr(commandline, "-c"); |
402 |
|
403 |
|
404 recipe = chompCommand(commandline); |
|
405 if (recipe == NULL) |
|
406 { |
|
407 error("talon: error: unable to locate argument start in '%s'\n", commandline); |
|
408 return 1; |
|
409 } |
244 if (recipe) |
410 if (recipe) |
245 { |
411 { |
246 /* there was a -c so extract the quoted commands */ |
412 /* there was a -c so extract the quoted commands */ |
247 |
413 |
248 while (*recipe != '"' && *recipe != '\0') |
|
249 recipe++; |
|
250 |
|
251 if (*recipe != '"') /* we found -c but no following quote */ |
|
252 { |
|
253 error("talon: error: unquoted recipe in shell call '%s'\n", commandline); |
|
254 return 1; |
|
255 } |
|
256 recipe++; |
|
257 |
|
258 int recipelen = strlen(recipe); |
414 int recipelen = strlen(recipe); |
259 if (recipelen > 0 && recipe[recipelen - 1] == '"') |
415 if (recipelen > 0 && recipe[recipelen - 1] == '"') |
260 recipe[recipelen - 1] = '\0'; /* remove trailing quote */ |
416 recipe[recipelen - 1] = '\0'; /* remove trailing quote */ |
261 } |
417 } |
262 else |
418 else |