25 |
#include <grub/partition.h> |
#include <grub/partition.h> |
26 |
#include <grub/disk.h> |
#include <grub/disk.h> |
27 |
#include <grub/file.h> |
#include <grub/file.h> |
28 |
|
#include <grub/parser.h> |
29 |
|
|
30 |
/* The current word. */ |
/* The current word. */ |
31 |
static char *current_word; |
static char *current_word; |
42 |
/* The callback function to print items. */ |
/* The callback function to print items. */ |
43 |
static void (*print_func) (const char *, grub_completion_type_t, int); |
static void (*print_func) (const char *, grub_completion_type_t, int); |
44 |
|
|
45 |
|
/* The state the command line is in. */ |
46 |
|
static grub_parser_state_t cmdline_state; |
47 |
|
|
48 |
|
|
49 |
/* Add a string to the list of possible completions. COMPLETION is the |
/* Add a string to the list of possible completions. COMPLETION is the |
128 |
{ |
{ |
129 |
if (! dir) |
if (! dir) |
130 |
{ |
{ |
131 |
if (add_completion (filename, " ", GRUB_COMPLETION_TYPE_FILE)) |
const char *prefix; |
132 |
|
if (cmdline_state == GRUB_PARSER_STATE_DQUOTE) |
133 |
|
prefix = "\" "; |
134 |
|
else if (cmdline_state == GRUB_PARSER_STATE_QUOTE) |
135 |
|
prefix = "\' "; |
136 |
|
else |
137 |
|
prefix = " "; |
138 |
|
|
139 |
|
if (add_completion (filename, prefix, GRUB_COMPLETION_TYPE_FILE)) |
140 |
return 1; |
return 1; |
141 |
} |
} |
142 |
else |
else |
369 |
return 0; |
return 0; |
370 |
} |
} |
371 |
|
|
372 |
|
|
373 |
|
static grub_parser_state_t |
374 |
|
get_state (const char *cmdline) |
375 |
|
{ |
376 |
|
grub_parser_state_t state = GRUB_PARSER_STATE_TEXT; |
377 |
|
char use; |
378 |
|
|
379 |
|
while (*cmdline) |
380 |
|
state = grub_parser_cmdline_state (state, *(cmdline++), &use); |
381 |
|
return state; |
382 |
|
} |
383 |
|
|
384 |
|
|
385 |
/* Try to complete the string in BUF. Return the characters that |
/* Try to complete the string in BUF. Return the characters that |
386 |
should be added to the string. This command outputs the possible |
should be added to the string. This command outputs the possible |
387 |
completions by calling HOOK, in that case set RESTORE to 1 so the |
completions by calling HOOK, in that case set RESTORE to 1 so the |
390 |
grub_normal_do_completion (char *buf, int *restore, |
grub_normal_do_completion (char *buf, int *restore, |
391 |
void (*hook) (const char *, grub_completion_type_t, int)) |
void (*hook) (const char *, grub_completion_type_t, int)) |
392 |
{ |
{ |
393 |
char *first_word; |
int argc; |
394 |
|
char **argv; |
395 |
|
|
396 |
/* Initialize variables. */ |
/* Initialize variables. */ |
397 |
match = 0; |
match = 0; |
400 |
print_func = hook; |
print_func = hook; |
401 |
|
|
402 |
*restore = 1; |
*restore = 1; |
403 |
|
|
404 |
/* Find the first word. */ |
if (grub_parser_split_cmdline (buf, 0, &argc, &argv)) |
405 |
for (first_word = buf; *first_word == ' '; first_word++) |
return 0; |
406 |
; |
|
407 |
|
current_word = argv[argc]; |
408 |
/* Find the delimeter of the current word. */ |
|
409 |
for (current_word = first_word + grub_strlen (first_word); |
/* Determine the state the command line is in, depending on the |
410 |
current_word > first_word; |
state, it can be determined how to complete. */ |
411 |
current_word--) |
cmdline_state = get_state (buf); |
412 |
if (*current_word == ' ' || *current_word == '=') |
|
413 |
break; |
if (argc == 0) |
|
|
|
|
if (current_word == first_word) |
|
414 |
{ |
{ |
415 |
/* Complete a command. */ |
/* Complete a command. */ |
416 |
if (grub_iterate_commands (iterate_command)) |
if (grub_iterate_commands (iterate_command)) |
417 |
goto fail; |
goto fail; |
418 |
} |
} |
419 |
else |
else if (*current_word == '-') |
420 |
{ |
{ |
421 |
current_word++; |
if (complete_arguments (buf)) |
422 |
|
goto fail; |
423 |
if (*current_word == '-') |
} |
424 |
{ |
else if (*current_word == '(' && ! grub_strchr (current_word, ')')) |
425 |
if (complete_arguments (buf)) |
{ |
426 |
goto fail; |
/* Complete a device. */ |
427 |
} |
if (complete_device ()) |
|
else if (*current_word == '(' && ! grub_strchr (current_word, ')')) |
|
|
{ |
|
|
/* Complete a device. */ |
|
|
if (complete_device ()) |
|
|
goto fail; |
|
|
} |
|
|
else |
|
|
{ |
|
|
/* Complete a file. */ |
|
|
if (complete_file ()) |
|
428 |
goto fail; |
goto fail; |
429 |
} |
} |
430 |
|
else |
431 |
|
{ |
432 |
|
/* Complete a file. */ |
433 |
|
if (complete_file ()) |
434 |
|
goto fail; |
435 |
} |
} |
436 |
|
|
437 |
/* If more than one match is found those matches will be printed and |
/* If more than one match is found those matches will be printed and |
445 |
if (match) |
if (match) |
446 |
{ |
{ |
447 |
char *ret; |
char *ret; |
448 |
|
char *escstr; |
449 |
|
char *newstr; |
450 |
int current_len; |
int current_len; |
451 |
int match_len; |
int match_len; |
452 |
|
int spaces = 0; |
453 |
|
|
454 |
current_len = grub_strlen (current_word); |
current_len = grub_strlen (current_word); |
455 |
match_len = grub_strlen (match); |
match_len = grub_strlen (match); |
456 |
ret = grub_malloc (match_len - current_len + grub_strlen (suffix) + 1); |
|
457 |
grub_strcpy (ret, match + current_len); |
/* Count the number of spaces that have to be escaped. XXX: |
458 |
|
More than just spaces have to be escaped. */ |
459 |
|
for (escstr = match + current_len; *escstr; escstr++) |
460 |
|
if (*escstr == ' ') |
461 |
|
spaces++; |
462 |
|
|
463 |
|
ret = grub_malloc (match_len - current_len + grub_strlen (suffix) + spaces + 1); |
464 |
|
newstr = ret; |
465 |
|
for (escstr = match + current_len; *escstr; escstr++) |
466 |
|
{ |
467 |
|
if (*escstr == ' ' && cmdline_state != GRUB_PARSER_STATE_QUOTE |
468 |
|
&& cmdline_state != GRUB_PARSER_STATE_QUOTE) |
469 |
|
*(newstr++) = '\\'; |
470 |
|
*(newstr++) = *escstr; |
471 |
|
} |
472 |
|
*newstr = '\0'; |
473 |
|
|
474 |
if (num_found == 1) |
if (num_found == 1) |
475 |
grub_strcat (ret, suffix); |
grub_strcat (ret, suffix); |
476 |
|
|