comparison src/specifier.c @ 272:c5d627a313b1 r21-0b34

Import from CVS: tag r21-0b34
author cvs
date Mon, 13 Aug 2007 10:28:48 +0200
parents 3d6bfa290dbd
children 6330739388db
comparison
equal deleted inserted replaced
271:c7b7086b0a39 272:c5d627a313b1
47 47
48 Lisp_Object Qconsole_type, Qdevice_class; 48 Lisp_Object Qconsole_type, Qdevice_class;
49 49
50 Lisp_Object Vuser_defined_tags; 50 Lisp_Object Vuser_defined_tags;
51 51
52 MAC_DEFINE (struct Lisp_Specifier *, MTspecmeth_or_given)
53 MAC_DEFINE (struct Lisp_Specifier *, MTspecifier_data)
54
55 typedef struct specifier_type_entry specifier_type_entry; 52 typedef struct specifier_type_entry specifier_type_entry;
56 struct specifier_type_entry 53 struct specifier_type_entry
57 { 54 {
58 Lisp_Object symbol; 55 Lisp_Object symbol;
59 struct specifier_methods *meths; 56 struct specifier_methods *meths;
78 75
79 #### Look into this for 19.14. */ 76 #### Look into this for 19.14. */
80 Lisp_Object_dynarr current_specifiers; 77 Lisp_Object_dynarr current_specifiers;
81 78
82 static void recompute_cached_specifier_everywhere (Lisp_Object specifier); 79 static void recompute_cached_specifier_everywhere (Lisp_Object specifier);
80
81 EXFUN (Fspecifier_specs, 4);
82 EXFUN (Fremove_specifier, 4);
83 83
84 84
85 /************************************************************************/ 85 /************************************************************************/
86 /* Specifier object methods */ 86 /* Specifier object methods */
87 /************************************************************************/ 87 /************************************************************************/
88
89 static Lisp_Object mark_specifier (Lisp_Object, void (*) (Lisp_Object));
90 static void print_specifier (Lisp_Object, Lisp_Object, int);
91 static int specifier_equal (Lisp_Object, Lisp_Object, int depth);
92 static unsigned long specifier_hash (Lisp_Object obj, int depth);
93 static unsigned int sizeof_specifier (CONST void *header);
94 static void finalize_specifier (void *header, int for_disksave);
95 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("specifier", specifier,
96 mark_specifier, print_specifier,
97 finalize_specifier,
98 specifier_equal, specifier_hash,
99 sizeof_specifier,
100 struct Lisp_Specifier);
101 88
102 /* Remove dead objects from the specified assoc list. */ 89 /* Remove dead objects from the specified assoc list. */
103 90
104 static Lisp_Object 91 static Lisp_Object
105 cleanup_assoc_list (Lisp_Object list) 92 cleanup_assoc_list (Lisp_Object list)
297 /* This function can be called from within redisplay. 284 /* This function can be called from within redisplay.
298 internal_equal can trigger a quit. That leads to Bad Things. */ 285 internal_equal can trigger a quit. That leads to Bad Things. */
299 Vinhibit_quit = Qt; 286 Vinhibit_quit = Qt;
300 287
301 depth++; 288 depth++;
302 if (s1->methods != s2->methods || 289 retval =
303 !internal_equal (s1->global_specs, s2->global_specs, depth) || 290 (s1->methods == s2->methods &&
304 !internal_equal (s1->device_specs, s2->device_specs, depth) || 291 internal_equal (s1->global_specs, s2->global_specs, depth) &&
305 !internal_equal (s1->frame_specs, s2->frame_specs, depth) || 292 internal_equal (s1->device_specs, s2->device_specs, depth) &&
306 !internal_equal (s1->window_specs, s2->window_specs, depth) || 293 internal_equal (s1->frame_specs, s2->frame_specs, depth) &&
307 !internal_equal (s1->buffer_specs, s2->buffer_specs, depth) || 294 internal_equal (s1->window_specs, s2->window_specs, depth) &&
308 !SPECMETH_OR_GIVEN (s1, equal, (o1, o2, depth - 1), 1)) 295 internal_equal (s1->buffer_specs, s2->buffer_specs, depth));
309 retval = 0; 296
310 else 297 if (retval && HAS_SPECMETH_P (s1, equal))
311 retval = 1; 298 retval = SPECMETH (s1, equal, (o1, o2, depth - 1));
312 299
313 Vinhibit_quit = old_inhibit_quit; 300 Vinhibit_quit = old_inhibit_quit;
314 return retval; 301 return retval;
315 } 302 }
316 303
320 struct Lisp_Specifier *s = XSPECIFIER (obj); 307 struct Lisp_Specifier *s = XSPECIFIER (obj);
321 308
322 /* specifier hashing is a bit problematic because there are so 309 /* specifier hashing is a bit problematic because there are so
323 many places where data can be stored. We pick what are perhaps 310 many places where data can be stored. We pick what are perhaps
324 the most likely places where interesting stuff will be. */ 311 the most likely places where interesting stuff will be. */
325 return HASH5 (SPECMETH_OR_GIVEN (s, hash, (obj, depth), 0), 312 return HASH5 ((HAS_SPECMETH_P (s, hash) ?
313 SPECMETH (s, hash, (obj, depth)) : 0),
326 (unsigned long) s->methods, 314 (unsigned long) s->methods,
327 internal_hash (s->global_specs, depth + 1), 315 internal_hash (s->global_specs, depth + 1),
328 internal_hash (s->frame_specs, depth + 1), 316 internal_hash (s->frame_specs, depth + 1),
329 internal_hash (s->buffer_specs, depth + 1)); 317 internal_hash (s->buffer_specs, depth + 1));
330 } 318 }
331 319
332 static unsigned int 320 static size_t
333 sizeof_specifier (CONST void *header) 321 sizeof_specifier (CONST void *header)
334 { 322 {
335 CONST struct Lisp_Specifier *p = (CONST struct Lisp_Specifier *) header; 323 CONST struct Lisp_Specifier *p = (CONST struct Lisp_Specifier *) header;
336 return sizeof (*p) + p->methods->extra_data_size - 1; 324 return sizeof (*p) + p->methods->extra_data_size - 1;
337 } 325 }
338 326
327 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("specifier", specifier,
328 mark_specifier, print_specifier,
329 finalize_specifier,
330 specifier_equal, specifier_hash,
331 sizeof_specifier,
332 struct Lisp_Specifier);
339 333
340 /************************************************************************/ 334 /************************************************************************/
341 /* Creating specifiers */ 335 /* Creating specifiers */
342 /************************************************************************/ 336 /************************************************************************/
343 337
359 } 353 }
360 354
361 static int 355 static int
362 valid_specifier_type_p (Lisp_Object type) 356 valid_specifier_type_p (Lisp_Object type)
363 { 357 {
364 if (decode_specifier_type (type, ERROR_ME_NOT)) 358 return decode_specifier_type (type, ERROR_ME_NOT) != 0;
365 return 1;
366 return 0;
367 } 359 }
368 360
369 DEFUN ("valid-specifier-type-p", Fvalid_specifier_type_p, 1, 1, 0, /* 361 DEFUN ("valid-specifier-type-p", Fvalid_specifier_type_p, 1, 1, 0, /*
370 Given a SPECIFIER-TYPE, return non-nil if it is valid. 362 Given a SPECIFIER-TYPE, return non-nil if it is valid.
371 Valid types are 'generic, 'integer, boolean, 'color, 'font, 'image, 363 Valid types are 'generic, 'integer, boolean, 'color, 'font, 'image,
372 'face-boolean, and 'toolbar. 364 'face-boolean, and 'toolbar.
373 */ 365 */
374 (specifier_type)) 366 (specifier_type))
375 { 367 {
376 if (valid_specifier_type_p (specifier_type)) 368 return valid_specifier_type_p (specifier_type) ? Qt : Qnil;
377 return Qt;
378 else
379 return Qnil;
380 } 369 }
381 370
382 DEFUN ("specifier-type-list", Fspecifier_type_list, 0, 0, 0, /* 371 DEFUN ("specifier-type-list", Fspecifier_type_list, 0, 0, 0, /*
383 Return a list of valid specifier types. 372 Return a list of valid specifier types.
384 */ 373 */
400 } 389 }
401 390
402 static Lisp_Object 391 static Lisp_Object
403 make_specifier (struct specifier_methods *spec_meths) 392 make_specifier (struct specifier_methods *spec_meths)
404 { 393 {
405 Lisp_Object specifier = Qnil; 394 Lisp_Object specifier;
406 struct gcpro gcpro1; 395 struct gcpro gcpro1;
407 struct Lisp_Specifier *sp = (struct Lisp_Specifier *) 396 struct Lisp_Specifier *sp = (struct Lisp_Specifier *)
408 alloc_lcrecord (sizeof (struct Lisp_Specifier) + 397 alloc_lcrecord (sizeof (struct Lisp_Specifier) +
409 spec_meths->extra_data_size - 1, lrecord_specifier); 398 spec_meths->extra_data_size - 1, lrecord_specifier);
410 399
426 UNGCPRO; 415 UNGCPRO;
427 return specifier; 416 return specifier;
428 } 417 }
429 418
430 DEFUN ("make-specifier", Fmake_specifier, 1, 1, 0, /* 419 DEFUN ("make-specifier", Fmake_specifier, 1, 1, 0, /*
431 Create a new specifier. 420 Return a new specifier object of type TYPE.
432 421
433 A specifier is an object that can be used to keep track of a property 422 A specifier is an object that can be used to keep track of a property
434 whose value can be per-buffer, per-window, per-frame, or per-device, 423 whose value can be per-buffer, per-window, per-frame, or per-device,
435 and can further be restricted to a particular console-type or device-class. 424 and can further be restricted to a particular console-type or device-class.
436 Specifiers are used, for example, for the various built-in properties of a 425 Specifiers are used, for example, for the various built-in properties of a
458 447
459 return make_specifier (meths); 448 return make_specifier (meths);
460 } 449 }
461 450
462 DEFUN ("specifierp", Fspecifierp, 1, 1, 0, /* 451 DEFUN ("specifierp", Fspecifierp, 1, 1, 0, /*
463 Return non-nil if OBJECT is a specifier. 452 Return t if OBJECT is a specifier.
464 453
465 A specifier is an object that can be used to keep track of a property 454 A specifier is an object that can be used to keep track of a property
466 whose value can be per-buffer, per-window, per-frame, or per-device, 455 whose value can be per-buffer, per-window, per-frame, or per-device,
467 and can further be restricted to a particular console-type or device-class. 456 and can further be restricted to a particular console-type or device-class.
468 See `make-specifier'. 457 See `make-specifier'.
469 */ 458 */
470 (object)) 459 (object))
471 { 460 {
472 if (!SPECIFIERP (object)) 461 return SPECIFIERP (object) ? Qt : Qnil;
473 return Qnil;
474 return Qt;
475 } 462 }
476 463
477 DEFUN ("specifier-type", Fspecifier_type, 1, 1, 0, /* 464 DEFUN ("specifier-type", Fspecifier_type, 1, 1, 0, /*
478 Return the type of SPECIFIER. 465 Return the type of SPECIFIER.
479 */ 466 */
487 /************************************************************************/ 474 /************************************************************************/
488 /* Locales and domains */ 475 /* Locales and domains */
489 /************************************************************************/ 476 /************************************************************************/
490 477
491 DEFUN ("valid-specifier-locale-p", Fvalid_specifier_locale_p, 1, 1, 0, /* 478 DEFUN ("valid-specifier-locale-p", Fvalid_specifier_locale_p, 1, 1, 0, /*
492 Return non-nil if LOCALE is a valid specifier locale. 479 Return t if LOCALE is a valid specifier locale.
493 Valid locales are a device, a frame, a window, a buffer, and 'global. 480 Valid locales are devices, frames, windows, buffers, and 'global.
494 (nil is not valid.) 481 \(nil is not valid.)
495 */ 482 */
496 (locale)) 483 (locale))
497 { 484 {
498 /* This cannot GC. */ 485 /* This cannot GC. */
499 if ((DEVICEP (locale) && DEVICE_LIVE_P (XDEVICE (locale))) || 486 return ((DEVICEP (locale) && DEVICE_LIVE_P (XDEVICE (locale))) ||
500 (FRAMEP (locale) && FRAME_LIVE_P (XFRAME (locale))) || 487 (FRAMEP (locale) && FRAME_LIVE_P (XFRAME (locale))) ||
501 (BUFFERP (locale) && BUFFER_LIVE_P (XBUFFER (locale))) || 488 (BUFFERP (locale) && BUFFER_LIVE_P (XBUFFER (locale))) ||
502 /* dead windows are allowed because they may become live 489 /* dead windows are allowed because they may become live
503 windows again when a window configuration is restored */ 490 windows again when a window configuration is restored */
504 WINDOWP (locale) || 491 WINDOWP (locale) ||
505 EQ (locale, Qglobal)) 492 EQ (locale, Qglobal))
506 return Qt; 493 ? Qt : Qnil;
507 else
508 return Qnil;
509 } 494 }
510 495
511 DEFUN ("valid-specifier-domain-p", Fvalid_specifier_domain_p, 1, 1, 0, /* 496 DEFUN ("valid-specifier-domain-p", Fvalid_specifier_domain_p, 1, 1, 0, /*
512 Return non-nil if DOMAIN is a valid specifier domain. 497 Return t if DOMAIN is a valid specifier domain.
513 A domain is used to instance a specifier (i.e. determine the specifier's 498 A domain is used to instance a specifier (i.e. determine the specifier's
514 value in that domain). Valid domains are a window, frame, or device. 499 value in that domain). Valid domains are windows, frames, and devices.
515 (nil is not valid.) 500 \(nil is not valid.)
516 */ 501 */
517 (domain)) 502 (domain))
518 { 503 {
519 /* This cannot GC. */ 504 /* This cannot GC. */
520 if ((DEVICEP (domain) && DEVICE_LIVE_P (XDEVICE (domain))) || 505 return ((DEVICEP (domain) && DEVICE_LIVE_P (XDEVICE (domain))) ||
521 (FRAMEP (domain) && FRAME_LIVE_P (XFRAME (domain))) || 506 (FRAMEP (domain) && FRAME_LIVE_P (XFRAME (domain))) ||
522 (WINDOWP (domain) && WINDOW_LIVE_P (XWINDOW (domain)))) 507 (WINDOWP (domain) && WINDOW_LIVE_P (XWINDOW (domain))))
523 return Qt; 508 ? Qt : Qnil;
524 else
525 return Qnil;
526 } 509 }
527 510
528 DEFUN ("valid-specifier-locale-type-p", Fvalid_specifier_locale_type_p, 1, 1, 0, /* 511 DEFUN ("valid-specifier-locale-type-p", Fvalid_specifier_locale_type_p, 1, 1, 0, /*
529 Given a specifier LOCALE-TYPE, return non-nil if it is valid. 512 Given a specifier LOCALE-TYPE, return non-nil if it is valid.
530 Valid locale types are 'global, 'device, 'frame, 'window, and 'buffer. 513 Valid locale types are 'global, 'device, 'frame, 'window, and 'buffer.
531 (Note, however, that in functions that accept either a locale or a locale 514 \(Note, however, that in functions that accept either a locale or a locale
532 type, 'global is considered an individual locale.) 515 type, 'global is considered an individual locale.)
533 */ 516 */
534 (locale_type)) 517 (locale_type))
535 { 518 {
536 /* This cannot GC. */ 519 /* This cannot GC. */
537 if (EQ (locale_type, Qglobal) || 520 return (EQ (locale_type, Qglobal) ||
538 EQ (locale_type, Qdevice) || 521 EQ (locale_type, Qdevice) ||
539 EQ (locale_type, Qframe) || 522 EQ (locale_type, Qframe) ||
540 EQ (locale_type, Qwindow) || 523 EQ (locale_type, Qwindow) ||
541 EQ (locale_type, Qbuffer)) 524 EQ (locale_type, Qbuffer)) ? Qt : Qnil;
542 return Qt;
543 else
544 return Qnil;
545 } 525 }
546 526
547 static void 527 static void
548 check_valid_locale_or_locale_type (Lisp_Object locale) 528 check_valid_locale_or_locale_type (Lisp_Object locale)
549 { 529 {
553 !NILP (Fvalid_specifier_locale_type_p (locale))) 533 !NILP (Fvalid_specifier_locale_type_p (locale)))
554 return; 534 return;
555 signal_simple_error ("Invalid specifier locale or locale type", locale); 535 signal_simple_error ("Invalid specifier locale or locale type", locale);
556 } 536 }
557 537
558 DEFUN ("specifier-locale-type-from-locale", Fspecifier_locale_type_from_locale, 1, 1, 0, /* 538 DEFUN ("specifier-locale-type-from-locale",
539 Fspecifier_locale_type_from_locale, 1, 1, 0, /*
559 Given a specifier LOCALE, return its type. 540 Given a specifier LOCALE, return its type.
560 */ 541 */
561 (locale)) 542 (locale))
562 { 543 {
563 /* This cannot GC. */ 544 /* This cannot GC. */
564 if (NILP (Fvalid_specifier_locale_p (locale))) 545 if (NILP (Fvalid_specifier_locale_p (locale)))
565 signal_simple_error ("Invalid specifier locale", locale); 546 signal_simple_error ("Invalid specifier locale", locale);
566 if (DEVICEP (locale)) 547 if (DEVICEP (locale)) return Qdevice;
567 return Qdevice; 548 if (FRAMEP (locale)) return Qframe;
568 if (FRAMEP (locale)) 549 if (WINDOWP (locale)) return Qwindow;
569 return Qframe; 550 if (BUFFERP (locale)) return Qbuffer;
570 if (WINDOWP (locale))
571 return Qwindow;
572 if (BUFFERP (locale))
573 return Qbuffer;
574 assert (EQ (locale, Qglobal)); 551 assert (EQ (locale, Qglobal));
575 return Qglobal; 552 return Qglobal;
576 } 553 }
577 554
578 Lisp_Object 555 static Lisp_Object
579 decode_locale (Lisp_Object locale) 556 decode_locale (Lisp_Object locale)
580 { 557 {
581 /* This cannot GC. */ 558 /* This cannot GC. */
582 if (NILP (locale)) 559 if (NILP (locale))
583 return Qglobal; 560 return Qglobal;
632 { 609 {
633 if (NILP (Fvalid_specifier_domain_p (domain))) 610 if (NILP (Fvalid_specifier_domain_p (domain)))
634 signal_simple_error ("Invalid specifier domain", domain); 611 signal_simple_error ("Invalid specifier domain", domain);
635 } 612 }
636 613
637 Lisp_Object 614 static Lisp_Object
638 decode_domain (Lisp_Object domain) 615 decode_domain (Lisp_Object domain)
639 { 616 {
640 if (NILP (domain)) 617 if (NILP (domain))
641 return Fselected_window (Qnil); 618 return Fselected_window (Qnil);
642 check_valid_domain (domain); 619 check_valid_domain (domain);
652 Return non-nil if TAG is a valid specifier tag. 629 Return non-nil if TAG is a valid specifier tag.
653 See also `valid-specifier-tag-set-p'. 630 See also `valid-specifier-tag-set-p'.
654 */ 631 */
655 (tag)) 632 (tag))
656 { 633 {
657 if (valid_console_type_p (tag) || 634 return (valid_console_type_p (tag) ||
658 valid_device_class_p (tag) || 635 valid_device_class_p (tag) ||
659 !NILP (assq_no_quit (tag, Vuser_defined_tags))) 636 !NILP (assq_no_quit (tag, Vuser_defined_tags))) ? Qt : Qnil;
660 return Qt;
661 return Qnil;
662 } 637 }
663 638
664 DEFUN ("valid-specifier-tag-set-p", Fvalid_specifier_tag_set_p, 1, 1, 0, /* 639 DEFUN ("valid-specifier-tag-set-p", Fvalid_specifier_tag_set_p, 1, 1, 0, /*
665 Return non-nil if TAG-SET is a valid specifier tag set. 640 Return non-nil if TAG-SET is a valid specifier tag set.
666 641
669 particular device class or device type and/or to mark instantiators 644 particular device class or device type and/or to mark instantiators
670 added by a particular package so that they can be later removed. 645 added by a particular package so that they can be later removed.
671 646
672 A specifier tag set consists of a list of zero of more specifier tags, 647 A specifier tag set consists of a list of zero of more specifier tags,
673 each of which is a symbol that is recognized by XEmacs as a tag. 648 each of which is a symbol that is recognized by XEmacs as a tag.
674 (The valid device types and device classes are always tags, as are 649 \(The valid device types and device classes are always tags, as are
675 any tags defined by `define-specifier-tag'.) It is called a "tag set" 650 any tags defined by `define-specifier-tag'.) It is called a "tag set"
676 (as opposed to a list) because the order of the tags or the number of 651 \(as opposed to a list) because the order of the tags or the number of
677 times a particular tag occurs does not matter. 652 times a particular tag occurs does not matter.
678 653
679 Each tag has a predicate associated with it, which specifies whether 654 Each tag has a predicate associated with it, which specifies whether
680 that tag applies to a particular device. The tags which are device types 655 that tag applies to a particular device. The tags which are device types
681 and classes match devices of that type or class. User-defined tags can 656 and classes match devices of that type or class. User-defined tags can
819 } 794 }
820 795
821 DEFUN ("define-specifier-tag", Fdefine_specifier_tag, 1, 2, 0, /* 796 DEFUN ("define-specifier-tag", Fdefine_specifier_tag, 1, 2, 0, /*
822 Define a new specifier tag. 797 Define a new specifier tag.
823 If PREDICATE is specified, it should be a function of one argument 798 If PREDICATE is specified, it should be a function of one argument
824 (a device) that specifies whether the tag matches that particular 799 \(a device) that specifies whether the tag matches that particular
825 device. If PREDICATE is omitted, the tag matches all devices. 800 device. If PREDICATE is omitted, the tag matches all devices.
826 801
827 You can redefine an existing user-defined specifier tag. However, 802 You can redefine an existing user-defined specifier tag. However,
828 you cannot redefine the built-in specifier tags (the device types 803 you cannot redefine the built-in specifier tags (the device types
829 and classes) or the symbols nil, t, 'all, or 'global. 804 and classes) or the symbols nil, t, 'all, or 'global.
891 866
892 void 867 void
893 setup_device_initial_specifier_tags (struct device *d) 868 setup_device_initial_specifier_tags (struct device *d)
894 { 869 {
895 Lisp_Object rest, rest2; 870 Lisp_Object rest, rest2;
896 Lisp_Object device = Qnil; 871 Lisp_Object device;
897 872
898 XSETDEVICE (device, d); 873 XSETDEVICE (device, d);
899 874
900 DEVICE_USER_DEFINED_TAGS (d) = Fcopy_alist (Vuser_defined_tags); 875 DEVICE_USER_DEFINED_TAGS (d) = Fcopy_alist (Vuser_defined_tags);
901 876
912 else 887 else
913 XCDR (XCAR (rest2)) = !NILP (call1 (predicate, device)) ? Qt : Qnil; 888 XCDR (XCAR (rest2)) = !NILP (call1 (predicate, device)) ? Qt : Qnil;
914 } 889 }
915 } 890 }
916 891
917 DEFUN ("device-matching-specifier-tag-list", Fdevice_matching_specifier_tag_list, 0, 1, 0, /* 892 DEFUN ("device-matching-specifier-tag-list",
893 Fdevice_matching_specifier_tag_list, 0, 1, 0, /*
918 Return a list of all specifier tags matching DEVICE. 894 Return a list of all specifier tags matching DEVICE.
919 DEVICE defaults to the selected device if omitted. 895 DEVICE defaults to the selected device if omitted.
920 */ 896 */
921 (device)) 897 (device))
922 { 898 {
932 list = Fcons (XCAR (XCAR (rest)), list); 908 list = Fcons (XCAR (XCAR (rest)), list);
933 } 909 }
934 910
935 list = Fnreverse (list); 911 list = Fnreverse (list);
936 list = Fcons (DEVICE_CLASS (d), list); 912 list = Fcons (DEVICE_CLASS (d), list);
937 list = Fcons (DEVICE_TYPE (d), list); 913 list = Fcons (DEVICE_TYPE (d), list);
938 914
939 RETURN_UNGCPRO (list); 915 RETURN_UNGCPRO (list);
940 } 916 }
941 917
942 DEFUN ("specifier-tag-list", Fspecifier_tag_list, 0, 0, 0, /* 918 DEFUN ("specifier-tag-list", Fspecifier_tag_list, 0, 0, 0, /*
1090 { 1066 {
1091 Lisp_Object rest; 1067 Lisp_Object rest;
1092 1068
1093 LIST_LOOP (rest, inst_list) 1069 LIST_LOOP (rest, inst_list)
1094 { 1070 {
1095 if (!CONSP (rest) || !CONSP (XCAR (rest))) 1071 Lisp_Object inst_pair, tag_set;
1072
1073 if (!CONSP (rest))
1096 { 1074 {
1097 maybe_signal_simple_error ("Invalid instantiator list", inst_list, 1075 maybe_signal_simple_error ("Invalid instantiator list", inst_list,
1098 Qspecifier, errb); 1076 Qspecifier, errb);
1099 return Qnil; 1077 return Qnil;
1100 } 1078 }
1101 if (NILP (Fvalid_specifier_tag_set_p (XCAR (XCAR (rest))))) 1079 if (!CONSP (inst_pair = XCAR (rest)))
1102 { 1080 {
1103 maybe_signal_simple_error ("Invalid specifier tag", 1081 maybe_signal_simple_error ("Invalid instantiator pair", inst_pair,
1104 XCAR (XCAR (rest)), Qspecifier, errb); 1082 Qspecifier, errb);
1105 return Qnil; 1083 return Qnil;
1106 } 1084 }
1107 1085 if (NILP (Fvalid_specifier_tag_set_p (tag_set = XCAR (inst_pair))))
1108 if (NILP (check_valid_instantiator (XCDR (XCAR (rest)), meths, 1086 {
1109 errb))) 1087 maybe_signal_simple_error ("Invalid specifier tag", tag_set,
1088 Qspecifier, errb);
1089 return Qnil;
1090 }
1091
1092 if (NILP (check_valid_instantiator (XCDR (inst_pair), meths, errb)))
1110 return Qnil; 1093 return Qnil;
1111 } 1094 }
1112 1095
1113 return Qt; 1096 return Qt;
1114 } 1097 }
1139 { 1122 {
1140 Lisp_Object rest; 1123 Lisp_Object rest;
1141 1124
1142 LIST_LOOP (rest, spec_list) 1125 LIST_LOOP (rest, spec_list)
1143 { 1126 {
1144 if (!CONSP (rest) || !CONSP (XCAR (rest))) 1127 Lisp_Object spec, locale;
1128 if (!CONSP (rest) || !CONSP (spec = XCAR (rest)))
1145 { 1129 {
1146 maybe_signal_simple_error ("Invalid specification list", spec_list, 1130 maybe_signal_simple_error ("Invalid specification list", spec_list,
1147 Qspecifier, errb); 1131 Qspecifier, errb);
1148 return Qnil; 1132 return Qnil;
1149 } 1133 }
1150 if (NILP (Fvalid_specifier_locale_p (XCAR (XCAR (rest))))) 1134 if (NILP (Fvalid_specifier_locale_p (locale = XCAR (spec))))
1151 { 1135 {
1152 maybe_signal_simple_error ("Invalid specifier locale", 1136 maybe_signal_simple_error ("Invalid specifier locale", locale,
1153 XCAR (XCAR (rest)),
1154 Qspecifier, errb); 1137 Qspecifier, errb);
1155 return Qnil; 1138 return Qnil;
1156 } 1139 }
1157 1140
1158 if (NILP (check_valid_inst_list (XCDR (XCAR (rest)), meths, errb))) 1141 if (NILP (check_valid_inst_list (XCDR (spec), meths, errb)))
1159 return Qnil; 1142 return Qnil;
1160 } 1143 }
1161 1144
1162 return Qt; 1145 return Qt;
1163 } 1146 }
1457 static enum spec_add_meth 1440 static enum spec_add_meth
1458 handle_multiple_add_insts (Lisp_Object *inst_list, 1441 handle_multiple_add_insts (Lisp_Object *inst_list,
1459 Lisp_Object new_list, 1442 Lisp_Object new_list,
1460 enum spec_add_meth add_meth) 1443 enum spec_add_meth add_meth)
1461 { 1444 {
1462 if (add_meth == SPEC_REMOVE_TAG_SET_PREPEND || 1445 switch (add_meth)
1463 add_meth == SPEC_REMOVE_TAG_SET_APPEND) 1446 {
1464 { 1447 case SPEC_REMOVE_TAG_SET_APPEND:
1465 Lisp_Object rest; 1448 add_meth = SPEC_APPEND;
1466 1449 goto remove_tag_set;
1467 LIST_LOOP (rest, new_list) 1450 case SPEC_REMOVE_TAG_SET_PREPEND:
1468 { 1451 add_meth = SPEC_PREPEND;
1469 Lisp_Object canontag = canonicalize_tag_set (XCAR (XCAR (rest))); 1452 remove_tag_set:
1470 struct gcpro gcpro1; 1453 {
1471 1454 Lisp_Object rest;
1472 GCPRO1 (canontag); 1455
1473 /* pull out all elements from the existing list with the 1456 LIST_LOOP (rest, new_list)
1474 same tag as any tags in NEW_LIST. */ 1457 {
1475 *inst_list = remassoc_no_quit (canontag, *inst_list); 1458 Lisp_Object canontag = canonicalize_tag_set (XCAR (XCAR (rest)));
1476 UNGCPRO; 1459 struct gcpro gcpro1;
1477 } 1460
1478 if (add_meth == SPEC_REMOVE_TAG_SET_PREPEND) 1461 GCPRO1 (canontag);
1479 return SPEC_PREPEND; 1462 /* pull out all elements from the existing list with the
1480 else 1463 same tag as any tags in NEW_LIST. */
1481 return SPEC_APPEND; 1464 *inst_list = remassoc_no_quit (canontag, *inst_list);
1482 } 1465 UNGCPRO;
1483 else if (add_meth == SPEC_REMOVE_LOCALE) 1466 }
1484 { 1467 }
1468 return add_meth;
1469 case SPEC_REMOVE_LOCALE:
1485 *inst_list = Qnil; 1470 *inst_list = Qnil;
1486 return SPEC_PREPEND; 1471 return SPEC_PREPEND;
1487 } 1472 case SPEC_APPEND:
1488 if (add_meth == SPEC_APPEND) 1473 return add_meth;
1489 return add_meth; 1474 default:
1490 1475 return SPEC_PREPEND;
1491 return SPEC_PREPEND; 1476 }
1492 } 1477 }
1493 1478
1494 /* Given a LOCALE and INST_LIST that is going to be added to SPECIFIER, 1479 /* Given a LOCALE and INST_LIST that is going to be added to SPECIFIER,
1495 copy, canonicalize, and call the going_to_add methods as necessary 1480 copy, canonicalize, and call the going_to_add methods as necessary
1496 to produce a new list that is the one that really will be added 1481 to produce a new list that is the one that really will be added
1500 build_up_processed_list (Lisp_Object specifier, Lisp_Object locale, 1485 build_up_processed_list (Lisp_Object specifier, Lisp_Object locale,
1501 Lisp_Object inst_list) 1486 Lisp_Object inst_list)
1502 { 1487 {
1503 /* The return value of this function must be GCPRO'd. */ 1488 /* The return value of this function must be GCPRO'd. */
1504 Lisp_Object rest, list_to_build_up = Qnil; 1489 Lisp_Object rest, list_to_build_up = Qnil;
1490 struct Lisp_Specifier *sp = XSPECIFIER (specifier);
1505 struct gcpro gcpro1; 1491 struct gcpro gcpro1;
1506 1492
1507 GCPRO1 (list_to_build_up); 1493 GCPRO1 (list_to_build_up);
1508 LIST_LOOP (rest, inst_list) 1494 LIST_LOOP (rest, inst_list)
1509 { 1495 {
1512 Lisp_Object sub_inst_list = Qnil; 1498 Lisp_Object sub_inst_list = Qnil;
1513 struct gcpro ngcpro1, ngcpro2; 1499 struct gcpro ngcpro1, ngcpro2;
1514 1500
1515 NGCPRO2 (instantiator, sub_inst_list); 1501 NGCPRO2 (instantiator, sub_inst_list);
1516 /* call the will-add method; it may GC */ 1502 /* call the will-add method; it may GC */
1517 sub_inst_list = SPECMETH_OR_GIVEN (XSPECIFIER (specifier), going_to_add, 1503 sub_inst_list = HAS_SPECMETH_P (sp, going_to_add) ?
1518 (specifier, locale, tag_set, 1504 SPECMETH (sp, going_to_add,
1519 instantiator), Qt); 1505 (specifier, locale, tag_set, instantiator)) :
1506 Qt;
1520 if (EQ (sub_inst_list, Qt)) 1507 if (EQ (sub_inst_list, Qt))
1521 /* no change here. */ 1508 /* no change here. */
1522 sub_inst_list = list1 (Fcons (canonicalize_tag_set (tag_set), 1509 sub_inst_list = list1 (Fcons (canonicalize_tag_set (tag_set),
1523 instantiator)); 1510 instantiator));
1524 else 1511 else
1549 static void 1536 static void
1550 specifier_add_spec (Lisp_Object specifier, Lisp_Object locale, 1537 specifier_add_spec (Lisp_Object specifier, Lisp_Object locale,
1551 Lisp_Object inst_list, enum spec_add_meth add_meth) 1538 Lisp_Object inst_list, enum spec_add_meth add_meth)
1552 { 1539 {
1553 struct Lisp_Specifier *sp = XSPECIFIER (specifier); 1540 struct Lisp_Specifier *sp = XSPECIFIER (specifier);
1554 enum spec_locale_type type; 1541 enum spec_locale_type type = locale_type_from_locale (locale);
1555 Lisp_Object *orig_inst_list; 1542 Lisp_Object *orig_inst_list, tem;
1556 Lisp_Object list_to_build_up = Qnil; 1543 Lisp_Object list_to_build_up = Qnil;
1557 struct gcpro gcpro1; 1544 struct gcpro gcpro1;
1558
1559 type = locale_type_from_locale (locale);
1560 1545
1561 GCPRO1 (list_to_build_up); 1546 GCPRO1 (list_to_build_up);
1562 list_to_build_up = build_up_processed_list (specifier, locale, inst_list); 1547 list_to_build_up = build_up_processed_list (specifier, locale, inst_list);
1563 /* Now handle REMOVE_LOCALE_TYPE and REMOVE_ALL. These are the 1548 /* Now handle REMOVE_LOCALE_TYPE and REMOVE_ALL. These are the
1564 add-meth types that affect locales other than this one. */ 1549 add-meth types that affect locales other than this one. */
1566 specifier_remove_locale_type (specifier, type, Qnil, 0); 1551 specifier_remove_locale_type (specifier, type, Qnil, 0);
1567 else if (add_meth == SPEC_REMOVE_ALL) 1552 else if (add_meth == SPEC_REMOVE_ALL)
1568 { 1553 {
1569 specifier_remove_locale_type (specifier, LOCALE_BUFFER, Qnil, 0); 1554 specifier_remove_locale_type (specifier, LOCALE_BUFFER, Qnil, 0);
1570 specifier_remove_locale_type (specifier, LOCALE_WINDOW, Qnil, 0); 1555 specifier_remove_locale_type (specifier, LOCALE_WINDOW, Qnil, 0);
1571 specifier_remove_locale_type (specifier, LOCALE_FRAME, Qnil, 0); 1556 specifier_remove_locale_type (specifier, LOCALE_FRAME, Qnil, 0);
1572 specifier_remove_locale_type (specifier, LOCALE_DEVICE, Qnil, 0); 1557 specifier_remove_locale_type (specifier, LOCALE_DEVICE, Qnil, 0);
1573 specifier_remove_spec (specifier, Qglobal, LOCALE_GLOBAL, Qnil, 0); 1558 specifier_remove_spec (specifier, Qglobal, LOCALE_GLOBAL, Qnil, 0);
1574 } 1559 }
1575 1560
1576 orig_inst_list = specifier_get_inst_list (specifier, locale, type); 1561 orig_inst_list = specifier_get_inst_list (specifier, locale, type);
1578 orig_inst_list = specifier_new_spec (specifier, locale, type); 1563 orig_inst_list = specifier_new_spec (specifier, locale, type);
1579 add_meth = handle_multiple_add_insts (orig_inst_list, list_to_build_up, 1564 add_meth = handle_multiple_add_insts (orig_inst_list, list_to_build_up,
1580 add_meth); 1565 add_meth);
1581 1566
1582 if (add_meth == SPEC_PREPEND) 1567 if (add_meth == SPEC_PREPEND)
1583 { 1568 tem = nconc2 (list_to_build_up, *orig_inst_list);
1584 *orig_inst_list = nconc2 (list_to_build_up, *orig_inst_list);
1585 }
1586 else if (add_meth == SPEC_APPEND) 1569 else if (add_meth == SPEC_APPEND)
1587 { 1570 tem = nconc2 (*orig_inst_list, list_to_build_up);
1588 *orig_inst_list = nconc2 (*orig_inst_list, list_to_build_up);
1589 }
1590 else 1571 else
1591 abort (); 1572 abort ();
1573
1574 *orig_inst_list = tem;
1592 1575
1593 UNGCPRO; 1576 UNGCPRO;
1594 1577
1595 /* call the after-change method */ 1578 /* call the after-change method */
1596 MAYBE_SPECMETH (sp, after_change, (specifier, locale)); 1579 MAYBE_SPECMETH (sp, after_change, (specifier, locale));
1823 add_meth = decode_how_to_add_specification (how_to_add); 1806 add_meth = decode_how_to_add_specification (how_to_add);
1824 1807
1825 LIST_LOOP (rest, spec_list) 1808 LIST_LOOP (rest, spec_list)
1826 { 1809 {
1827 /* Placating the GCC god. */ 1810 /* Placating the GCC god. */
1828 Lisp_Object crock1 = specifier; 1811 Lisp_Object specification = XCAR (rest);
1829 Lisp_Object crock2 = XCAR (XCAR (rest)); 1812 Lisp_Object locale = XCAR (specification);
1830 Lisp_Object crock3 = XCDR (XCAR (rest)); 1813 Lisp_Object inst_list = XCDR (specification);
1831 1814
1832 specifier_add_spec (crock1, crock2, crock3, add_meth); 1815 specifier_add_spec (specifier, locale, inst_list, add_meth);
1833 } 1816 }
1834 recompute_cached_specifier_everywhere (specifier); 1817 recompute_cached_specifier_everywhere (specifier);
1835 return Qnil; 1818 return Qnil;
1836 } 1819 }
1837 1820
1907 result is as if `specifier-spec-list' were called on each element of the 1890 result is as if `specifier-spec-list' were called on each element of the
1908 list and the results concatenated together. 1891 list and the results concatenated together.
1909 1892
1910 Only instantiators where TAG-SET (a list of zero or more tags) is a 1893 Only instantiators where TAG-SET (a list of zero or more tags) is a
1911 subset of (or possibly equal to) the instantiator's tag set are returned. 1894 subset of (or possibly equal to) the instantiator's tag set are returned.
1912 (The default value of nil is a subset of all tag sets, so in this case 1895 \(The default value of nil is a subset of all tag sets, so in this case
1913 no instantiators will be screened out.) If EXACT-P is non-nil, however, 1896 no instantiators will be screened out.) If EXACT-P is non-nil, however,
1914 TAG-SET must be equal to an instantiator's tag set for the instantiator 1897 TAG-SET must be equal to an instantiator's tag set for the instantiator
1915 to be returned. 1898 to be returned.
1916 */ 1899 */
1917 (specifier, locale, tag_set, exact_p)) 1900 (specifier, locale, tag_set, exact_p))
2272 2255
2273 if (HAS_SPECMETH_P (sp, instantiate)) 2256 if (HAS_SPECMETH_P (sp, instantiate))
2274 val = call_with_suspended_errors 2257 val = call_with_suspended_errors
2275 ((lisp_fn_t) RAW_SPECMETH (sp, instantiate), 2258 ((lisp_fn_t) RAW_SPECMETH (sp, instantiate),
2276 Qunbound, Qspecifier, errb, 5, specifier, 2259 Qunbound, Qspecifier, errb, 5, specifier,
2277 matchspec, domain, XCDR (tagged_inst), depth); 2260 matchspec, domain, val, depth);
2278 2261
2279 if (!UNBOUNDP (val)) 2262 if (!UNBOUNDP (val))
2280 { 2263 {
2281 unbind_to (count, Qnil); 2264 unbind_to (count, Qnil);
2282 UNGCPRO; 2265 UNGCPRO;
2547 2530
2548 DEFUN ("specifier-matching-instance-from-inst-list", 2531 DEFUN ("specifier-matching-instance-from-inst-list",
2549 Fspecifier_matching_instance_from_inst_list, 4, 5, 0, /* 2532 Fspecifier_matching_instance_from_inst_list, 4, 5, 0, /*
2550 Attempt to convert a particular inst-list into an instance. 2533 Attempt to convert a particular inst-list into an instance.
2551 This attempts to instantiate INST-LIST in the given DOMAIN 2534 This attempts to instantiate INST-LIST in the given DOMAIN
2552 (as if INST-LIST existed in a specification in SPECIFIER), 2535 \(as if INST-LIST existed in a specification in SPECIFIER),
2553 matching the specifications against MATCHSPEC. 2536 matching the specifications against MATCHSPEC.
2554 2537
2555 This function is analogous to `specifier-instance-from-inst-list' 2538 This function is analogous to `specifier-instance-from-inst-list'
2556 but allows for specification-matching as in `specifier-matching-instance'. 2539 but allows for specification-matching as in `specifier-matching-instance'.
2557 See that function for a description of exactly how the matching process 2540 See that function for a description of exactly how the matching process
2614 2597
2615 static void 2598 static void
2616 recompute_one_cached_specifier_in_window (Lisp_Object specifier, 2599 recompute_one_cached_specifier_in_window (Lisp_Object specifier,
2617 struct window *w) 2600 struct window *w)
2618 { 2601 {
2619 Lisp_Object window = Qnil; 2602 Lisp_Object window;
2620 Lisp_Object newval, *location; 2603 Lisp_Object newval, *location;
2621 2604
2622 XSETWINDOW (window, w); 2605 XSETWINDOW (window, w);
2623 2606
2624 newval = specifier_instance (specifier, Qunbound, window, ERROR_ME_WARN, 2607 newval = specifier_instance (specifier, Qunbound, window, ERROR_ME_WARN,
2640 2623
2641 static void 2624 static void
2642 recompute_one_cached_specifier_in_frame (Lisp_Object specifier, 2625 recompute_one_cached_specifier_in_frame (Lisp_Object specifier,
2643 struct frame *f) 2626 struct frame *f)
2644 { 2627 {
2645 Lisp_Object frame = Qnil; 2628 Lisp_Object frame;
2646 Lisp_Object newval, *location; 2629 Lisp_Object newval, *location;
2647 2630
2648 XSETFRAME (frame, f); 2631 XSETFRAME (frame, f);
2649 2632
2650 newval = specifier_instance (specifier, Qunbound, frame, ERROR_ME_WARN, 2633 newval = specifier_instance (specifier, Qunbound, frame, ERROR_ME_WARN,