1/* complete.c, created from complete.def. */ 2#line 23 "complete.def" 3 4#line 34 "complete.def" 5 6#include <config.h> 7 8#include <stdio.h> 9 10#include "../bashtypes.h" 11 12#if defined (HAVE_UNISTD_H) 13# include <unistd.h> 14#endif 15 16#include "../bashansi.h" 17#include "../bashintl.h" 18 19#include "../shell.h" 20#include "../builtins.h" 21#include "../pcomplete.h" 22#include "../bashline.h" 23 24#include "common.h" 25#include "bashgetopt.h" 26 27#include <readline/readline.h> 28 29#define STRDUP(x) ((x) ? savestring (x) : (char *)NULL) 30 31static int find_compact __P((char *)); 32static int find_compopt __P((char *)); 33 34static int build_actions __P((WORD_LIST *, int *, int *, unsigned long *, unsigned long *)); 35 36static int remove_cmd_completions __P((WORD_LIST *)); 37 38static int print_one_completion __P((char *, COMPSPEC *)); 39static int print_compitem __P((BUCKET_CONTENTS *)); 40static void print_all_completions __P((void)); 41static int print_cmd_completions __P((WORD_LIST *)); 42 43static char *Garg, *Warg, *Parg, *Sarg, *Xarg, *Farg, *Carg; 44 45static struct _compacts { 46 char *actname; 47 int actflag; 48 int actopt; 49} compacts[] = { 50 { "alias", CA_ALIAS, 'a' }, 51 { "arrayvar", CA_ARRAYVAR, 0 }, 52 { "binding", CA_BINDING, 0 }, 53 { "builtin", CA_BUILTIN, 'b' }, 54 { "command", CA_COMMAND, 'c' }, 55 { "directory", CA_DIRECTORY, 'd' }, 56 { "disabled", CA_DISABLED, 0 }, 57 { "enabled", CA_ENABLED, 0 }, 58 { "export", CA_EXPORT, 'e' }, 59 { "file", CA_FILE, 'f' }, 60 { "function", CA_FUNCTION, 0 }, 61 { "helptopic", CA_BUILTIN, 0 }, /* for now */ 62 { "hostname", CA_HOSTNAME, 0 }, 63 { "group", CA_GROUP, 'g' }, 64 { "job", CA_JOB, 'j' }, 65 { "keyword", CA_KEYWORD, 'k' }, 66 { "running", CA_RUNNING, 0 }, 67 { "service", CA_SERVICE, 's' }, 68 { "setopt", CA_SETOPT, 0 }, 69 { "shopt", CA_SHOPT, 0 }, 70 { "signal", CA_SIGNAL, 0 }, 71 { "stopped", CA_STOPPED, 0 }, 72 { "user", CA_USER, 'u' }, 73 { "variable", CA_VARIABLE, 'v' }, 74 { (char *)NULL, 0, 0 }, 75}; 76 77/* This should be a STRING_INT_ALIST */ 78static struct _compopt { 79 char *optname; 80 int optflag; 81} compopts[] = { 82 { "bashdefault", COPT_BASHDEFAULT }, 83 { "default", COPT_DEFAULT }, 84 { "dirnames", COPT_DIRNAMES }, 85 { "filenames",COPT_FILENAMES}, 86 { "nospace", COPT_NOSPACE }, 87 { "plusdirs", COPT_PLUSDIRS }, 88 { (char *)NULL, 0 }, 89}; 90 91static int 92find_compact (name) 93 char *name; 94{ 95 register int i; 96 97 for (i = 0; compacts[i].actname; i++) 98 if (STREQ (name, compacts[i].actname)) 99 return i; 100 return -1; 101} 102 103static int 104find_compopt (name) 105 char *name; 106{ 107 register int i; 108 109 for (i = 0; compopts[i].optname; i++) 110 if (STREQ (name, compopts[i].optname)) 111 return i; 112 return -1; 113} 114 115/* Build the actions and compspec options from the options specified in LIST. 116 ACTP is a pointer to an unsigned long in which to place the bitmap of 117 actions. OPTP is a pointer to an unsigned long in which to place the 118 btmap of compspec options (arguments to `-o'). PP, if non-null, gets 1 119 if -p is supplied; RP, if non-null, gets 1 if -r is supplied. 120 If either is null, the corresponding option generates an error. 121 This also sets variables corresponding to options that take arguments as 122 a side effect; the caller should ensure that those variables are set to 123 NULL before calling build_actions. Return value: 124 EX_USAGE = bad option 125 EXECUTION_SUCCESS = some options supplied 126 EXECUTION_FAILURE = no options supplied 127*/ 128 129static int 130build_actions (list, pp, rp, actp, optp) 131 WORD_LIST *list; 132 int *pp, *rp; 133 unsigned long *actp, *optp; 134{ 135 int opt, ind, opt_given; 136 unsigned long acts, copts; 137 138 acts = copts = (unsigned long)0L; 139 opt_given = 0; 140 141 reset_internal_getopt (); 142 while ((opt = internal_getopt (list, "abcdefgjko:prsuvA:G:W:P:S:X:F:C:")) != -1) 143 { 144 opt_given = 1; 145 switch (opt) 146 { 147 case 'r': 148 if (rp) 149 { 150 *rp = 1; 151 break; 152 } 153 else 154 { 155 sh_invalidopt ("-r"); 156 builtin_usage (); 157 return (EX_USAGE); 158 } 159 160 case 'p': 161 if (pp) 162 { 163 *pp = 1; 164 break; 165 } 166 else 167 { 168 sh_invalidopt ("-p"); 169 builtin_usage (); 170 return (EX_USAGE); 171 } 172 173 case 'a': 174 acts |= CA_ALIAS; 175 break; 176 case 'b': 177 acts |= CA_BUILTIN; 178 break; 179 case 'c': 180 acts |= CA_COMMAND; 181 break; 182 case 'd': 183 acts |= CA_DIRECTORY; 184 break; 185 case 'e': 186 acts |= CA_EXPORT; 187 break; 188 case 'f': 189 acts |= CA_FILE; 190 break; 191 case 'g': 192 acts |= CA_GROUP; 193 break; 194 case 'j': 195 acts |= CA_JOB; 196 break; 197 case 'k': 198 acts |= CA_KEYWORD; 199 break; 200 case 's': 201 acts |= CA_SERVICE; 202 break; 203 case 'u': 204 acts |= CA_USER; 205 break; 206 case 'v': 207 acts |= CA_VARIABLE; 208 break; 209 case 'o': 210 ind = find_compopt (list_optarg); 211 if (ind < 0) 212 { 213 sh_invalidoptname (list_optarg); 214 return (EX_USAGE); 215 } 216 copts |= compopts[ind].optflag; 217 break; 218 case 'A': 219 ind = find_compact (list_optarg); 220 if (ind < 0) 221 { 222 builtin_error (_("%s: invalid action name"), list_optarg); 223 return (EX_USAGE); 224 } 225 acts |= compacts[ind].actflag; 226 break; 227 case 'C': 228 Carg = list_optarg; 229 break; 230 case 'F': 231 Farg = list_optarg; 232 break; 233 case 'G': 234 Garg = list_optarg; 235 break; 236 case 'P': 237 Parg = list_optarg; 238 break; 239 case 'S': 240 Sarg = list_optarg; 241 break; 242 case 'W': 243 Warg = list_optarg; 244 break; 245 case 'X': 246 Xarg = list_optarg; 247 break; 248 default: 249 builtin_usage (); 250 return (EX_USAGE); 251 } 252 } 253 254 *actp = acts; 255 *optp = copts; 256 257 return (opt_given ? EXECUTION_SUCCESS : EXECUTION_FAILURE); 258} 259 260/* Add, remove, and display completion specifiers. */ 261int 262complete_builtin (list) 263 WORD_LIST *list; 264{ 265 int opt_given, pflag, rflag, rval; 266 unsigned long acts, copts; 267 COMPSPEC *cs; 268 269 if (list == 0) 270 { 271 print_all_completions (); 272 return (EXECUTION_SUCCESS); 273 } 274 275 opt_given = pflag = rflag = 0; 276 acts = copts = (unsigned long)0L; 277 Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (char *)NULL; 278 cs = (COMPSPEC *)NULL; 279 280 /* Build the actions from the arguments. Also sets the [A-Z]arg variables 281 as a side effect if they are supplied as options. */ 282 rval = build_actions (list, &pflag, &rflag, &acts, &copts); 283 if (rval == EX_USAGE) 284 return (rval); 285 opt_given = rval != EXECUTION_FAILURE; 286 287 list = loptend; 288 289 /* -p overrides everything else */ 290 if (pflag || (list == 0 && opt_given == 0)) 291 { 292 if (list == 0) 293 { 294 print_all_completions (); 295 return (EXECUTION_SUCCESS); 296 } 297 return (print_cmd_completions (list)); 298 } 299 300 /* next, -r overrides everything else. */ 301 if (rflag) 302 { 303 if (list == 0) 304 { 305 progcomp_flush (); 306 return (EXECUTION_SUCCESS); 307 } 308 return (remove_cmd_completions (list)); 309 } 310 311 if (list == 0 && opt_given) 312 { 313 builtin_usage (); 314 return (EX_USAGE); 315 } 316 317 /* If we get here, we need to build a compspec and add it for each 318 remaining argument. */ 319 cs = compspec_create (); 320 cs->actions = acts; 321 cs->options = copts; 322 323 cs->globpat = STRDUP (Garg); 324 cs->words = STRDUP (Warg); 325 cs->prefix = STRDUP (Parg); 326 cs->suffix = STRDUP (Sarg); 327 cs->funcname = STRDUP (Farg); 328 cs->command = STRDUP (Carg); 329 cs->filterpat = STRDUP (Xarg); 330 331 for (rval = EXECUTION_SUCCESS ; list; list = list->next) 332 { 333 /* Add CS as the compspec for the specified commands. */ 334 if (progcomp_insert (list->word->word, cs) == 0) 335 rval = EXECUTION_FAILURE; 336 } 337 338 return (rval); 339} 340 341static int 342remove_cmd_completions (list) 343 WORD_LIST *list; 344{ 345 WORD_LIST *l; 346 int ret; 347 348 for (ret = EXECUTION_SUCCESS, l = list; l; l = l->next) 349 { 350 if (progcomp_remove (l->word->word) == 0) 351 { 352 builtin_error (_("%s: no completion specification"), l->word->word); 353 ret = EXECUTION_FAILURE; 354 } 355 } 356 return ret; 357} 358 359#define SQPRINTARG(a, f) \ 360 do { \ 361 if (a) \ 362 { \ 363 x = sh_single_quote (a); \ 364 printf ("%s %s ", f, x); \ 365 free (x); \ 366 } \ 367 } while (0) 368 369#define PRINTARG(a, f) \ 370 do { \ 371 if (a) \ 372 printf ("%s %s ", f, a); \ 373 } while (0) 374 375#define PRINTOPT(a, f) \ 376 do { \ 377 if (acts & a) \ 378 printf ("%s ", f); \ 379 } while (0) 380 381#define PRINTACT(a, f) \ 382 do { \ 383 if (acts & a) \ 384 printf ("-A %s ", f); \ 385 } while (0) 386 387#define PRINTCOMPOPT(a, f) \ 388 do { \ 389 if (copts & a) \ 390 printf ("-o %s ", f); \ 391 } while (0) 392 393static int 394print_one_completion (cmd, cs) 395 char *cmd; 396 COMPSPEC *cs; 397{ 398 unsigned long acts, copts; 399 char *x; 400 401 printf ("complete "); 402 403 copts = cs->options; 404 405 /* First, print the -o options. */ 406 PRINTCOMPOPT (COPT_BASHDEFAULT, "bashdefault"); 407 PRINTCOMPOPT (COPT_DEFAULT, "default"); 408 PRINTCOMPOPT (COPT_DIRNAMES, "dirnames"); 409 PRINTCOMPOPT (COPT_FILENAMES, "filenames"); 410 PRINTCOMPOPT (COPT_NOSPACE, "nospace"); 411 PRINTCOMPOPT (COPT_PLUSDIRS, "plusdirs"); 412 413 acts = cs->actions; 414 415 /* simple flags next */ 416 PRINTOPT (CA_ALIAS, "-a"); 417 PRINTOPT (CA_BUILTIN, "-b"); 418 PRINTOPT (CA_COMMAND, "-c"); 419 PRINTOPT (CA_DIRECTORY, "-d"); 420 PRINTOPT (CA_EXPORT, "-e"); 421 PRINTOPT (CA_FILE, "-f"); 422 PRINTOPT (CA_GROUP, "-g"); 423 PRINTOPT (CA_JOB, "-j"); 424 PRINTOPT (CA_KEYWORD, "-k"); 425 PRINTOPT (CA_SERVICE, "-s"); 426 PRINTOPT (CA_USER, "-u"); 427 PRINTOPT (CA_VARIABLE, "-v"); 428 429 /* now the rest of the actions */ 430 PRINTACT (CA_ARRAYVAR, "arrayvar"); 431 PRINTACT (CA_BINDING, "binding"); 432 PRINTACT (CA_DISABLED, "disabled"); 433 PRINTACT (CA_ENABLED, "enabled"); 434 PRINTACT (CA_FUNCTION, "function"); 435 PRINTACT (CA_HELPTOPIC, "helptopic"); 436 PRINTACT (CA_HOSTNAME, "hostname"); 437 PRINTACT (CA_RUNNING, "running"); 438 PRINTACT (CA_SETOPT, "setopt"); 439 PRINTACT (CA_SHOPT, "shopt"); 440 PRINTACT (CA_SIGNAL, "signal"); 441 PRINTACT (CA_STOPPED, "stopped"); 442 443 /* now the rest of the arguments */ 444 445 /* arguments that require quoting */ 446 SQPRINTARG (cs->globpat, "-G"); 447 SQPRINTARG (cs->words, "-W"); 448 SQPRINTARG (cs->prefix, "-P"); 449 SQPRINTARG (cs->suffix, "-S"); 450 SQPRINTARG (cs->filterpat, "-X"); 451 452 /* simple arguments that don't require quoting */ 453 PRINTARG (cs->funcname, "-F"); 454 PRINTARG (cs->command, "-C"); 455 456 printf ("%s\n", cmd); 457 458 return (0); 459} 460 461static int 462print_compitem (item) 463 BUCKET_CONTENTS *item; 464{ 465 COMPSPEC *cs; 466 char *cmd; 467 468 cmd = item->key; 469 cs = (COMPSPEC *)item->data; 470 471 return (print_one_completion (cmd, cs)); 472} 473 474static void 475print_all_completions () 476{ 477 progcomp_walk (print_compitem); 478} 479 480static int 481print_cmd_completions (list) 482 WORD_LIST *list; 483{ 484 WORD_LIST *l; 485 COMPSPEC *cs; 486 int ret; 487 488 for (ret = EXECUTION_SUCCESS, l = list; l; l = l->next) 489 { 490 cs = progcomp_search (l->word->word); 491 if (cs) 492 print_one_completion (l->word->word, cs); 493 else 494 { 495 builtin_error (_("%s: no completion specification"), l->word->word); 496 ret = EXECUTION_FAILURE; 497 } 498 } 499 return (ret); 500} 501 502#line 540 "complete.def" 503 504int 505compgen_builtin (list) 506 WORD_LIST *list; 507{ 508 int rval; 509 unsigned long acts, copts; 510 COMPSPEC *cs; 511 STRINGLIST *sl; 512 char *word, **matches; 513 514 if (list == 0) 515 return (EXECUTION_SUCCESS); 516 517 acts = copts = (unsigned long)0L; 518 Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (char *)NULL; 519 cs = (COMPSPEC *)NULL; 520 521 /* Build the actions from the arguments. Also sets the [A-Z]arg variables 522 as a side effect if they are supplied as options. */ 523 rval = build_actions (list, (int *)NULL, (int *)NULL, &acts, &copts); 524 if (rval == EX_USAGE) 525 return (rval); 526 if (rval == EXECUTION_FAILURE) 527 return (EXECUTION_SUCCESS); 528 529 list = loptend; 530 531 word = (list && list->word) ? list->word->word : ""; 532 533 if (Farg) 534 builtin_error (_("warning: -F option may not work as you expect")); 535 if (Carg) 536 builtin_error (_("warning: -C option may not work as you expect")); 537 538 /* If we get here, we need to build a compspec and evaluate it. */ 539 cs = compspec_create (); 540 cs->actions = acts; 541 cs->options = copts; 542 cs->refcount = 1; 543 544 cs->globpat = STRDUP (Garg); 545 cs->words = STRDUP (Warg); 546 cs->prefix = STRDUP (Parg); 547 cs->suffix = STRDUP (Sarg); 548 cs->funcname = STRDUP (Farg); 549 cs->command = STRDUP (Carg); 550 cs->filterpat = STRDUP (Xarg); 551 552 rval = EXECUTION_FAILURE; 553 sl = gen_compspec_completions (cs, "compgen", word, 0, 0); 554 555 /* If the compspec wants the bash default completions, temporarily 556 turn off programmable completion and call the bash completion code. */ 557 if ((sl == 0 || sl->list_len == 0) && (copts & COPT_BASHDEFAULT)) 558 { 559 matches = bash_default_completion (word, 0, 0, 0, 0); 560 sl = completions_to_stringlist (matches); 561 strvec_dispose (matches); 562 } 563 564 /* This isn't perfect, but it's the best we can do, given what readline 565 exports from its set of completion utility functions. */ 566 if ((sl == 0 || sl->list_len == 0) && (copts & COPT_DEFAULT)) 567 { 568 matches = rl_completion_matches (word, rl_filename_completion_function); 569 sl = completions_to_stringlist (matches); 570 strvec_dispose (matches); 571 } 572 573 if (sl) 574 { 575 if (sl->list && sl->list_len) 576 { 577 rval = EXECUTION_SUCCESS; 578 strlist_print (sl, (char *)NULL); 579 } 580 strlist_dispose (sl); 581 } 582 583 compspec_dispose (cs); 584 return (rval); 585} 586