comparison src/dired.c @ 440:8de8e3f6228a r21-2-28

Import from CVS: tag r21-2-28
author cvs
date Mon, 13 Aug 2007 11:33:38 +0200
parents 3ecd8885ac67
children abe6d1db359e
comparison
equal deleted inserted replaced
439:357dd071b03c 440:8de8e3f6228a
540 if and only if the completion returned in the car was unique. 540 if and only if the completion returned in the car was unique.
541 */ 541 */
542 (user)) 542 (user))
543 { 543 {
544 int uniq; 544 int uniq;
545 Lisp_Object completed; 545 Lisp_Object completed = user_name_completion (user, 0, &uniq);
546
547 completed = user_name_completion (user, 0, &uniq);
548 return Fcons (completed, uniq ? Qt : Qnil); 546 return Fcons (completed, uniq ? Qt : Qnil);
549 } 547 }
550 548
551 DEFUN ("user-name-all-completions", Fuser_name_all_completions, 1, 1, 0, /* 549 DEFUN ("user-name-all-completions", Fuser_name_all_completions, 1, 1, 0, /*
552 Return a list of all completions of user name USER. 550 Return a list of all completions of user name USER.
555 (user)) 553 (user))
556 { 554 {
557 return user_name_completion (user, 1, NULL); 555 return user_name_completion (user, 1, NULL);
558 } 556 }
559 557
560 struct user_cache { 558 struct user_name
561 Bufbyte **data; 559 {
560 Bufbyte *ptr;
561 size_t len;
562 };
563
564 struct user_cache
565 {
566 struct user_name *user_names;
562 int length; 567 int length;
563 int size; 568 int size;
564 EMACS_TIME last_rebuild_time; 569 EMACS_TIME last_rebuild_time;
565 }; 570 };
566 static struct user_cache user_cache; 571 static struct user_cache user_cache;
568 static void 573 static void
569 free_user_cache (struct user_cache *cache) 574 free_user_cache (struct user_cache *cache)
570 { 575 {
571 int i; 576 int i;
572 for (i = 0; i < cache->length; i++) 577 for (i = 0; i < cache->length; i++)
573 xfree (cache->data[i]); 578 xfree (cache->user_names[i].ptr);
574 xfree (cache->data); 579 xfree (cache->user_names);
580 xzero (*cache);
575 } 581 }
576 582
577 static Lisp_Object 583 static Lisp_Object
578 user_name_completion_unwind (Lisp_Object locative) 584 user_name_completion_unwind (Lisp_Object cache_incomplete_p)
579 { 585 {
580 int interrupted = !NILP (XCAR (locative)); 586 endpwent ();
581 587 speed_up_interrupts ();
582 if (interrupted) 588
583 { 589 if (! NILP (XCAR (cache_incomplete_p)))
584 endpwent (); 590 free_user_cache (&user_cache);
585 speed_up_interrupts (); 591
586 free_user_cache (&user_cache); 592 free_cons (XCONS (cache_incomplete_p));
587 }
588 free_cons (XCONS (locative));
589 593
590 return Qnil; 594 return Qnil;
591 } 595 }
592 596
593 #define USER_CACHE_REBUILD (24*60*60) /* 1 day, in seconds */ 597 #define USER_CACHE_TTL (24*60*60) /* Time to live: 1 day, in seconds */
594 598
595 static Lisp_Object 599 static Lisp_Object
596 user_name_completion (Lisp_Object user, int all_flag, int *uniq) 600 user_name_completion (Lisp_Object user, int all_flag, int *uniq)
597 { 601 {
598 /* This function can GC */ 602 /* This function can GC */
599 int matchcount = 0; 603 int matchcount = 0;
600 Lisp_Object bestmatch = Qnil; 604 Lisp_Object bestmatch = Qnil;
601 Charcount bestmatchsize = 0; 605 Charcount bestmatchsize = 0;
602 int speccount = specpdl_depth ();
603 Charcount user_name_length; 606 Charcount user_name_length;
604 EMACS_TIME t; 607 EMACS_TIME t;
605 int i; 608 int i;
606 struct gcpro gcpro1, gcpro2; 609 struct gcpro gcpro1, gcpro2;
607 610
612 user_name_length = XSTRING_CHAR_LENGTH (user); 615 user_name_length = XSTRING_CHAR_LENGTH (user);
613 616
614 /* Cache user name lookups because it tends to be quite slow. 617 /* Cache user name lookups because it tends to be quite slow.
615 * Rebuild the cache occasionally to catch changes */ 618 * Rebuild the cache occasionally to catch changes */
616 EMACS_GET_TIME (t); 619 EMACS_GET_TIME (t);
617 if (user_cache.data && 620 if (user_cache.user_names &&
618 (EMACS_SECS (t) - EMACS_SECS (user_cache.last_rebuild_time) 621 (EMACS_SECS (t) - EMACS_SECS (user_cache.last_rebuild_time)
619 > USER_CACHE_REBUILD)) 622 > USER_CACHE_TTL))
620 { 623 free_user_cache (&user_cache);
621 free_user_cache (&user_cache); 624
622 xzero (user_cache); 625 if (!user_cache.user_names)
623 }
624
625 if (!user_cache.data)
626 { 626 {
627 struct passwd *pwd; 627 struct passwd *pwd;
628 Lisp_Object locative = noseeum_cons (Qt, Qnil); 628 Lisp_Object cache_incomplete_p = noseeum_cons (Qt, Qnil);
629 int speccount = specpdl_depth ();
630
629 slow_down_interrupts (); 631 slow_down_interrupts ();
630 setpwent (); 632 setpwent ();
631 record_unwind_protect (user_name_completion_unwind, locative); 633 record_unwind_protect (user_name_completion_unwind, cache_incomplete_p);
632 while ((pwd = getpwent ())) 634 while ((pwd = getpwent ()))
633 { 635 {
634 Bufbyte *pwuser;
635 QUIT; 636 QUIT;
636 DO_REALLOC (user_cache.data, user_cache.size, 637 DO_REALLOC (user_cache.user_names, user_cache.size,
637 user_cache.length + 1, Bufbyte *); 638 user_cache.length + 1, struct user_name);
638 GET_C_CHARPTR_INT_DATA_ALLOCA (pwd->pw_name, FORMAT_OS, pwuser); 639 TO_INTERNAL_FORMAT (C_STRING, pwd->pw_name,
639 user_cache.data[user_cache.length++] = 640 MALLOC,
640 (Bufbyte *) xstrdup ((char *) pwuser); 641 (user_cache.user_names[user_cache.length].ptr,
642 user_cache.user_names[user_cache.length].len),
643 Qnative);
644 user_cache.length++;
641 } 645 }
642 endpwent (); 646 XCAR (cache_incomplete_p) = Qnil;
643 speed_up_interrupts (); 647 unbind_to (speccount, Qnil);
644 XCAR (locative) = Qnil; 648
645 unbind_to (speccount, Qnil); /* free locative cons */
646 EMACS_GET_TIME (user_cache.last_rebuild_time); 649 EMACS_GET_TIME (user_cache.last_rebuild_time);
647 } 650 }
648 651
649 for (i = 0; i < user_cache.length; i++) 652 for (i = 0; i < user_cache.length; i++)
650 { 653 {
651 Bufbyte *u_name = user_cache.data[i]; 654 Bufbyte *u_name = user_cache.user_names[i].ptr;
652 Bytecount len = strlen ((char *) u_name); 655 Bytecount len = user_cache.user_names[i].len;
653 /* scmp() works in chars, not bytes, so we have to compute this: */ 656 /* scmp() works in chars, not bytes, so we have to compute this: */
654 Charcount cclen = bytecount_to_charcount (u_name, len); 657 Charcount cclen = bytecount_to_charcount (u_name, len);
655 658
656 QUIT; 659 QUIT;
657 660