XEmacs 21.2-b1
[chise/xemacs-chise.git.1] / src / specifier.c
1 /* Specifier implementation
2    Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
3    Copyright (C) 1995, 1996 Ben Wing.
4    Copyright (C) 1995 Sun Microsystems, Inc.
5
6 This file is part of XEmacs.
7
8 XEmacs is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
11 later version.
12
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with XEmacs; see the file COPYING.  If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.  */
22
23 /* Synched up with: Not in FSF. */
24
25 /* Design by Ben Wing;
26    Original version by Chuck Thompson;
27    rewritten by Ben Wing;
28    Magic specifiers by Kirill Katsnelson;
29 */
30
31 #include <config.h>
32 #include "lisp.h"
33
34 #include "buffer.h"
35 #include "device.h"
36 #include "frame.h"
37 #include "opaque.h"
38 #include "specifier.h"
39 #include "window.h"
40 #include "glyphs.h"  /* for DISP_TABLE_SIZE definition */
41
42 Lisp_Object Qspecifierp;
43 Lisp_Object Qprepend, Qappend, Qremove_tag_set_prepend, Qremove_tag_set_append;
44 Lisp_Object Qremove_locale, Qremove_locale_type, Qremove_all;
45 Lisp_Object Qfallback;
46
47 /* Qinteger, Qboolean, Qgeneric defined in general.c. */
48 Lisp_Object Qnatnum;
49
50 Lisp_Object Qconsole_type, Qdevice_class;
51
52 static Lisp_Object Vuser_defined_tags;
53
54 typedef struct specifier_type_entry specifier_type_entry;
55 struct specifier_type_entry
56 {
57   Lisp_Object symbol;
58   struct specifier_methods *meths;
59 };
60
61 typedef struct
62 {
63   Dynarr_declare (specifier_type_entry);
64 } specifier_type_entry_dynarr;
65
66 specifier_type_entry_dynarr *the_specifier_type_entry_dynarr;
67
68 static Lisp_Object Vspecifier_type_list;
69
70 static Lisp_Object Vcached_specifiers;
71 /* Do NOT mark through this, or specifiers will never be GC'd. */
72 static Lisp_Object Vall_specifiers;
73
74 static Lisp_Object Vunlock_ghost_specifiers;
75
76 /* #### The purpose of this is to check for inheritance loops
77    in specifiers that can inherit from other specifiers, but it's
78    not yet implemented.
79
80    #### Look into this for 19.14. */
81 /* static Lisp_Object_dynarr current_specifiers; */
82
83 static void recompute_cached_specifier_everywhere (Lisp_Object specifier);
84
85 EXFUN (Fspecifier_specs, 4);
86 EXFUN (Fremove_specifier, 4);
87
88 \f
89 /************************************************************************/
90 /*                       Specifier object methods                       */
91 /************************************************************************/
92
93 /* Remove dead objects from the specified assoc list. */
94
95 static Lisp_Object
96 cleanup_assoc_list (Lisp_Object list)
97 {
98   Lisp_Object loop, prev, retval;
99
100   loop = retval = list;
101   prev = Qnil;
102
103   while (!NILP (loop))
104     {
105       Lisp_Object entry = XCAR (loop);
106       Lisp_Object key = XCAR (entry);
107
108       /* remember, dead windows can become alive again. */
109       if (!WINDOWP (key) && object_dead_p (key))
110         {
111           if (NILP (prev))
112             {
113               /* Removing the head. */
114               retval = XCDR (retval);
115             }
116           else
117             {
118               Fsetcdr (prev, XCDR (loop));
119             }
120         }
121       else
122         prev = loop;
123
124       loop = XCDR (loop);
125     }
126
127   return retval;
128 }
129
130 /* Remove dead objects from the various lists so that they
131    don't keep getting marked as long as this specifier exists and
132    therefore wasting memory. */
133
134 void
135 cleanup_specifiers (void)
136 {
137   Lisp_Object rest;
138
139   for (rest = Vall_specifiers;
140        !NILP (rest);
141        rest = XSPECIFIER (rest)->next_specifier)
142     {
143       struct Lisp_Specifier *sp = XSPECIFIER (rest);
144       /* This effectively changes the specifier specs.
145          However, there's no need to call
146          recompute_cached_specifier_everywhere() or the
147          after-change methods because the only specs we
148          are removing are for dead objects, and they can
149          never have any effect on the specifier values:
150          specifiers can only be instantiated over live
151          objects, and you can't derive a dead object
152          from a live one. */
153       sp->device_specs = cleanup_assoc_list (sp->device_specs);
154       sp->frame_specs = cleanup_assoc_list (sp->frame_specs);
155       sp->buffer_specs = cleanup_assoc_list (sp->buffer_specs);
156       /* windows are handled specially because dead windows
157          can be resurrected */
158     }
159 }
160
161 void
162 kill_specifier_buffer_locals (Lisp_Object buffer)
163 {
164   Lisp_Object rest;
165
166   for (rest = Vall_specifiers;
167        !NILP (rest);
168        rest = XSPECIFIER (rest)->next_specifier)
169     {
170       struct Lisp_Specifier *sp = XSPECIFIER (rest);
171
172       /* Make sure we're actually going to be changing something.
173          Fremove_specifier() always calls
174          recompute_cached_specifier_everywhere() (#### but should
175          be smarter about this). */
176       if (!NILP (assq_no_quit (buffer, sp->buffer_specs)))
177         Fremove_specifier (rest, buffer, Qnil, Qnil);
178     }
179 }
180
181 static Lisp_Object
182 mark_specifier (Lisp_Object obj, void (*markobj) (Lisp_Object))
183 {
184   struct Lisp_Specifier *specifier = XSPECIFIER (obj);
185
186   ((markobj) (specifier->global_specs));
187   ((markobj) (specifier->device_specs));
188   ((markobj) (specifier->frame_specs));
189   ((markobj) (specifier->window_specs));
190   ((markobj) (specifier->buffer_specs));
191   ((markobj) (specifier->magic_parent));
192   ((markobj) (specifier->fallback));
193   if (!GHOST_SPECIFIER_P (XSPECIFIER (obj)))
194     MAYBE_SPECMETH (specifier, mark, (obj, markobj));
195   return Qnil;
196 }
197
198 /* The idea here is that the specifier specs point to locales
199    (windows, buffers, frames, and devices), and we want to make sure
200    that the specs disappear automatically when the associated locale
201    is no longer in use.  For all but windows, "no longer in use"
202    corresponds exactly to when the object is deleted (non-deleted
203    objects are always held permanently in special lists, and deleted
204    objects are never on these lists and never reusable).  To handle
205    this, we just have cleanup_specifiers() called periodically
206    (at the beginning of garbage collection); it removes all dead
207    objects.
208
209    For windows, however, it's trickier because dead objects can be
210    converted to live ones again if the dead object is in a window
211    configuration.  Therefore, for windows, "no longer in use"
212    corresponds to when the window object is garbage-collected.
213    We now use weak lists for this purpose.
214
215 */
216
217 void
218 prune_specifiers (int (*obj_marked_p) (Lisp_Object))
219 {
220   Lisp_Object rest, prev = Qnil;
221
222   for (rest = Vall_specifiers;
223        !GC_NILP (rest);
224        rest = XSPECIFIER (rest)->next_specifier)
225     {
226       if (! ((*obj_marked_p) (rest)))
227         {
228           struct Lisp_Specifier* sp = XSPECIFIER (rest);
229           /* A bit of assertion that we're removing both parts of the
230              magic one altogether */
231           assert (!GC_MAGIC_SPECIFIER_P(sp)
232                   || (GC_BODILY_SPECIFIER_P(sp) && (*obj_marked_p)(sp->fallback))
233                   || (GC_GHOST_SPECIFIER_P(sp) && (*obj_marked_p)(sp->magic_parent)));
234           /* This specifier is garbage.  Remove it from the list. */
235           if (GC_NILP (prev))
236             Vall_specifiers = sp->next_specifier;
237           else
238             XSPECIFIER (prev)->next_specifier = sp->next_specifier;
239         }
240       else
241         prev = rest;
242     }
243 }
244
245 static void
246 print_specifier (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
247 {
248   struct Lisp_Specifier *sp = XSPECIFIER (obj);
249   char buf[100];
250   int count = specpdl_depth ();
251   Lisp_Object the_specs;
252
253   if (print_readably)
254     error ("printing unreadable object #<%s-specifier 0x%x>",
255            sp->methods->name, sp->header.uid);
256
257   sprintf (buf, "#<%s-specifier global=", sp->methods->name);
258   write_c_string (buf, printcharfun);
259   specbind (Qprint_string_length, make_int (100));
260   specbind (Qprint_length, make_int (5));
261   the_specs = Fspecifier_specs (obj, Qglobal, Qnil, Qnil);
262   if (NILP (the_specs))
263     /* there are no global specs */
264     write_c_string ("<unspecified>", printcharfun);
265   else
266     print_internal (the_specs, printcharfun, 1);
267   if (!NILP (sp->fallback))
268     {
269       write_c_string (" fallback=", printcharfun);
270       print_internal (sp->fallback, printcharfun, escapeflag);
271     }
272   unbind_to (count, Qnil);
273   sprintf (buf, " 0x%x>", sp->header.uid);
274   write_c_string (buf, printcharfun);
275 }
276
277 static void
278 finalize_specifier (void *header, int for_disksave)
279 {
280   struct Lisp_Specifier *sp = (struct Lisp_Specifier *) header;
281   /* don't be snafued by the disksave finalization. */
282   if (!for_disksave && !GC_GHOST_SPECIFIER_P(sp) && sp->caching)
283     {
284       xfree (sp->caching);
285       sp->caching = 0;
286     }
287 }
288
289 static int
290 specifier_equal (Lisp_Object o1, Lisp_Object o2, int depth)
291 {
292   struct Lisp_Specifier *s1 = XSPECIFIER (o1);
293   struct Lisp_Specifier *s2 = XSPECIFIER (o2);
294   int retval;
295   Lisp_Object old_inhibit_quit = Vinhibit_quit;
296
297   /* This function can be called from within redisplay.
298      internal_equal can trigger a quit.  That leads to Bad Things. */
299   Vinhibit_quit = Qt;
300
301   depth++;
302   retval =
303     (s1->methods == s2->methods &&
304      internal_equal (s1->global_specs, s2->global_specs, depth) &&
305      internal_equal (s1->device_specs, s2->device_specs, depth) &&
306      internal_equal (s1->frame_specs,  s2->frame_specs,  depth) &&
307      internal_equal (s1->window_specs, s2->window_specs, depth) &&
308      internal_equal (s1->buffer_specs, s2->buffer_specs, depth) &&
309      internal_equal (s1->fallback,     s2->fallback,     depth));
310
311   if (retval && HAS_SPECMETH_P (s1, equal))
312     retval = SPECMETH (s1, equal, (o1, o2, depth - 1));
313
314   Vinhibit_quit = old_inhibit_quit;
315   return retval;
316 }
317
318 static unsigned long
319 specifier_hash (Lisp_Object obj, int depth)
320 {
321   struct Lisp_Specifier *s = XSPECIFIER (obj);
322
323   /* specifier hashing is a bit problematic because there are so
324      many places where data can be stored.  We pick what are perhaps
325      the most likely places where interesting stuff will be. */
326   return HASH5 ((HAS_SPECMETH_P (s, hash) ?
327                  SPECMETH (s, hash, (obj, depth)) : 0),
328                 (unsigned long) s->methods,
329                 internal_hash (s->global_specs, depth + 1),
330                 internal_hash (s->frame_specs,  depth + 1),
331                 internal_hash (s->buffer_specs, depth + 1));
332 }
333
334 static size_t
335 sizeof_specifier (CONST void *header)
336 {
337   if (GHOST_SPECIFIER_P ((struct Lisp_Specifier *) header))
338     return sizeof (struct Lisp_Specifier);
339   else
340     {
341       CONST struct Lisp_Specifier *p = (CONST struct Lisp_Specifier *) header;
342       return sizeof (*p) + p->methods->extra_data_size - 1;
343     }
344 }
345
346 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("specifier", specifier,
347                                         mark_specifier, print_specifier,
348                                         finalize_specifier,
349                                         specifier_equal, specifier_hash,
350                                         sizeof_specifier,
351                                         struct Lisp_Specifier);
352 \f
353 /************************************************************************/
354 /*                       Creating specifiers                            */
355 /************************************************************************/
356
357 static struct specifier_methods *
358 decode_specifier_type (Lisp_Object type, Error_behavior errb)
359 {
360   int i;
361
362   for (i = 0; i < Dynarr_length (the_specifier_type_entry_dynarr); i++)
363     {
364       if (EQ (type, Dynarr_at (the_specifier_type_entry_dynarr, i).symbol))
365         return Dynarr_at (the_specifier_type_entry_dynarr, i).meths;
366     }
367
368   maybe_signal_simple_error ("Invalid specifier type", type,
369                              Qspecifier, errb);
370
371   return 0;
372 }
373
374 static int
375 valid_specifier_type_p (Lisp_Object type)
376 {
377   return decode_specifier_type (type, ERROR_ME_NOT) != 0;
378 }
379
380 DEFUN ("valid-specifier-type-p", Fvalid_specifier_type_p, 1, 1, 0, /*
381 Given a SPECIFIER-TYPE, return non-nil if it is valid.
382 Valid types are 'generic, 'integer, boolean, 'color, 'font, 'image,
383 'face-boolean, and 'toolbar.
384 */
385        (specifier_type))
386 {
387   return valid_specifier_type_p (specifier_type) ? Qt : Qnil;
388 }
389
390 DEFUN ("specifier-type-list", Fspecifier_type_list, 0, 0, 0, /*
391 Return a list of valid specifier types.
392 */
393        ())
394 {
395   return Fcopy_sequence (Vspecifier_type_list);
396 }
397
398 void
399 add_entry_to_specifier_type_list (Lisp_Object symbol,
400                                   struct specifier_methods *meths)
401 {
402   struct specifier_type_entry entry;
403
404   entry.symbol = symbol;
405   entry.meths = meths;
406   Dynarr_add (the_specifier_type_entry_dynarr, entry);
407   Vspecifier_type_list = Fcons (symbol, Vspecifier_type_list);
408 }
409
410 static Lisp_Object
411 make_specifier_internal (struct specifier_methods *spec_meths,
412                          size_t data_size, int call_create_meth)
413 {
414   Lisp_Object specifier;
415   struct Lisp_Specifier *sp = (struct Lisp_Specifier *)
416     alloc_lcrecord (sizeof (struct Lisp_Specifier) +
417                     data_size - 1, lrecord_specifier);
418
419   sp->methods = spec_meths;
420   sp->global_specs = Qnil;
421   sp->device_specs = Qnil;
422   sp->frame_specs = Qnil;
423   sp->window_specs = make_weak_list (WEAK_LIST_KEY_ASSOC);
424   sp->buffer_specs = Qnil;
425   sp->fallback = Qnil;
426   sp->magic_parent = Qnil;
427   sp->caching = 0;
428   sp->next_specifier = Vall_specifiers;
429
430   XSETSPECIFIER (specifier, sp);
431   Vall_specifiers = specifier;
432
433   if (call_create_meth)
434     {
435       struct gcpro gcpro1;
436       GCPRO1 (specifier);
437       MAYBE_SPECMETH (XSPECIFIER (specifier), create, (specifier));
438       UNGCPRO;
439     }
440   return specifier;
441 }
442
443 static Lisp_Object
444 make_specifier (struct specifier_methods *meths)
445 {
446   return make_specifier_internal (meths, meths->extra_data_size, 1);
447 }
448
449 Lisp_Object
450 make_magic_specifier (Lisp_Object type)
451 {
452   /* This function can GC */
453   struct specifier_methods *meths = decode_specifier_type (type, ERROR_ME);
454   Lisp_Object bodily, ghost;
455   struct gcpro gcpro1;
456
457   bodily = make_specifier (meths);
458   GCPRO1 (bodily);
459   ghost  = make_specifier_internal (meths, 0, 0);
460   UNGCPRO;
461
462   /* Connect guys together */
463   XSPECIFIER(bodily)->magic_parent = Qt;
464   XSPECIFIER(bodily)->fallback = ghost;
465   XSPECIFIER(ghost)->magic_parent = bodily;
466
467   return bodily;
468 }
469
470 DEFUN ("make-specifier", Fmake_specifier, 1, 1, 0, /*
471 Return a new specifier object of type TYPE.
472
473 A specifier is an object that can be used to keep track of a property
474 whose value can be per-buffer, per-window, per-frame, or per-device,
475 and can further be restricted to a particular console-type or device-class.
476 Specifiers are used, for example, for the various built-in properties of a
477 face; this allows a face to have different values in different frames,
478 buffers, etc.  For more information, see `specifier-instance',
479 `specifier-specs', and `add-spec-to-specifier'; or, for a detailed
480 description of specifiers, including how they are instantiated over a
481 particular domain (i.e. how their value in that domain is determined),
482 see the chapter on specifiers in the XEmacs Lisp Reference Manual.
483
484 TYPE specifies the particular type of specifier, and should be one of
485 the symbols 'generic, 'integer, 'boolean, 'color, 'font, 'image,
486 'face-boolean, or 'toolbar.
487
488 For more information on particular types of specifiers, see the functions
489 `generic-specifier-p', `integer-specifier-p', `boolean-specifier-p',
490 `color-specifier-p', `font-specifier-p', `image-specifier-p',
491 `face-boolean-specifier-p', and `toolbar-specifier-p'.
492 */
493        (type))
494 {
495   /* This function can GC */
496   struct specifier_methods *meths = decode_specifier_type (type,
497                                                            ERROR_ME);
498
499   return make_specifier (meths);
500 }
501
502 DEFUN ("specifierp", Fspecifierp, 1, 1, 0, /*
503 Return t if OBJECT is a specifier.
504
505 A specifier is an object that can be used to keep track of a property
506 whose value can be per-buffer, per-window, per-frame, or per-device,
507 and can further be restricted to a particular console-type or device-class.
508 See `make-specifier'.
509 */
510        (object))
511 {
512   return SPECIFIERP (object) ? Qt : Qnil;
513 }
514
515 DEFUN ("specifier-type", Fspecifier_type, 1, 1, 0, /*
516 Return the type of SPECIFIER.
517 */
518        (specifier))
519 {
520   CHECK_SPECIFIER (specifier);
521   return intern (XSPECIFIER (specifier)->methods->name);
522 }
523
524 \f
525 /************************************************************************/
526 /*                       Locales and domains                            */
527 /************************************************************************/
528
529 DEFUN ("valid-specifier-locale-p", Fvalid_specifier_locale_p, 1, 1, 0, /*
530 Return t if LOCALE is a valid specifier locale.
531 Valid locales are devices, frames, windows, buffers, and 'global.
532 \(nil is not valid.)
533 */
534        (locale))
535 {
536   /* This cannot GC. */
537   return ((DEVICEP (locale) && DEVICE_LIVE_P (XDEVICE (locale))) ||
538           (FRAMEP  (locale) && FRAME_LIVE_P  (XFRAME  (locale))) ||
539           (BUFFERP (locale) && BUFFER_LIVE_P (XBUFFER (locale))) ||
540           /* dead windows are allowed because they may become live
541              windows again when a window configuration is restored */
542           WINDOWP (locale) ||
543           EQ (locale, Qglobal))
544     ? Qt : Qnil;
545 }
546
547 DEFUN ("valid-specifier-domain-p", Fvalid_specifier_domain_p, 1, 1, 0, /*
548 Return t if DOMAIN is a valid specifier domain.
549 A domain is used to instance a specifier (i.e. determine the specifier's
550 value in that domain).  Valid domains are windows, frames, and devices.
551 \(nil is not valid.)
552 */
553      (domain))
554 {
555   /* This cannot GC. */
556   return ((DEVICEP (domain) && DEVICE_LIVE_P (XDEVICE (domain))) ||
557           (FRAMEP  (domain) && FRAME_LIVE_P  (XFRAME  (domain))) ||
558           (WINDOWP (domain) && WINDOW_LIVE_P (XWINDOW (domain))))
559     ? Qt : Qnil;
560 }
561
562 DEFUN ("valid-specifier-locale-type-p", Fvalid_specifier_locale_type_p, 1, 1, 0, /*
563 Given a specifier LOCALE-TYPE, return non-nil if it is valid.
564 Valid locale types are 'global, 'device, 'frame, 'window, and 'buffer.
565 \(Note, however, that in functions that accept either a locale or a locale
566 type, 'global is considered an individual locale.)
567 */
568      (locale_type))
569 {
570   /* This cannot GC. */
571   return (EQ (locale_type, Qglobal) ||
572           EQ (locale_type, Qdevice) ||
573           EQ (locale_type, Qframe)  ||
574           EQ (locale_type, Qwindow) ||
575           EQ (locale_type, Qbuffer)) ? Qt : Qnil;
576 }
577
578 static void
579 check_valid_locale_or_locale_type (Lisp_Object locale)
580 {
581   /* This cannot GC. */
582   if (EQ (locale, Qall) ||
583       !NILP (Fvalid_specifier_locale_p (locale)) ||
584       !NILP (Fvalid_specifier_locale_type_p (locale)))
585     return;
586   signal_simple_error ("Invalid specifier locale or locale type", locale);
587 }
588
589 DEFUN ("specifier-locale-type-from-locale", Fspecifier_locale_type_from_locale,
590        1, 1, 0, /*
591 Given a specifier LOCALE, return its type.
592 */
593        (locale))
594 {
595   /* This cannot GC. */
596   if (NILP (Fvalid_specifier_locale_p (locale)))
597     signal_simple_error ("Invalid specifier locale", locale);
598   if (DEVICEP (locale)) return Qdevice;
599   if (FRAMEP  (locale)) return Qframe;
600   if (WINDOWP (locale)) return Qwindow;
601   if (BUFFERP (locale)) return Qbuffer;
602   assert (EQ (locale, Qglobal));
603   return Qglobal;
604 }
605
606 static Lisp_Object
607 decode_locale (Lisp_Object locale)
608 {
609   /* This cannot GC. */
610   if (NILP (locale))
611     return Qglobal;
612   else if (!NILP (Fvalid_specifier_locale_p (locale)))
613     return locale;
614   else
615     signal_simple_error ("Invalid specifier locale", locale);
616
617   return Qnil;
618 }
619
620 static enum spec_locale_type
621 decode_locale_type (Lisp_Object locale_type)
622 {
623   /* This cannot GC. */
624   if (EQ (locale_type, Qglobal)) return LOCALE_GLOBAL;
625   if (EQ (locale_type, Qdevice)) return LOCALE_DEVICE;
626   if (EQ (locale_type, Qframe))  return LOCALE_FRAME;
627   if (EQ (locale_type, Qwindow)) return LOCALE_WINDOW;
628   if (EQ (locale_type, Qbuffer)) return LOCALE_BUFFER;
629
630   signal_simple_error ("Invalid specifier locale type", locale_type);
631   return LOCALE_GLOBAL; /* not reached */
632 }
633
634 Lisp_Object
635 decode_locale_list (Lisp_Object locale)
636 {
637   /* This cannot GC. */
638   /* The return value of this function must be GCPRO'd. */
639   if (NILP (locale))
640     locale = list1 (Qall);
641   else
642     {
643       Lisp_Object rest;
644       if (!CONSP (locale))
645         locale = list1 (locale);
646       EXTERNAL_LIST_LOOP (rest, locale)
647         check_valid_locale_or_locale_type (XCAR (rest));
648     }
649   return locale;
650 }
651
652 static enum spec_locale_type
653 locale_type_from_locale (Lisp_Object locale)
654 {
655   return decode_locale_type (Fspecifier_locale_type_from_locale (locale));
656 }
657
658 static void
659 check_valid_domain (Lisp_Object domain)
660 {
661   if (NILP (Fvalid_specifier_domain_p (domain)))
662     signal_simple_error ("Invalid specifier domain", domain);
663 }
664
665 static Lisp_Object
666 decode_domain (Lisp_Object domain)
667 {
668   if (NILP (domain))
669     return Fselected_window (Qnil);
670   check_valid_domain (domain);
671   return domain;
672 }
673
674 \f
675 /************************************************************************/
676 /*                                 Tags                                 */
677 /************************************************************************/
678
679 DEFUN ("valid-specifier-tag-p", Fvalid_specifier_tag_p, 1, 1, 0, /*
680 Return non-nil if TAG is a valid specifier tag.
681 See also `valid-specifier-tag-set-p'.
682 */
683        (tag))
684 {
685   return (valid_console_type_p (tag) ||
686           valid_device_class_p (tag) ||
687           !NILP (assq_no_quit (tag, Vuser_defined_tags))) ? Qt : Qnil;
688 }
689
690 DEFUN ("valid-specifier-tag-set-p", Fvalid_specifier_tag_set_p, 1, 1, 0, /*
691 Return non-nil if TAG-SET is a valid specifier tag set.
692
693 A specifier tag set is an entity that is attached to an instantiator
694 and can be used to restrict the scope of that instantiator to a
695 particular device class or device type and/or to mark instantiators
696 added by a particular package so that they can be later removed.
697
698 A specifier tag set consists of a list of zero of more specifier tags,
699 each of which is a symbol that is recognized by XEmacs as a tag.
700 \(The valid device types and device classes are always tags, as are
701 any tags defined by `define-specifier-tag'.) It is called a "tag set"
702 \(as opposed to a list) because the order of the tags or the number of
703 times a particular tag occurs does not matter.
704
705 Each tag has a predicate associated with it, which specifies whether
706 that tag applies to a particular device.  The tags which are device types
707 and classes match devices of that type or class.  User-defined tags can
708 have any predicate, or none (meaning that all devices match).  When
709 attempting to instance a specifier, a particular instantiator is only
710 considered if the device of the domain being instanced over matches
711 all tags in the tag set attached to that instantiator.
712
713 Most of the time, a tag set is not specified, and the instantiator
714 gets a null tag set, which matches all devices.
715 */
716      (tag_set))
717 {
718   Lisp_Object rest;
719
720   for (rest = tag_set; !NILP (rest); rest = XCDR (rest))
721     {
722       if (!CONSP (rest))
723         return Qnil;
724       if (NILP (Fvalid_specifier_tag_p (XCAR (rest))))
725         return Qnil;
726       QUIT;
727     }
728   return Qt;
729 }
730
731 Lisp_Object
732 decode_specifier_tag_set (Lisp_Object tag_set)
733 {
734   /* The return value of this function must be GCPRO'd. */
735   if (!NILP (Fvalid_specifier_tag_p (tag_set)))
736     return list1 (tag_set);
737   if (NILP (Fvalid_specifier_tag_set_p (tag_set)))
738     signal_simple_error ("Invalid specifier tag-set", tag_set);
739   return tag_set;
740 }
741
742 static Lisp_Object
743 canonicalize_tag_set (Lisp_Object tag_set)
744 {
745   int len = XINT (Flength (tag_set));
746   Lisp_Object *tags, rest;
747   int i, j;
748
749   /* We assume in this function that the tag_set has already been
750      validated, so there are no surprises. */
751
752   if (len == 0 || len == 1)
753     /* most common case */
754     return tag_set;
755
756   tags = alloca_array (Lisp_Object, len);
757
758   i = 0;
759   LIST_LOOP (rest, tag_set)
760     tags[i++] = XCAR (rest);
761
762   /* Sort the list of tags.  We use a bubble sort here (copied from
763      extent_fragment_update()) -- reduces the function call overhead,
764      and is the fastest sort for small numbers of items. */
765
766   for (i = 1; i < len; i++)
767     {
768       j = i - 1;
769       while (j >= 0 &&
770              strcmp ((char *) string_data (XSYMBOL (tags[j])->name),
771                      (char *) string_data (XSYMBOL (tags[j+1])->name)) > 0)
772         {
773           Lisp_Object tmp = tags[j];
774           tags[j] = tags[j+1];
775           tags[j+1] = tmp;
776           j--;
777         }
778     }
779
780   /* Now eliminate duplicates. */
781
782   for (i = 1, j = 1; i < len; i++)
783     {
784       /* j holds the destination, i the source. */
785       if (!EQ (tags[i], tags[i-1]))
786         tags[j++] = tags[i];
787     }
788
789   return Flist (j, tags);
790 }
791
792 DEFUN ("canonicalize-tag-set", Fcanonicalize_tag_set, 1, 1, 0, /*
793 Canonicalize the given tag set.
794 Two canonicalized tag sets can be compared with `equal' to see if they
795 represent the same tag set. (Specifically, canonicalizing involves
796 sorting by symbol name and removing duplicates.)
797 */
798        (tag_set))
799 {
800   if (NILP (Fvalid_specifier_tag_set_p (tag_set)))
801     signal_simple_error ("Invalid tag set", tag_set);
802   return canonicalize_tag_set (tag_set);
803 }
804
805 static int
806 device_matches_specifier_tag_set_p (Lisp_Object device, Lisp_Object tag_set)
807 {
808   Lisp_Object devtype, devclass, rest;
809   struct device *d = XDEVICE (device);
810
811   devtype = DEVICE_TYPE (d);
812   devclass = DEVICE_CLASS (d);
813
814   LIST_LOOP (rest, tag_set)
815     {
816       Lisp_Object tag = XCAR (rest);
817       Lisp_Object assoc;
818
819       if (EQ (tag, devtype) || EQ (tag, devclass))
820         continue;
821       assoc = assq_no_quit (tag, DEVICE_USER_DEFINED_TAGS (d));
822       /* other built-in tags (device types/classes) are not in
823          the user-defined-tags list. */
824       if (NILP (assoc) || NILP (XCDR (assoc)))
825         return 0;
826     }
827
828   return 1;
829 }
830
831 DEFUN ("device-matches-specifier-tag-set-p", Fdevice_matches_specifier_tag_set_p, 2, 2, 0, /*
832 Return non-nil if DEVICE matches specifier tag set TAG-SET.
833 This means that DEVICE matches each tag in the tag set. (Every
834 tag recognized by XEmacs has a predicate associated with it that
835 specifies which devices match it.)
836 */
837        (device, tag_set))
838 {
839   CHECK_LIVE_DEVICE (device);
840
841   if (NILP (Fvalid_specifier_tag_set_p (tag_set)))
842     signal_simple_error ("Invalid tag set", tag_set);
843
844   return device_matches_specifier_tag_set_p (device, tag_set) ? Qt : Qnil;
845 }
846
847 DEFUN ("define-specifier-tag", Fdefine_specifier_tag, 1, 2, 0, /*
848 Define a new specifier tag.
849 If PREDICATE is specified, it should be a function of one argument
850 \(a device) that specifies whether the tag matches that particular
851 device.  If PREDICATE is omitted, the tag matches all devices.
852
853 You can redefine an existing user-defined specifier tag.  However,
854 you cannot redefine the built-in specifier tags (the device types
855 and classes) or the symbols nil, t, 'all, or 'global.
856 */
857        (tag, predicate))
858 {
859   Lisp_Object assoc, devcons, concons;
860   int recompute = 0;
861
862   CHECK_SYMBOL (tag);
863   if (valid_device_class_p (tag) ||
864       valid_console_type_p (tag))
865     signal_simple_error ("Cannot redefine built-in specifier tags", tag);
866   /* Try to prevent common instantiators and locales from being
867      redefined, to reduce ambiguity */
868   if (NILP (tag) || EQ (tag, Qt) || EQ (tag, Qall) || EQ (tag, Qglobal))
869     signal_simple_error ("Cannot define nil, t, 'all, or 'global",
870                          tag);
871   assoc = assq_no_quit (tag, Vuser_defined_tags);
872   if (NILP (assoc))
873     {
874       recompute = 1;
875       Vuser_defined_tags = Fcons (Fcons (tag, predicate), Vuser_defined_tags);
876       DEVICE_LOOP_NO_BREAK (devcons, concons)
877         {
878           struct device *d = XDEVICE (XCAR (devcons));
879           /* Initially set the value to t in case of error
880              in predicate */
881           DEVICE_USER_DEFINED_TAGS (d) =
882             Fcons (Fcons (tag, Qt), DEVICE_USER_DEFINED_TAGS (d));
883         }
884     }
885   else if (!NILP (predicate) && !NILP (XCDR (assoc)))
886     {
887       recompute = 1;
888       XCDR (assoc) = predicate;
889     }
890
891   /* recompute the tag values for all devices.  However, in the special
892      case where both the old and new predicates are nil, we know that
893      we don't have to do this. (It's probably common for people to
894      call (define-specifier-tag) more than once on the same tag,
895      and the most common case is where PREDICATE is not specified.) */
896
897   if (recompute)
898     {
899       DEVICE_LOOP_NO_BREAK (devcons, concons)
900         {
901           Lisp_Object device = XCAR (devcons);
902           assoc = assq_no_quit (tag,
903                                 DEVICE_USER_DEFINED_TAGS (XDEVICE (device)));
904           assert (CONSP (assoc));
905           if (NILP (predicate))
906             XCDR (assoc) = Qt;
907           else
908             XCDR (assoc) = !NILP (call1 (predicate, device)) ? Qt : Qnil;
909         }
910     }
911
912   return Qnil;
913 }
914
915 /* Called at device-creation time to initialize the user-defined
916    tag values for the newly-created device. */
917
918 void
919 setup_device_initial_specifier_tags (struct device *d)
920 {
921   Lisp_Object rest, rest2;
922   Lisp_Object device;
923
924   XSETDEVICE (device, d);
925
926   DEVICE_USER_DEFINED_TAGS (d) = Fcopy_alist (Vuser_defined_tags);
927
928   /* Now set up the initial values */
929   LIST_LOOP (rest, DEVICE_USER_DEFINED_TAGS (d))
930     XCDR (XCAR (rest)) = Qt;
931
932   for (rest = Vuser_defined_tags, rest2 = DEVICE_USER_DEFINED_TAGS (d);
933        !NILP (rest); rest = XCDR (rest), rest2 = XCDR (rest2))
934     {
935       Lisp_Object predicate = XCDR (XCAR (rest));
936       if (NILP (predicate))
937         XCDR (XCAR (rest2)) = Qt;
938       else
939         XCDR (XCAR (rest2)) = !NILP (call1 (predicate, device)) ? Qt : Qnil;
940     }
941 }
942
943 DEFUN ("device-matching-specifier-tag-list", Fdevice_matching_specifier_tag_list,
944        0, 1, 0, /*
945 Return a list of all specifier tags matching DEVICE.
946 DEVICE defaults to the selected device if omitted.
947 */
948        (device))
949 {
950   struct device *d = decode_device (device);
951   Lisp_Object rest, list = Qnil;
952   struct gcpro gcpro1;
953
954   GCPRO1 (list);
955
956   LIST_LOOP (rest, DEVICE_USER_DEFINED_TAGS (d))
957     {
958       if (!NILP (XCDR (XCAR (rest))))
959         list = Fcons (XCAR (XCAR (rest)), list);
960     }
961
962   list = Fnreverse (list);
963   list = Fcons (DEVICE_CLASS (d), list);
964   list = Fcons (DEVICE_TYPE  (d), list);
965
966   RETURN_UNGCPRO (list);
967 }
968
969 DEFUN ("specifier-tag-list", Fspecifier_tag_list, 0, 0, 0, /*
970 Return a list of all currently-defined specifier tags.
971 This includes the built-in ones (the device types and classes).
972 */
973        ())
974 {
975   Lisp_Object list = Qnil, rest;
976   struct gcpro gcpro1;
977
978   GCPRO1 (list);
979
980   LIST_LOOP (rest, Vuser_defined_tags)
981     list = Fcons (XCAR (XCAR (rest)), list);
982
983   list = Fnreverse (list);
984   list = nconc2 (Fcopy_sequence (Vdevice_class_list), list);
985   list = nconc2 (Fcopy_sequence (Vconsole_type_list), list);
986
987   RETURN_UNGCPRO (list);
988 }
989
990 DEFUN ("specifier-tag-predicate", Fspecifier_tag_predicate, 1, 1, 0, /*
991 Return the predicate for the given specifier tag.
992 */
993        (tag))
994 {
995   /* The return value of this function must be GCPRO'd. */
996   CHECK_SYMBOL (tag);
997
998   if (NILP (Fvalid_specifier_tag_p (tag)))
999     signal_simple_error ("Invalid specifier tag", tag);
1000
1001   /* Make up some predicates for the built-in types */
1002
1003   if (valid_console_type_p (tag))
1004     return list3 (Qlambda, list1 (Qdevice),
1005                   list3 (Qeq, list2 (Qquote, tag),
1006                          list2 (Qconsole_type, Qdevice)));
1007
1008   if (valid_device_class_p (tag))
1009     return list3 (Qlambda, list1 (Qdevice),
1010                   list3 (Qeq, list2 (Qquote, tag),
1011                          list2 (Qdevice_class, Qdevice)));
1012
1013   return XCDR (assq_no_quit (tag, Vuser_defined_tags));
1014 }
1015
1016 /* Return true if A "matches" B.  If EXACT_P is 0, A must be a subset of B.
1017   Otherwise, A must be `equal' to B.  The sets must be canonicalized. */
1018 static int
1019 tag_sets_match_p (Lisp_Object a, Lisp_Object b, int exact_p)
1020 {
1021   if (!exact_p)
1022     {
1023       while (!NILP (a) && !NILP (b))
1024         {
1025           if (EQ (XCAR (a), XCAR (b)))
1026             a = XCDR (a);
1027           b = XCDR (b);
1028         }
1029
1030       return NILP (a);
1031     }
1032   else
1033     {
1034       while (!NILP (a) && !NILP (b))
1035         {
1036           if (!EQ (XCAR (a), XCAR (b)))
1037             return 0;
1038           a = XCDR (a);
1039           b = XCDR (b);
1040         }
1041
1042       return NILP (a) && NILP (b);
1043     }
1044 }
1045
1046 \f
1047 /************************************************************************/
1048 /*                       Spec-lists and inst-lists                      */
1049 /************************************************************************/
1050
1051 static Lisp_Object
1052 call_validate_method (Lisp_Object boxed_method, Lisp_Object instantiator)
1053 {
1054   ((void (*)(Lisp_Object)) get_opaque_ptr (boxed_method)) (instantiator);
1055   return Qt;
1056 }
1057
1058 static Lisp_Object
1059 check_valid_instantiator (Lisp_Object instantiator,
1060                           struct specifier_methods *meths,
1061                           Error_behavior errb)
1062 {
1063   if (meths->validate_method)
1064     {
1065       Lisp_Object retval;
1066
1067       if (ERRB_EQ (errb, ERROR_ME))
1068         {
1069           (meths->validate_method) (instantiator);
1070           retval = Qt;
1071         }
1072       else
1073         {
1074           Lisp_Object opaque = make_opaque_ptr ((void *)
1075                                                 meths->validate_method);
1076           struct gcpro gcpro1;
1077
1078           GCPRO1 (opaque);
1079           retval = call_with_suspended_errors
1080             ((lisp_fn_t) call_validate_method,
1081              Qnil, Qspecifier, errb, 2, opaque, instantiator);
1082
1083           free_opaque_ptr (opaque);
1084           UNGCPRO;
1085         }
1086
1087       return retval;
1088     }
1089   return Qt;
1090 }
1091
1092 DEFUN ("check-valid-instantiator", Fcheck_valid_instantiator, 2, 2, 0, /*
1093 Signal an error if INSTANTIATOR is invalid for SPECIFIER-TYPE.
1094 */
1095        (instantiator, specifier_type))
1096 {
1097   struct specifier_methods *meths = decode_specifier_type (specifier_type,
1098                                                            ERROR_ME);
1099
1100   return check_valid_instantiator (instantiator, meths, ERROR_ME);
1101 }
1102
1103 DEFUN ("valid-instantiator-p", Fvalid_instantiator_p, 2, 2, 0, /*
1104 Return non-nil if INSTANTIATOR is valid for SPECIFIER-TYPE.
1105 */
1106        (instantiator, specifier_type))
1107 {
1108   struct specifier_methods *meths = decode_specifier_type (specifier_type,
1109                                                            ERROR_ME);
1110
1111   return check_valid_instantiator (instantiator, meths, ERROR_ME_NOT);
1112 }
1113
1114 static Lisp_Object
1115 check_valid_inst_list (Lisp_Object inst_list, struct specifier_methods *meths,
1116                        Error_behavior errb)
1117 {
1118   Lisp_Object rest;
1119
1120   LIST_LOOP (rest, inst_list)
1121     {
1122       Lisp_Object inst_pair, tag_set;
1123
1124       if (!CONSP (rest))
1125         {
1126           maybe_signal_simple_error ("Invalid instantiator list", inst_list,
1127                                      Qspecifier, errb);
1128           return Qnil;
1129         }
1130       if (!CONSP (inst_pair = XCAR (rest)))
1131         {
1132           maybe_signal_simple_error ("Invalid instantiator pair", inst_pair,
1133                                      Qspecifier, errb);
1134           return Qnil;
1135         }
1136       if (NILP (Fvalid_specifier_tag_set_p (tag_set = XCAR (inst_pair))))
1137         {
1138           maybe_signal_simple_error ("Invalid specifier tag", tag_set,
1139                                      Qspecifier, errb);
1140           return Qnil;
1141         }
1142
1143       if (NILP (check_valid_instantiator (XCDR (inst_pair), meths, errb)))
1144         return Qnil;
1145     }
1146
1147   return Qt;
1148 }
1149
1150 DEFUN ("check-valid-inst-list", Fcheck_valid_inst_list, 2, 2, 0, /*
1151 Signal an error if INST-LIST is invalid for specifier type TYPE.
1152 */
1153        (inst_list, type))
1154 {
1155   struct specifier_methods *meths = decode_specifier_type (type, ERROR_ME);
1156
1157   return check_valid_inst_list (inst_list, meths, ERROR_ME);
1158 }
1159
1160 DEFUN ("valid-inst-list-p", Fvalid_inst_list_p, 2, 2, 0, /*
1161 Return non-nil if INST-LIST is valid for specifier type TYPE.
1162 */
1163        (inst_list, type))
1164 {
1165   struct specifier_methods *meths = decode_specifier_type (type, ERROR_ME);
1166
1167   return check_valid_inst_list (inst_list, meths, ERROR_ME_NOT);
1168 }
1169
1170 static Lisp_Object
1171 check_valid_spec_list (Lisp_Object spec_list, struct specifier_methods *meths,
1172                        Error_behavior errb)
1173 {
1174   Lisp_Object rest;
1175
1176   LIST_LOOP (rest, spec_list)
1177     {
1178       Lisp_Object spec, locale;
1179       if (!CONSP (rest) || !CONSP (spec = XCAR (rest)))
1180         {
1181           maybe_signal_simple_error ("Invalid specification list", spec_list,
1182                                      Qspecifier, errb);
1183           return Qnil;
1184         }
1185       if (NILP (Fvalid_specifier_locale_p (locale = XCAR (spec))))
1186         {
1187           maybe_signal_simple_error ("Invalid specifier locale", locale,
1188                                      Qspecifier, errb);
1189           return Qnil;
1190         }
1191
1192       if (NILP (check_valid_inst_list (XCDR (spec), meths, errb)))
1193         return Qnil;
1194     }
1195
1196   return Qt;
1197 }
1198
1199 DEFUN ("check-valid-spec-list", Fcheck_valid_spec_list, 2, 2, 0, /*
1200 Signal an error if SPEC-LIST is invalid for specifier type TYPE.
1201 */
1202        (spec_list, type))
1203 {
1204   struct specifier_methods *meths = decode_specifier_type (type, ERROR_ME);
1205
1206   return check_valid_spec_list (spec_list, meths, ERROR_ME);
1207 }
1208
1209 DEFUN ("valid-spec-list-p", Fvalid_spec_list_p, 2, 2, 0, /*
1210 Return non-nil if SPEC-LIST is valid for specifier type TYPE.
1211 */
1212        (spec_list, type))
1213 {
1214   struct specifier_methods *meths = decode_specifier_type (type, ERROR_ME);
1215
1216   return check_valid_spec_list (spec_list, meths, ERROR_ME_NOT);
1217 }
1218
1219 enum spec_add_meth
1220 decode_how_to_add_specification (Lisp_Object how_to_add)
1221 {
1222   if (NILP (how_to_add) || EQ (Qremove_tag_set_prepend, how_to_add))
1223     return SPEC_REMOVE_TAG_SET_PREPEND;
1224   if (EQ (Qremove_tag_set_append, how_to_add))
1225     return SPEC_REMOVE_TAG_SET_APPEND;
1226   if (EQ (Qappend, how_to_add))
1227     return SPEC_APPEND;
1228   if (EQ (Qprepend, how_to_add))
1229     return SPEC_PREPEND;
1230   if (EQ (Qremove_locale, how_to_add))
1231     return SPEC_REMOVE_LOCALE;
1232   if (EQ (Qremove_locale_type, how_to_add))
1233     return SPEC_REMOVE_LOCALE_TYPE;
1234   if (EQ (Qremove_all, how_to_add))
1235     return SPEC_REMOVE_ALL;
1236
1237   signal_simple_error ("Invalid `how-to-add' flag", how_to_add);
1238
1239   return SPEC_PREPEND;          /* not reached */
1240 }
1241
1242 /* Given a specifier object SPEC, return bodily specifier if SPEC is a
1243    ghost specifier, otherwise return the object itself
1244 */
1245 static Lisp_Object
1246 bodily_specifier (Lisp_Object spec)
1247 {
1248   return (GHOST_SPECIFIER_P (XSPECIFIER (spec))
1249           ? XSPECIFIER(spec)->magic_parent : spec);
1250 }
1251
1252 /* Signal error if (specifier SPEC is read-only.
1253    Read only are ghost specifiers unless Vunlock_ghost_specifiers is
1254    non-nil.  All other specifiers are read-write.
1255 */
1256 static void
1257 check_modifiable_specifier (Lisp_Object spec)
1258 {
1259   if (NILP (Vunlock_ghost_specifiers)
1260       && GHOST_SPECIFIER_P (XSPECIFIER (spec)))
1261     signal_simple_error ("Attempt to modify read-only specifier",
1262                          list1 (spec));
1263 }
1264
1265 /* Helper function which unwind protects the value of
1266    Vunlock_ghost_specifiers, then sets it to non-nil value */
1267 static Lisp_Object
1268 restore_unlock_value (Lisp_Object val)
1269 {
1270   Vunlock_ghost_specifiers = val;
1271   return val;
1272 }
1273
1274 int
1275 unlock_ghost_specifiers_protected (void)
1276 {
1277   int depth = specpdl_depth ();
1278   record_unwind_protect (restore_unlock_value,
1279                          Vunlock_ghost_specifiers);
1280   Vunlock_ghost_specifiers = Qt;
1281   return depth;
1282 }
1283
1284 /* This gets hit so much that the function call overhead had a
1285    measurable impact (according to Quantify).  #### We should figure
1286    out the frequency with which this is called with the various types
1287    and reorder the check accordingly. */
1288 #define SPECIFIER_GET_SPEC_LIST(specifier, type)                        \
1289 (type == LOCALE_GLOBAL ? &(XSPECIFIER (specifier)->global_specs)   :    \
1290  type == LOCALE_DEVICE ? &(XSPECIFIER (specifier)->device_specs)   :    \
1291  type == LOCALE_FRAME  ? &(XSPECIFIER (specifier)->frame_specs)    :    \
1292  type == LOCALE_WINDOW ? &(XWEAK_LIST_LIST                              \
1293                            (XSPECIFIER (specifier)->window_specs)) :    \
1294  type == LOCALE_BUFFER ? &(XSPECIFIER (specifier)->buffer_specs)   :    \
1295  0)
1296
1297 static Lisp_Object *
1298 specifier_get_inst_list (Lisp_Object specifier, Lisp_Object locale,
1299                          enum spec_locale_type type)
1300 {
1301   Lisp_Object *spec_list = SPECIFIER_GET_SPEC_LIST (specifier, type);
1302   Lisp_Object specification;
1303
1304   if (type == LOCALE_GLOBAL)
1305     return spec_list;
1306   /* Calling assq_no_quit when it is just going to return nil anyhow
1307      is extremely expensive.  So sayeth Quantify. */
1308   if (!CONSP (*spec_list))
1309     return 0;
1310   specification = assq_no_quit (locale, *spec_list);
1311   if (NILP (specification))
1312     return 0;
1313   return &XCDR (specification);
1314 }
1315
1316 /* For the given INST_LIST, return a new INST_LIST containing all elements
1317    where TAG-SET matches the element's tag set.  EXACT_P indicates whether
1318    the match must be exact (as opposed to a subset).  SHORT_P indicates
1319    that the short form (for `specifier-specs') should be returned if
1320    possible.  If COPY_TREE_P, `copy-tree' is used to ensure that no
1321    elements of the new list are shared with the initial list.
1322 */
1323
1324 static Lisp_Object
1325 specifier_process_inst_list (Lisp_Object inst_list,
1326                              Lisp_Object tag_set, int exact_p,
1327                              int short_p, int copy_tree_p)
1328 {
1329   Lisp_Object retval = Qnil;
1330   Lisp_Object rest;
1331   struct gcpro gcpro1;
1332
1333   GCPRO1 (retval);
1334   LIST_LOOP (rest, inst_list)
1335     {
1336       Lisp_Object tagged_inst = XCAR (rest);
1337       Lisp_Object tagged_inst_tag = XCAR (tagged_inst);
1338       if (tag_sets_match_p (tag_set, tagged_inst_tag, exact_p))
1339         {
1340           if (short_p && NILP (tagged_inst_tag))
1341             retval = Fcons (copy_tree_p ?
1342                             Fcopy_tree (XCDR (tagged_inst), Qt) :
1343                             XCDR (tagged_inst),
1344                             retval);
1345           else
1346             retval = Fcons (copy_tree_p ? Fcopy_tree (tagged_inst, Qt) :
1347                             tagged_inst, retval);
1348         }
1349     }
1350   retval = Fnreverse (retval);
1351   UNGCPRO;
1352   /* If there is a single instantiator and the short form is
1353      requested, return just the instantiator (rather than a one-element
1354      list of it) unless it is nil (so that it can be distinguished from
1355      no instantiators at all). */
1356   if (short_p && CONSP (retval) && !NILP (XCAR (retval)) &&
1357       NILP (XCDR (retval)))
1358     return XCAR (retval);
1359   else
1360     return retval;
1361 }
1362
1363 static Lisp_Object
1364 specifier_get_external_inst_list (Lisp_Object specifier, Lisp_Object locale,
1365                                   enum spec_locale_type type,
1366                                   Lisp_Object tag_set, int exact_p,
1367                                   int short_p, int copy_tree_p)
1368 {
1369   Lisp_Object *inst_list = specifier_get_inst_list (specifier, locale,
1370                                                     type);
1371   if (!inst_list || NILP (*inst_list))
1372     {
1373       /* nil for *inst_list should only occur in 'global */
1374       assert (!inst_list || EQ (locale, Qglobal));
1375       return Qnil;
1376     }
1377
1378   return specifier_process_inst_list (*inst_list, tag_set, exact_p,
1379                                       short_p, copy_tree_p);
1380 }
1381
1382 static Lisp_Object
1383 specifier_get_external_spec_list (Lisp_Object specifier,
1384                                   enum spec_locale_type type,
1385                                   Lisp_Object tag_set, int exact_p)
1386 {
1387   Lisp_Object *spec_list = SPECIFIER_GET_SPEC_LIST (specifier, type);
1388   Lisp_Object retval = Qnil;
1389   Lisp_Object rest;
1390   struct gcpro gcpro1;
1391
1392   assert (type != LOCALE_GLOBAL);
1393   /* We're about to let stuff go external; make sure there aren't
1394      any dead objects */
1395   *spec_list = cleanup_assoc_list (*spec_list);
1396
1397   GCPRO1 (retval);
1398   LIST_LOOP (rest, *spec_list)
1399     {
1400       Lisp_Object spec = XCAR (rest);
1401       Lisp_Object inst_list =
1402         specifier_process_inst_list (XCDR (spec), tag_set, exact_p, 0, 1);
1403       if (!NILP (inst_list))
1404         retval = Fcons (Fcons (XCAR (spec), inst_list), retval);
1405     }
1406   RETURN_UNGCPRO (Fnreverse (retval));
1407 }
1408
1409 static Lisp_Object *
1410 specifier_new_spec (Lisp_Object specifier, Lisp_Object locale,
1411                     enum spec_locale_type type)
1412 {
1413   Lisp_Object *spec_list = SPECIFIER_GET_SPEC_LIST (specifier, type);
1414   Lisp_Object new_spec = Fcons (locale, Qnil);
1415   assert (type != LOCALE_GLOBAL);
1416   *spec_list = Fcons (new_spec, *spec_list);
1417   return &XCDR (new_spec);
1418 }
1419
1420 /* For the given INST_LIST, return a new list comprised of elements
1421    where TAG_SET does not match the element's tag set.  This operation
1422    is destructive. */
1423
1424 static Lisp_Object
1425 specifier_process_remove_inst_list (Lisp_Object inst_list,
1426                                     Lisp_Object tag_set, int exact_p,
1427                                     int *was_removed)
1428 {
1429   Lisp_Object prev = Qnil, rest;
1430
1431   *was_removed = 0;
1432
1433   LIST_LOOP (rest, inst_list)
1434     {
1435       if (tag_sets_match_p (tag_set, XCAR (XCAR (rest)), exact_p))
1436         {
1437           /* time to remove. */
1438           *was_removed = 1;
1439           if (NILP (prev))
1440             inst_list = XCDR (rest);
1441           else
1442             XCDR (prev) = XCDR (rest);
1443         }
1444       else
1445         prev = rest;
1446     }
1447
1448   return inst_list;
1449 }
1450
1451 static void
1452 specifier_remove_spec (Lisp_Object specifier, Lisp_Object locale,
1453                        enum spec_locale_type type,
1454                        Lisp_Object tag_set, int exact_p)
1455 {
1456   Lisp_Object *spec_list = SPECIFIER_GET_SPEC_LIST (specifier, type);
1457   Lisp_Object assoc;
1458   int was_removed;
1459
1460   if (type == LOCALE_GLOBAL)
1461     *spec_list = specifier_process_remove_inst_list (*spec_list, tag_set,
1462                                                      exact_p, &was_removed);
1463   else
1464     {
1465       assoc = assq_no_quit (locale, *spec_list);
1466       if (NILP (assoc))
1467         /* this locale is not found. */
1468         return;
1469       XCDR (assoc) = specifier_process_remove_inst_list (XCDR (assoc),
1470                                                          tag_set, exact_p,
1471                                                          &was_removed);
1472       if (NILP (XCDR (assoc)))
1473         /* no inst-pairs left; remove this locale entirely. */
1474         *spec_list = remassq_no_quit (locale, *spec_list);
1475     }
1476
1477   if (was_removed)
1478     MAYBE_SPECMETH (XSPECIFIER (specifier), after_change,
1479                     (bodily_specifier (specifier), locale));
1480 }
1481
1482 static void
1483 specifier_remove_locale_type (Lisp_Object specifier,
1484                               enum spec_locale_type type,
1485                               Lisp_Object tag_set, int exact_p)
1486 {
1487   Lisp_Object *spec_list = SPECIFIER_GET_SPEC_LIST (specifier, type);
1488   Lisp_Object prev = Qnil, rest;
1489
1490   assert (type != LOCALE_GLOBAL);
1491   LIST_LOOP (rest, *spec_list)
1492     {
1493       int was_removed;
1494       int remove_spec = 0;
1495       Lisp_Object spec = XCAR (rest);
1496
1497       /* There may be dead objects floating around */
1498       /* remember, dead windows can become alive again. */
1499       if (!WINDOWP (XCAR (spec)) && object_dead_p (XCAR (spec)))
1500         {
1501           remove_spec = 1;
1502           was_removed = 0;
1503         }
1504       else
1505         {
1506           XCDR (spec) = specifier_process_remove_inst_list (XCDR (spec),
1507                                                             tag_set, exact_p,
1508                                                             &was_removed);
1509           if (NILP (XCDR (spec)))
1510             remove_spec = 1;
1511         }
1512
1513       if (remove_spec)
1514         {
1515           if (NILP (prev))
1516             *spec_list = XCDR (rest);
1517           else
1518             XCDR (prev) = XCDR (rest);
1519         }
1520       else
1521         prev = rest;
1522
1523       if (was_removed)
1524         MAYBE_SPECMETH (XSPECIFIER (specifier), after_change,
1525                         (bodily_specifier (specifier), XCAR (spec)));
1526     }
1527 }
1528
1529 /* NEW_LIST is going to be added to INST_LIST, with add method ADD_METH.
1530    Frob INST_LIST according to ADD_METH.  No need to call an after-change
1531    function; the calling function will do this.  Return either SPEC_PREPEND
1532    or SPEC_APPEND, indicating whether to prepend or append the NEW_LIST. */
1533
1534 static enum spec_add_meth
1535 handle_multiple_add_insts (Lisp_Object *inst_list,
1536                            Lisp_Object new_list,
1537                            enum spec_add_meth add_meth)
1538 {
1539   switch (add_meth)
1540     {
1541     case SPEC_REMOVE_TAG_SET_APPEND:
1542       add_meth = SPEC_APPEND;
1543       goto remove_tag_set;
1544     case SPEC_REMOVE_TAG_SET_PREPEND:
1545       add_meth = SPEC_PREPEND;
1546     remove_tag_set:
1547       {
1548         Lisp_Object rest;
1549
1550         LIST_LOOP (rest, new_list)
1551           {
1552             Lisp_Object canontag = canonicalize_tag_set (XCAR (XCAR (rest)));
1553             struct gcpro gcpro1;
1554
1555             GCPRO1 (canontag);
1556             /* pull out all elements from the existing list with the
1557                same tag as any tags in NEW_LIST. */
1558             *inst_list = remassoc_no_quit (canontag, *inst_list);
1559             UNGCPRO;
1560           }
1561       }
1562       return add_meth;
1563     case SPEC_REMOVE_LOCALE:
1564       *inst_list = Qnil;
1565       return SPEC_PREPEND;
1566     case SPEC_APPEND:
1567       return add_meth;
1568     default:
1569       return SPEC_PREPEND;
1570     }
1571 }
1572
1573 /* Given a LOCALE and INST_LIST that is going to be added to SPECIFIER,
1574    copy, canonicalize, and call the going_to_add methods as necessary
1575    to produce a new list that is the one that really will be added
1576    to the specifier. */
1577
1578 static Lisp_Object
1579 build_up_processed_list (Lisp_Object specifier, Lisp_Object locale,
1580                          Lisp_Object inst_list)
1581 {
1582   /* The return value of this function must be GCPRO'd. */
1583   Lisp_Object rest, list_to_build_up = Qnil;
1584   struct Lisp_Specifier *sp = XSPECIFIER (specifier);
1585   struct gcpro gcpro1;
1586
1587   GCPRO1 (list_to_build_up);
1588   LIST_LOOP (rest, inst_list)
1589     {
1590       Lisp_Object tag_set = XCAR (XCAR (rest));
1591       Lisp_Object instantiator = Fcopy_tree (XCDR (XCAR (rest)), Qt);
1592       Lisp_Object sub_inst_list = Qnil;
1593       struct gcpro ngcpro1, ngcpro2;
1594
1595       NGCPRO2 (instantiator, sub_inst_list);
1596       /* call the will-add method; it may GC */
1597       sub_inst_list = HAS_SPECMETH_P (sp, going_to_add) ?
1598         SPECMETH (sp, going_to_add,
1599                   (bodily_specifier (specifier), locale,
1600                    tag_set, instantiator)) :
1601         Qt;
1602       if (EQ (sub_inst_list, Qt))
1603         /* no change here. */
1604         sub_inst_list = list1 (Fcons (canonicalize_tag_set (tag_set),
1605                                       instantiator));
1606       else
1607         {
1608           /* now canonicalize all the tag sets in the new objects */
1609           Lisp_Object rest2;
1610           LIST_LOOP (rest2, sub_inst_list)
1611             XCAR (XCAR (rest2)) = canonicalize_tag_set (XCAR (XCAR (rest2)));
1612         }
1613
1614       list_to_build_up = nconc2 (sub_inst_list, list_to_build_up);
1615       NUNGCPRO;
1616     }
1617
1618   RETURN_UNGCPRO (Fnreverse (list_to_build_up));
1619 }
1620
1621 /* Add a specification (locale and instantiator list) to a specifier.
1622    ADD_METH specifies what to do with existing specifications in the
1623    specifier, and is an enum that corresponds to the values in
1624    `add-spec-to-specifier'.  The calling routine is responsible for
1625    validating LOCALE and INST-LIST, but the tag-sets in INST-LIST
1626    do not need to be canonicalized. */
1627
1628   /* #### I really need to rethink the after-change
1629      functions to make them easier to use and more efficient. */
1630
1631 static void
1632 specifier_add_spec (Lisp_Object specifier, Lisp_Object locale,
1633                     Lisp_Object inst_list, enum spec_add_meth add_meth)
1634 {
1635   struct Lisp_Specifier *sp = XSPECIFIER (specifier);
1636   enum spec_locale_type type = locale_type_from_locale (locale);
1637   Lisp_Object *orig_inst_list, tem;
1638   Lisp_Object list_to_build_up = Qnil;
1639   struct gcpro gcpro1;
1640
1641   GCPRO1 (list_to_build_up);
1642   list_to_build_up = build_up_processed_list (specifier, locale, inst_list);
1643   /* Now handle REMOVE_LOCALE_TYPE and REMOVE_ALL.  These are the
1644      add-meth types that affect locales other than this one. */
1645   if (add_meth == SPEC_REMOVE_LOCALE_TYPE)
1646     specifier_remove_locale_type (specifier, type, Qnil, 0);
1647   else if (add_meth == SPEC_REMOVE_ALL)
1648     {
1649       specifier_remove_locale_type (specifier, LOCALE_BUFFER, Qnil, 0);
1650       specifier_remove_locale_type (specifier, LOCALE_WINDOW, Qnil, 0);
1651       specifier_remove_locale_type (specifier, LOCALE_FRAME,  Qnil, 0);
1652       specifier_remove_locale_type (specifier, LOCALE_DEVICE, Qnil, 0);
1653       specifier_remove_spec (specifier, Qglobal, LOCALE_GLOBAL, Qnil, 0);
1654     }
1655
1656   orig_inst_list = specifier_get_inst_list (specifier, locale, type);
1657   if (!orig_inst_list)
1658     orig_inst_list = specifier_new_spec (specifier, locale, type);
1659   add_meth = handle_multiple_add_insts (orig_inst_list, list_to_build_up,
1660                                         add_meth);
1661
1662   if (add_meth == SPEC_PREPEND)
1663     tem = nconc2 (list_to_build_up, *orig_inst_list);
1664   else if (add_meth == SPEC_APPEND)
1665     tem = nconc2 (*orig_inst_list, list_to_build_up);
1666   else
1667     abort ();
1668
1669   *orig_inst_list = tem;
1670
1671   UNGCPRO;
1672
1673   /* call the after-change method */
1674   MAYBE_SPECMETH (sp, after_change,
1675                   (bodily_specifier (specifier), locale));
1676 }
1677
1678 static void
1679 specifier_copy_spec (Lisp_Object specifier, Lisp_Object dest,
1680                      Lisp_Object locale, enum spec_locale_type type,
1681                      Lisp_Object tag_set, int exact_p,
1682                      enum spec_add_meth add_meth)
1683 {
1684   Lisp_Object inst_list =
1685     specifier_get_external_inst_list (specifier, locale, type, tag_set,
1686                                       exact_p, 0, 0);
1687   specifier_add_spec (dest, locale, inst_list, add_meth);
1688 }
1689
1690 static void
1691 specifier_copy_locale_type (Lisp_Object specifier, Lisp_Object dest,
1692                             enum spec_locale_type type,
1693                             Lisp_Object tag_set, int exact_p,
1694                             enum spec_add_meth add_meth)
1695 {
1696   Lisp_Object *src_list = SPECIFIER_GET_SPEC_LIST (specifier, type);
1697   Lisp_Object rest;
1698
1699   /* This algorithm is O(n^2) in running time.
1700      It's certainly possible to implement an O(n log n) algorithm,
1701      but I doubt there's any need to. */
1702
1703   LIST_LOOP (rest, *src_list)
1704     {
1705       Lisp_Object spec = XCAR (rest);
1706       /* There may be dead objects floating around */
1707       /* remember, dead windows can become alive again. */
1708       if (WINDOWP (XCAR (spec)) || !object_dead_p (XCAR (spec)))
1709         specifier_add_spec
1710           (dest, XCAR (spec),
1711            specifier_process_inst_list (XCDR (spec), tag_set, exact_p, 0, 0),
1712            add_meth);
1713     }
1714 }
1715
1716 /* map MAPFUN over the locales in SPECIFIER that are given in LOCALE.
1717    CLOSURE is passed unchanged to MAPFUN.  LOCALE can be one of
1718
1719      -- nil (same as 'all)
1720      -- a single locale, locale type, or 'all
1721      -- a list of locales, locale types, and/or 'all
1722
1723    MAPFUN is called for each locale and locale type given; for 'all,
1724    it is called for the locale 'global and for the four possible
1725    locale types.  In each invocation, either LOCALE will be a locale
1726    and LOCALE_TYPE will be the locale type of this locale,
1727    or LOCALE will be nil and LOCALE_TYPE will be a locale type.
1728    If MAPFUN ever returns non-zero, the mapping is halted and the
1729    value returned is returned from map_specifier().  Otherwise, the
1730    mapping proceeds to the end and map_specifier() returns 0.
1731  */
1732
1733 static int
1734 map_specifier (Lisp_Object specifier, Lisp_Object locale,
1735                int (*mapfun) (Lisp_Object specifier,
1736                               Lisp_Object locale,
1737                               enum spec_locale_type locale_type,
1738                               Lisp_Object tag_set,
1739                               int exact_p,
1740                               void *closure),
1741                Lisp_Object tag_set, Lisp_Object exact_p,
1742                void *closure)
1743 {
1744   int retval = 0;
1745   Lisp_Object rest;
1746   struct gcpro gcpro1, gcpro2;
1747
1748   GCPRO2 (tag_set, locale);
1749   locale = decode_locale_list (locale);
1750   tag_set = decode_specifier_tag_set (tag_set);
1751   tag_set = canonicalize_tag_set (tag_set);
1752
1753   LIST_LOOP (rest, locale)
1754     {
1755       Lisp_Object theloc = XCAR (rest);
1756       if (!NILP (Fvalid_specifier_locale_p (theloc)))
1757         {
1758           retval = (*mapfun) (specifier, theloc,
1759                               locale_type_from_locale (theloc),
1760                               tag_set, !NILP (exact_p), closure);
1761           if (retval)
1762             break;
1763         }
1764       else if (!NILP (Fvalid_specifier_locale_type_p (theloc)))
1765         {
1766           retval = (*mapfun) (specifier, Qnil,
1767                               decode_locale_type (theloc), tag_set,
1768                               !NILP (exact_p), closure);
1769           if (retval)
1770             break;
1771         }
1772       else
1773         {
1774           assert (EQ (theloc, Qall));
1775           retval = (*mapfun) (specifier, Qnil, LOCALE_BUFFER, tag_set,
1776                               !NILP (exact_p), closure);
1777           if (retval)
1778             break;
1779           retval = (*mapfun) (specifier, Qnil, LOCALE_WINDOW, tag_set,
1780                               !NILP (exact_p), closure);
1781           if (retval)
1782             break;
1783           retval = (*mapfun) (specifier, Qnil, LOCALE_FRAME, tag_set,
1784                               !NILP (exact_p), closure);
1785           if (retval)
1786             break;
1787           retval = (*mapfun) (specifier, Qnil, LOCALE_DEVICE, tag_set,
1788                               !NILP (exact_p), closure);
1789           if (retval)
1790             break;
1791           retval = (*mapfun) (specifier, Qglobal, LOCALE_GLOBAL, tag_set,
1792                               !NILP (exact_p), closure);
1793           if (retval)
1794             break;
1795         }
1796     }
1797
1798   UNGCPRO;
1799   return retval;
1800 }
1801
1802 DEFUN ("add-spec-to-specifier", Fadd_spec_to_specifier, 2, 5, 0, /*
1803 Add a specification to SPECIFIER.
1804 The specification maps from LOCALE (which should be a window, buffer,
1805 frame, device, or 'global, and defaults to 'global) to INSTANTIATOR,
1806 whose allowed values depend on the type of the specifier.  Optional
1807 argument TAG-SET limits the instantiator to apply only to the specified
1808 tag set, which should be a list of tags all of which must match the
1809 device being instantiated over (tags are a device type, a device class,
1810 or tags defined with `define-specifier-tag').  Specifying a single
1811 symbol for TAG-SET is equivalent to specifying a one-element list
1812 containing that symbol.  Optional argument HOW-TO-ADD specifies what to
1813 do if there are already specifications in the specifier.
1814 It should be one of
1815
1816   'prepend              Put at the beginning of the current list of
1817                         instantiators for LOCALE.
1818   'append               Add to the end of the current list of
1819                         instantiators for LOCALE.
1820   'remove-tag-set-prepend (this is the default)
1821                         Remove any existing instantiators whose tag set is
1822                         the same as TAG-SET; then put the new instantiator
1823                         at the beginning of the current list. ("Same tag
1824                         set" means that they contain the same elements.
1825                         The order may be different.)
1826   'remove-tag-set-append
1827                         Remove any existing instantiators whose tag set is
1828                         the same as TAG-SET; then put the new instantiator
1829                         at the end of the current list.
1830   'remove-locale        Remove all previous instantiators for this locale
1831                         before adding the new spec.
1832   'remove-locale-type   Remove all specifications for all locales of the
1833                         same type as LOCALE (this includes LOCALE itself)
1834                         before adding the new spec.
1835   'remove-all           Remove all specifications from the specifier
1836                         before adding the new spec.
1837
1838 You can retrieve the specifications for a particular locale or locale type
1839 with the function `specifier-spec-list' or `specifier-specs'.
1840 */
1841        (specifier, instantiator, locale, tag_set, how_to_add))
1842 {
1843   enum spec_add_meth add_meth;
1844   Lisp_Object inst_list;
1845   struct gcpro gcpro1;
1846
1847   CHECK_SPECIFIER (specifier);
1848   check_modifiable_specifier (specifier);
1849   
1850   locale = decode_locale (locale);
1851   check_valid_instantiator (instantiator,
1852                             decode_specifier_type
1853                             (Fspecifier_type (specifier), ERROR_ME),
1854                             ERROR_ME);
1855   /* tag_set might be newly-created material, but it's part of inst_list
1856      so is properly GC-protected. */
1857   tag_set = decode_specifier_tag_set (tag_set);
1858   add_meth = decode_how_to_add_specification (how_to_add);
1859
1860   inst_list = list1 (Fcons (tag_set, instantiator));
1861   GCPRO1 (inst_list);
1862   specifier_add_spec (specifier, locale, inst_list, add_meth);
1863   recompute_cached_specifier_everywhere (specifier);
1864   RETURN_UNGCPRO (Qnil);
1865 }
1866
1867 DEFUN ("add-spec-list-to-specifier", Fadd_spec_list_to_specifier, 2, 3, 0, /*
1868 Add a spec-list (a list of specifications) to SPECIFIER.
1869 The format of a spec-list is
1870
1871   ((LOCALE (TAG-SET . INSTANTIATOR) ...) ...)
1872
1873 where
1874   LOCALE := a window, a buffer, a frame, a device, or 'global
1875   TAG-SET := an unordered list of zero or more TAGS, each of which
1876              is a symbol
1877   TAG := a device class (see `valid-device-class-p'), a device type
1878          (see `valid-console-type-p'), or a tag defined with
1879          `define-specifier-tag'
1880   INSTANTIATOR := format determined by the type of specifier
1881
1882 The pair (TAG-SET . INSTANTIATOR) is called an `inst-pair'.
1883 A list of inst-pairs is called an `inst-list'.
1884 The pair (LOCALE . INST-LIST) is called a `specification' or `spec'.
1885 A spec-list, then, can be viewed as a list of specifications.
1886
1887 HOW-TO-ADD specifies how to combine the new specifications with
1888 the existing ones, and has the same semantics as for
1889 `add-spec-to-specifier'.
1890
1891 In many circumstances, the higher-level function `set-specifier' is
1892 more convenient and should be used instead.
1893 */
1894        (specifier, spec_list, how_to_add))
1895 {
1896   enum spec_add_meth add_meth;
1897   Lisp_Object rest;
1898
1899   CHECK_SPECIFIER (specifier);
1900   check_modifiable_specifier (specifier);
1901
1902   check_valid_spec_list (spec_list,
1903                          decode_specifier_type
1904                          (Fspecifier_type (specifier), ERROR_ME),
1905                          ERROR_ME);
1906   add_meth = decode_how_to_add_specification (how_to_add);
1907
1908   LIST_LOOP (rest, spec_list)
1909     {
1910       /* Placating the GCC god. */
1911       Lisp_Object specification = XCAR (rest);
1912       Lisp_Object locale    = XCAR (specification);
1913       Lisp_Object inst_list = XCDR (specification);
1914
1915       specifier_add_spec (specifier, locale, inst_list, add_meth);
1916     }
1917   recompute_cached_specifier_everywhere (specifier);
1918   return Qnil;
1919 }
1920
1921 void
1922 add_spec_to_ghost_specifier (Lisp_Object specifier, Lisp_Object instantiator,
1923                              Lisp_Object locale, Lisp_Object tag_set,
1924                              Lisp_Object how_to_add)
1925 {
1926   int depth = unlock_ghost_specifiers_protected ();
1927   Fadd_spec_to_specifier (XSPECIFIER(specifier)->fallback,
1928                           instantiator, locale, tag_set, how_to_add);
1929   unbind_to (depth, Qnil);
1930 }
1931
1932 struct specifier_spec_list_closure
1933 {
1934   Lisp_Object head, tail;
1935 };
1936
1937 static int
1938 specifier_spec_list_mapfun (Lisp_Object specifier,
1939                             Lisp_Object locale,
1940                             enum spec_locale_type locale_type,
1941                             Lisp_Object tag_set,
1942                             int exact_p,
1943                             void *closure)
1944 {
1945   struct specifier_spec_list_closure *cl =
1946     (struct specifier_spec_list_closure *) closure;
1947   Lisp_Object partial;
1948
1949   if (NILP (locale))
1950     partial = specifier_get_external_spec_list (specifier,
1951                                                 locale_type,
1952                                                 tag_set, exact_p);
1953   else
1954     {
1955       partial = specifier_get_external_inst_list (specifier, locale,
1956                                                   locale_type, tag_set,
1957                                                   exact_p, 0, 1);
1958       if (!NILP (partial))
1959         partial = list1 (Fcons (locale, partial));
1960     }
1961   if (NILP (partial))
1962     return 0;
1963
1964   /* tack on the new list */
1965   if (NILP (cl->tail))
1966     cl->head = cl->tail = partial;
1967   else
1968     XCDR (cl->tail) = partial;
1969   /* find the new tail */
1970   while (CONSP (XCDR (cl->tail)))
1971     cl->tail = XCDR (cl->tail);
1972   return 0;
1973 }
1974
1975 /* For the given SPECIFIER create and return a list of all specs
1976    contained within it, subject to LOCALE.  If LOCALE is a locale, only
1977    specs in that locale will be returned.  If LOCALE is a locale type,
1978    all specs in all locales of that type will be returned.  If LOCALE is
1979    nil, all specs will be returned.  This always copies lists and never
1980    returns the actual lists, because we do not want someone manipulating
1981    the actual objects.  This may cause a slight loss of potential
1982    functionality but if we were to allow it then a user could manage to
1983    violate our assertion that the specs contained in the actual
1984    specifier lists are all valid. */
1985
1986 DEFUN ("specifier-spec-list", Fspecifier_spec_list, 1, 4, 0, /*
1987 Return the spec-list of specifications for SPECIFIER in LOCALE.
1988
1989 If LOCALE is a particular locale (a buffer, window, frame, device,
1990 or 'global), a spec-list consisting of the specification for that
1991 locale will be returned.
1992
1993 If LOCALE is a locale type (i.e. 'buffer, 'window, 'frame, or 'device),
1994 a spec-list of the specifications for all locales of that type will be
1995 returned.
1996
1997 If LOCALE is nil or 'all, a spec-list of all specifications in SPECIFIER
1998 will be returned.
1999
2000 LOCALE can also be a list of locales, locale types, and/or 'all; the
2001 result is as if `specifier-spec-list' were called on each element of the
2002 list and the results concatenated together.
2003
2004 Only instantiators where TAG-SET (a list of zero or more tags) is a
2005 subset of (or possibly equal to) the instantiator's tag set are returned.
2006 \(The default value of nil is a subset of all tag sets, so in this case
2007 no instantiators will be screened out.) If EXACT-P is non-nil, however,
2008 TAG-SET must be equal to an instantiator's tag set for the instantiator
2009 to be returned.
2010 */
2011      (specifier, locale, tag_set, exact_p))
2012 {
2013   struct specifier_spec_list_closure cl;
2014   struct gcpro gcpro1, gcpro2;
2015
2016   CHECK_SPECIFIER (specifier);
2017   cl.head = cl.tail = Qnil;
2018   GCPRO2 (cl.head, cl.tail);
2019   map_specifier (specifier, locale, specifier_spec_list_mapfun,
2020                  tag_set, exact_p, &cl);
2021   UNGCPRO;
2022   return cl.head;
2023 }
2024
2025
2026 DEFUN ("specifier-specs", Fspecifier_specs, 1, 4, 0, /*
2027 Return the specification(s) for SPECIFIER in LOCALE.
2028
2029 If LOCALE is a single locale or is a list of one element containing a
2030 single locale, then a "short form" of the instantiators for that locale
2031 will be returned.  Otherwise, this function is identical to
2032 `specifier-spec-list'.
2033
2034 The "short form" is designed for readability and not for ease of use
2035 in Lisp programs, and is as follows:
2036
2037 1. If there is only one instantiator, then an inst-pair (i.e. cons of
2038    tag and instantiator) will be returned; otherwise a list of
2039    inst-pairs will be returned.
2040 2. For each inst-pair returned, if the instantiator's tag is 'any,
2041    the tag will be removed and the instantiator itself will be returned
2042    instead of the inst-pair.
2043 3. If there is only one instantiator, its value is nil, and its tag is
2044    'any, a one-element list containing nil will be returned rather
2045    than just nil, to distinguish this case from there being no
2046    instantiators at all.
2047 */
2048        (specifier, locale, tag_set, exact_p))
2049 {
2050   if (!NILP (Fvalid_specifier_locale_p (locale)) ||
2051       (CONSP (locale) && !NILP (Fvalid_specifier_locale_p (XCAR (locale))) &&
2052        NILP (XCDR (locale))))
2053     {
2054       struct gcpro gcpro1;
2055
2056       CHECK_SPECIFIER (specifier);
2057       if (CONSP (locale))
2058         locale = XCAR (locale);
2059       GCPRO1 (tag_set);
2060       tag_set = decode_specifier_tag_set (tag_set);
2061       tag_set = canonicalize_tag_set (tag_set);
2062       RETURN_UNGCPRO
2063         (specifier_get_external_inst_list (specifier, locale,
2064                                            locale_type_from_locale (locale),
2065                                            tag_set, !NILP (exact_p), 1, 1));
2066     }
2067   else
2068     return Fspecifier_spec_list (specifier, locale, tag_set, exact_p);
2069 }
2070
2071 static int
2072 remove_specifier_mapfun (Lisp_Object specifier,
2073                          Lisp_Object locale,
2074                          enum spec_locale_type locale_type,
2075                          Lisp_Object tag_set,
2076                          int exact_p,
2077                          void *ignored_closure)
2078 {
2079   if (NILP (locale))
2080     specifier_remove_locale_type (specifier, locale_type, tag_set, exact_p);
2081   else
2082     specifier_remove_spec (specifier, locale, locale_type, tag_set, exact_p);
2083   return 0;
2084 }
2085
2086 DEFUN ("remove-specifier", Fremove_specifier, 1, 4, 0, /*
2087 Remove specification(s) for SPECIFIER.
2088
2089 If LOCALE is a particular locale (a window, buffer, frame, device,
2090 or 'global), the specification for that locale will be removed.
2091
2092 If instead, LOCALE is a locale type (i.e. 'window, 'buffer, 'frame,
2093 or 'device), the specifications for all locales of that type will be
2094 removed.
2095
2096 If LOCALE is nil or 'all, all specifications will be removed.
2097
2098 LOCALE can also be a list of locales, locale types, and/or 'all; this
2099 is equivalent to calling `remove-specifier' for each of the elements
2100 in the list.
2101
2102 Only instantiators where TAG-SET (a list of zero or more tags) is a
2103 subset of (or possibly equal to) the instantiator's tag set are removed.
2104 The default value of nil is a subset of all tag sets, so in this case
2105 no instantiators will be screened out. If EXACT-P is non-nil, however,
2106 TAG-SET must be equal to an instantiator's tag set for the instantiator
2107 to be removed.
2108 */
2109        (specifier, locale, tag_set, exact_p))
2110 {
2111   CHECK_SPECIFIER (specifier);
2112   check_modifiable_specifier (specifier);
2113
2114   map_specifier (specifier, locale, remove_specifier_mapfun,
2115                  tag_set, exact_p, 0);
2116   recompute_cached_specifier_everywhere (specifier);
2117   return Qnil;
2118 }
2119
2120 void
2121 remove_ghost_specifier (Lisp_Object specifier, Lisp_Object locale,
2122                         Lisp_Object tag_set, Lisp_Object exact_p)
2123 {
2124   int depth = unlock_ghost_specifiers_protected ();
2125   Fremove_specifier (XSPECIFIER(specifier)->fallback,
2126                      locale, tag_set, exact_p);
2127   unbind_to (depth, Qnil);
2128 }
2129
2130 struct copy_specifier_closure
2131 {
2132   Lisp_Object dest;
2133   enum spec_add_meth add_meth;
2134   int add_meth_is_nil;
2135 };
2136
2137 static int
2138 copy_specifier_mapfun (Lisp_Object specifier,
2139                        Lisp_Object locale,
2140                        enum spec_locale_type locale_type,
2141                        Lisp_Object tag_set,
2142                        int exact_p,
2143                        void *closure)
2144 {
2145   struct copy_specifier_closure *cl =
2146     (struct copy_specifier_closure *) closure;
2147
2148   if (NILP (locale))
2149     specifier_copy_locale_type (specifier, cl->dest, locale_type,
2150                                 tag_set, exact_p,
2151                                 cl->add_meth_is_nil ?
2152                                 SPEC_REMOVE_LOCALE_TYPE :
2153                                 cl->add_meth);
2154   else
2155     specifier_copy_spec (specifier, cl->dest, locale, locale_type,
2156                          tag_set, exact_p,
2157                          cl->add_meth_is_nil ? SPEC_REMOVE_LOCALE :
2158                          cl->add_meth);
2159   return 0;
2160 }
2161
2162 DEFUN ("copy-specifier", Fcopy_specifier, 1, 6, 0, /*
2163 Copy SPECIFIER to DEST, or create a new one if DEST is nil.
2164
2165 If DEST is nil or omitted, a new specifier will be created and the
2166 specifications copied into it.  Otherwise, the specifications will be
2167 copied into the existing specifier in DEST.
2168
2169 If LOCALE is nil or 'all, all specifications will be copied.  If LOCALE
2170 is a particular locale, the specification for that particular locale will
2171 be copied.  If LOCALE is a locale type, the specifications for all locales
2172 of that type will be copied.  LOCALE can also be a list of locales,
2173 locale types, and/or 'all; this is equivalent to calling `copy-specifier'
2174 for each of the elements of the list.  See `specifier-spec-list' for more
2175 information about LOCALE.
2176
2177 Only instantiators where TAG-SET (a list of zero or more tags) is a
2178 subset of (or possibly equal to) the instantiator's tag set are copied.
2179 The default value of nil is a subset of all tag sets, so in this case
2180 no instantiators will be screened out. If EXACT-P is non-nil, however,
2181 TAG-SET must be equal to an instantiator's tag set for the instantiator
2182 to be copied.
2183
2184 Optional argument HOW-TO-ADD specifies what to do with existing
2185 specifications in DEST.  If nil, then whichever locales or locale types
2186 are copied will first be completely erased in DEST.  Otherwise, it is
2187 the same as in `add-spec-to-specifier'.
2188 */
2189        (specifier, dest, locale, tag_set, exact_p, how_to_add))
2190 {
2191   struct gcpro gcpro1;
2192   struct copy_specifier_closure cl;
2193
2194   CHECK_SPECIFIER (specifier);
2195   if (NILP (how_to_add))
2196     cl.add_meth_is_nil = 1;
2197   else
2198     cl.add_meth_is_nil = 0;
2199   cl.add_meth = decode_how_to_add_specification (how_to_add);
2200   if (NILP (dest))
2201     {
2202       /* #### What about copying the extra data? */
2203       dest = make_specifier (XSPECIFIER (specifier)->methods);
2204     }
2205   else
2206     {
2207       CHECK_SPECIFIER (dest);
2208       check_modifiable_specifier (dest);
2209       if (XSPECIFIER (dest)->methods != XSPECIFIER (specifier)->methods)
2210         error ("Specifiers not of same type");
2211     }
2212
2213   cl.dest = dest;
2214   GCPRO1 (dest);
2215   map_specifier (specifier, locale, copy_specifier_mapfun,
2216                  tag_set, exact_p, &cl);
2217   UNGCPRO;
2218   recompute_cached_specifier_everywhere (dest);
2219   return dest;
2220 }
2221
2222 \f
2223 /************************************************************************/
2224 /*                              Instancing                              */
2225 /************************************************************************/
2226
2227 static Lisp_Object
2228 call_validate_matchspec_method (Lisp_Object boxed_method,
2229                                 Lisp_Object matchspec)
2230 {
2231   ((void (*)(Lisp_Object)) get_opaque_ptr (boxed_method)) (matchspec);
2232   return Qt;
2233 }
2234
2235 static Lisp_Object
2236 check_valid_specifier_matchspec (Lisp_Object matchspec,
2237                                  struct specifier_methods *meths,
2238                                  Error_behavior errb)
2239 {
2240   if (meths->validate_matchspec_method)
2241     {
2242       Lisp_Object retval;
2243
2244       if (ERRB_EQ (errb, ERROR_ME))
2245         {
2246           (meths->validate_matchspec_method) (matchspec);
2247           retval = Qt;
2248         }
2249       else
2250         {
2251           Lisp_Object opaque =
2252             make_opaque_ptr ((void *) meths->validate_matchspec_method);
2253           struct gcpro gcpro1;
2254
2255           GCPRO1 (opaque);
2256           retval = call_with_suspended_errors
2257             ((lisp_fn_t) call_validate_matchspec_method,
2258              Qnil, Qspecifier, errb, 2, opaque, matchspec);
2259
2260           free_opaque_ptr (opaque);
2261           UNGCPRO;
2262         }
2263
2264       return retval;
2265     }
2266   else
2267     {
2268       maybe_signal_simple_error
2269         ("Matchspecs not allowed for this specifier type",
2270          intern (meths->name), Qspecifier, errb);
2271       return Qnil;
2272     }
2273 }
2274
2275 DEFUN ("check-valid-specifier-matchspec", Fcheck_valid_specifier_matchspec, 2, 2, 0, /*
2276 Signal an error if MATCHSPEC is invalid for SPECIFIER-TYPE.
2277 See `specifier-matching-instance' for a description of matchspecs.
2278 */
2279        (matchspec, specifier_type))
2280 {
2281   struct specifier_methods *meths = decode_specifier_type (specifier_type,
2282                                                            ERROR_ME);
2283
2284   return check_valid_specifier_matchspec (matchspec, meths, ERROR_ME);
2285 }
2286
2287 DEFUN ("valid-specifier-matchspec-p", Fvalid_specifier_matchspec_p, 2, 2, 0, /*
2288 Return non-nil if MATCHSPEC is valid for SPECIFIER-TYPE.
2289 See `specifier-matching-instance' for a description of matchspecs.
2290 */
2291        (matchspec, specifier_type))
2292 {
2293   struct specifier_methods *meths = decode_specifier_type (specifier_type,
2294                                                            ERROR_ME);
2295
2296   return check_valid_specifier_matchspec (matchspec, meths, ERROR_ME_NOT);
2297 }
2298
2299 /* This function is purposely not callable from Lisp.  If a Lisp
2300    caller wants to set a fallback, they should just set the
2301    global value. */
2302
2303 void
2304 set_specifier_fallback (Lisp_Object specifier, Lisp_Object fallback)
2305 {
2306   struct Lisp_Specifier *sp = XSPECIFIER (specifier);
2307   assert (SPECIFIERP (fallback) ||
2308           !NILP (Fvalid_inst_list_p (fallback, Fspecifier_type (specifier))));
2309   if (SPECIFIERP (fallback))
2310     assert (EQ (Fspecifier_type (specifier), Fspecifier_type (fallback)));
2311   if (BODILY_SPECIFIER_P (sp))
2312     GHOST_SPECIFIER(sp)->fallback = fallback;
2313   else
2314     sp->fallback = fallback;
2315   /* call the after-change method */
2316   MAYBE_SPECMETH (sp, after_change,
2317                   (bodily_specifier (specifier), Qfallback));
2318   recompute_cached_specifier_everywhere (specifier);
2319 }
2320
2321 DEFUN ("specifier-fallback", Fspecifier_fallback, 1, 1, 0, /*
2322 Return the fallback value for SPECIFIER.
2323 Fallback values are provided by the C code for certain built-in
2324 specifiers to make sure that instancing won't fail even if all
2325 specs are removed from the specifier, or to implement simple
2326 inheritance behavior (e.g. this method is used to ensure that
2327 faces other than 'default inherit their attributes from 'default).
2328 By design, you cannot change the fallback value, and specifiers
2329 created with `make-specifier' will never have a fallback (although
2330 a similar, Lisp-accessible capability may be provided in the future
2331 to allow for inheritance).
2332
2333 The fallback value will be an inst-list that is instanced like
2334 any other inst-list, a specifier of the same type as SPECIFIER
2335 \(results in inheritance), or nil for no fallback.
2336
2337 When you instance a specifier, you can explicitly request that the
2338 fallback not be consulted. (The C code does this, for example, when
2339 merging faces.) See `specifier-instance'.
2340 */
2341        (specifier))
2342 {
2343   CHECK_SPECIFIER (specifier);
2344   return Fcopy_tree (XSPECIFIER (specifier)->fallback, Qt);
2345 }
2346
2347 static Lisp_Object
2348 specifier_instance_from_inst_list (Lisp_Object specifier,
2349                                    Lisp_Object matchspec,
2350                                    Lisp_Object domain,
2351                                    Lisp_Object inst_list,
2352                                    Error_behavior errb, int no_quit,
2353                                    Lisp_Object depth)
2354 {
2355   /* This function can GC */
2356   struct Lisp_Specifier *sp;
2357   Lisp_Object device;
2358   Lisp_Object rest;
2359   int count = specpdl_depth ();
2360   struct gcpro gcpro1, gcpro2;
2361
2362   GCPRO2 (specifier, inst_list);
2363
2364   sp = XSPECIFIER (specifier);
2365   device = DFW_DEVICE (domain);
2366
2367   if (no_quit)
2368   /* The instantiate method is allowed to call eval.  Since it
2369      is quite common for this function to get called from somewhere in
2370      redisplay we need to make sure that quits are ignored.  Otherwise
2371      Fsignal will abort. */
2372     specbind (Qinhibit_quit, Qt);
2373
2374   LIST_LOOP (rest, inst_list)
2375     {
2376       Lisp_Object tagged_inst = XCAR (rest);
2377       Lisp_Object tag_set = XCAR (tagged_inst);
2378
2379       if (device_matches_specifier_tag_set_p (device, tag_set))
2380         {
2381           Lisp_Object val = XCDR (tagged_inst);
2382
2383           if (HAS_SPECMETH_P (sp, instantiate))
2384             val = call_with_suspended_errors
2385               ((lisp_fn_t) RAW_SPECMETH (sp, instantiate),
2386                Qunbound, Qspecifier, errb, 5, specifier,
2387                matchspec, domain, val, depth);
2388
2389           if (!UNBOUNDP (val))
2390             {
2391               unbind_to (count, Qnil);
2392               UNGCPRO;
2393               return val;
2394             }
2395         }
2396     }
2397
2398   unbind_to (count, Qnil);
2399   UNGCPRO;
2400   return Qunbound;
2401 }
2402
2403 /* Given a SPECIFIER and a DOMAIN, return a specific instance for that
2404    specifier. Try to find one by checking the specifier types from most
2405    specific (buffer) to most general (global).  If we find an instance,
2406    return it.  Otherwise return Qunbound. */
2407
2408 #define CHECK_INSTANCE_ENTRY(key, matchspec, type)                      \
2409 do {                                                                    \
2410   Lisp_Object *__inst_list =                                            \
2411     specifier_get_inst_list (specifier, key, type);                     \
2412   if (__inst_list)                                                      \
2413     {                                                                   \
2414       Lisp_Object __val__ =                                             \
2415         specifier_instance_from_inst_list (specifier, matchspec,        \
2416                                            domain, *__inst_list,        \
2417                                            errb, no_quit, depth);       \
2418       if (!UNBOUNDP (__val__))                                          \
2419         return __val__;                                                 \
2420     }                                                                   \
2421 } while (0)
2422
2423 /* We accept any window, frame or device domain and do our checking
2424    starting from as specific a locale type as we can determine from the
2425    domain we are passed and going on up through as many other locale types
2426    as we can determine.  In practice, when called from redisplay the
2427    arg will usually be a window and occasionally a frame.  If
2428    triggered by a user call, who knows what it will usually be. */
2429 Lisp_Object
2430 specifier_instance (Lisp_Object specifier, Lisp_Object matchspec,
2431                     Lisp_Object domain, Error_behavior errb, int no_quit,
2432                     int no_fallback, Lisp_Object depth)
2433 {
2434   Lisp_Object buffer = Qnil;
2435   Lisp_Object window = Qnil;
2436   Lisp_Object frame = Qnil;
2437   Lisp_Object device = Qnil;
2438   Lisp_Object tag = Qnil;
2439   struct device *d;
2440   struct Lisp_Specifier *sp;
2441
2442   sp = XSPECIFIER (specifier);
2443
2444   /* Attempt to determine buffer, window, frame, and device from the
2445      domain. */
2446   if (WINDOWP (domain))
2447     window = domain;
2448   else if (FRAMEP (domain))
2449     frame = domain;
2450   else if (DEVICEP (domain))
2451     device = domain;
2452   else
2453     /* #### dmoore - dammit, this should just signal an error or something
2454        shouldn't it?
2455        #### No. Errors are handled in Lisp primitives implementation.
2456        Invalid domain is a design error here - kkm. */
2457     abort ();
2458
2459   if (NILP (buffer) && !NILP (window))
2460     buffer = XWINDOW (window)->buffer;
2461   if (NILP (frame) && !NILP (window))
2462     frame = XWINDOW (window)->frame;
2463   if (NILP (device))
2464     /* frame had better exist; if device is undeterminable, something
2465        really went wrong. */
2466     device = XFRAME (frame)->device;
2467
2468   /* device had better be determined by now; abort if not. */
2469   d = XDEVICE (device);
2470   tag = DEVICE_CLASS (d);
2471
2472   depth = make_int (1 + XINT (depth));
2473   if (XINT (depth) > 20)
2474     {
2475       maybe_error (Qspecifier, errb, "Apparent loop in specifier inheritance");
2476       /* The specification is fucked; at least try the fallback
2477          (which better not be fucked, because it's not changeable
2478          from Lisp). */
2479       depth = Qzero;
2480       goto do_fallback;
2481     }
2482
2483 try_again:
2484   /* First see if we can generate one from the window specifiers. */
2485   if (!NILP (window))
2486     CHECK_INSTANCE_ENTRY (window, matchspec, LOCALE_WINDOW);
2487
2488   /* Next see if we can generate one from the buffer specifiers. */
2489   if (!NILP (buffer))
2490     CHECK_INSTANCE_ENTRY (buffer, matchspec, LOCALE_BUFFER);
2491
2492   /* Next see if we can generate one from the frame specifiers. */
2493   if (!NILP (frame))
2494     CHECK_INSTANCE_ENTRY (frame, matchspec, LOCALE_FRAME);
2495
2496   /* If we still haven't succeeded try with the device specifiers. */
2497   CHECK_INSTANCE_ENTRY (device, matchspec, LOCALE_DEVICE);
2498
2499   /* Last and least try the global specifiers. */
2500   CHECK_INSTANCE_ENTRY (Qglobal, matchspec, LOCALE_GLOBAL);
2501
2502 do_fallback:
2503   /* We're out of specifiers and we still haven't generated an
2504      instance.  At least try the fallback ...  If this fails,
2505      then we just return Qunbound. */
2506
2507   if (no_fallback || NILP (sp->fallback))
2508     /* I said, I don't want the fallbacks. */
2509     return Qunbound;
2510
2511   if (SPECIFIERP (sp->fallback))
2512     {
2513       /* If you introduced loops in the default specifier chain,
2514          then you're fucked, so you better not do this. */
2515       specifier = sp->fallback;
2516       sp = XSPECIFIER (specifier);
2517       goto try_again;
2518     }
2519
2520   assert (CONSP (sp->fallback));
2521   return specifier_instance_from_inst_list (specifier, matchspec, domain,
2522                                             sp->fallback, errb, no_quit,
2523                                             depth);
2524 }
2525 #undef CHECK_INSTANCE_ENTRY
2526
2527 Lisp_Object
2528 specifier_instance_no_quit (Lisp_Object specifier, Lisp_Object matchspec,
2529                             Lisp_Object domain, Error_behavior errb,
2530                             int no_fallback, Lisp_Object depth)
2531 {
2532   return specifier_instance (specifier, matchspec, domain, errb,
2533                              1, no_fallback, depth);
2534 }
2535
2536 DEFUN ("specifier-instance", Fspecifier_instance, 1, 4, 0, /*
2537 Instantiate SPECIFIER (return its value) in DOMAIN.
2538 If no instance can be generated for this domain, return DEFAULT.
2539
2540 DOMAIN should be a window, frame, or device.  Other values that are legal
2541 as a locale (e.g. a buffer) are not valid as a domain because they do not
2542 provide enough information to identify a particular device (see
2543 `valid-specifier-domain-p').  DOMAIN defaults to the selected window
2544 if omitted.
2545
2546 "Instantiating" a specifier in a particular domain means determining
2547 the specifier's "value" in that domain.  This is accomplished by
2548 searching through the specifications in the specifier that correspond
2549 to all locales that can be derived from the given domain, from specific
2550 to general.  In most cases, the domain is an Emacs window.  In that case
2551 specifications are searched for as follows:
2552
2553 1. A specification whose locale is the window itself;
2554 2. A specification whose locale is the window's buffer;
2555 3. A specification whose locale is the window's frame;
2556 4. A specification whose locale is the window's frame's device;
2557 5. A specification whose locale is 'global.
2558
2559 If all of those fail, then the C-code-provided fallback value for
2560 this specifier is consulted (see `specifier-fallback').  If it is
2561 an inst-list, then this function attempts to instantiate that list
2562 just as when a specification is located in the first five steps above.
2563 If the fallback is a specifier, `specifier-instance' is called
2564 recursively on this specifier and the return value used.  Note,
2565 however, that if the optional argument NO-FALLBACK is non-nil,
2566 the fallback value will not be consulted.
2567
2568 Note that there may be more than one specification matching a particular
2569 locale; all such specifications are considered before looking for any
2570 specifications for more general locales.  Any particular specification
2571 that is found may be rejected because its tag set does not match the
2572 device being instantiated over, or because the specification is not
2573 valid for the device of the given domain (e.g. the font or color name
2574 does not exist for this particular X server).
2575
2576 The returned value is dependent on the type of specifier.  For example,
2577 for a font specifier (as returned by the `face-font' function), the returned
2578 value will be a font-instance object.  For glyphs, the returned value
2579 will be a string, pixmap, or subwindow.
2580
2581 See also `specifier-matching-instance'.
2582 */
2583        (specifier, domain, default_, no_fallback))
2584 {
2585   Lisp_Object instance;
2586
2587   CHECK_SPECIFIER (specifier);
2588   domain = decode_domain (domain);
2589
2590   instance = specifier_instance (specifier, Qunbound, domain, ERROR_ME, 0,
2591                                  !NILP (no_fallback), Qzero);
2592   return UNBOUNDP (instance) ? default_ : instance;
2593 }
2594
2595 DEFUN ("specifier-matching-instance", Fspecifier_matching_instance, 2, 5, 0, /*
2596 Return an instance for SPECIFIER in DOMAIN that matches MATCHSPEC.
2597 If no instance can be generated for this domain, return DEFAULT.
2598
2599 This function is identical to `specifier-instance' except that a
2600 specification will only be considered if it matches MATCHSPEC.
2601 The definition of "match", and allowed values for MATCHSPEC, are
2602 dependent on the particular type of specifier.  Here are some examples:
2603
2604 -- For chartable (e.g. display table) specifiers, MATCHSPEC should be a
2605    character, and the specification (a chartable) must give a value for
2606    that character in order to be considered.  This allows you to specify,
2607    e.g., a buffer-local display table that only gives values for particular
2608    characters.  All other characters are handled as if the buffer-local
2609    display table is not there. (Chartable specifiers are not yet
2610    implemented.)
2611
2612 -- For font specifiers, MATCHSPEC should be a charset, and the specification
2613    (a font string) must have a registry that matches the charset's registry.
2614    (This only makes sense with Mule support.) This makes it easy to choose a
2615    font that can display a particular character. (This is what redisplay
2616    does, in fact.)
2617 */
2618        (specifier, matchspec, domain, default_, no_fallback))
2619 {
2620   Lisp_Object instance;
2621
2622   CHECK_SPECIFIER (specifier);
2623   check_valid_specifier_matchspec (matchspec, XSPECIFIER (specifier)->methods,
2624                                    ERROR_ME);
2625   domain = decode_domain (domain);
2626
2627   instance = specifier_instance (specifier, matchspec, domain, ERROR_ME,
2628                                  0, !NILP (no_fallback), Qzero);
2629   return UNBOUNDP (instance) ? default_ : instance;
2630 }
2631
2632 DEFUN ("specifier-instance-from-inst-list", Fspecifier_instance_from_inst_list,
2633        3, 4, 0, /*
2634 Attempt to convert a particular inst-list into an instance.
2635 This attempts to instantiate INST-LIST in the given DOMAIN,
2636 as if INST-LIST existed in a specification in SPECIFIER.  If
2637 the instantiation fails, DEFAULT is returned.  In most circumstances,
2638 you should not use this function; use `specifier-instance' instead.
2639 */
2640        (specifier, domain, inst_list, default_))
2641 {
2642   Lisp_Object val = Qunbound;
2643   struct Lisp_Specifier *sp = XSPECIFIER (specifier);
2644   struct gcpro gcpro1;
2645   Lisp_Object built_up_list = Qnil;
2646
2647   CHECK_SPECIFIER (specifier);
2648   check_valid_domain (domain);
2649   check_valid_inst_list (inst_list, sp->methods, ERROR_ME);
2650   GCPRO1 (built_up_list);
2651   built_up_list = build_up_processed_list (specifier, domain, inst_list);
2652   if (!NILP (built_up_list))
2653     val = specifier_instance_from_inst_list (specifier, Qunbound, domain,
2654                                              built_up_list, ERROR_ME,
2655                                              0, Qzero);
2656   UNGCPRO;
2657   return UNBOUNDP (val) ? default_ : val;
2658 }
2659
2660 DEFUN ("specifier-matching-instance-from-inst-list", Fspecifier_matching_instance_from_inst_list,
2661        4, 5, 0, /*
2662 Attempt to convert a particular inst-list into an instance.
2663 This attempts to instantiate INST-LIST in the given DOMAIN
2664 \(as if INST-LIST existed in a specification in SPECIFIER),
2665 matching the specifications against MATCHSPEC.
2666
2667 This function is analogous to `specifier-instance-from-inst-list'
2668 but allows for specification-matching as in `specifier-matching-instance'.
2669 See that function for a description of exactly how the matching process
2670 works.
2671 */
2672        (specifier, matchspec, domain, inst_list, default_))
2673 {
2674   Lisp_Object val = Qunbound;
2675   struct Lisp_Specifier *sp = XSPECIFIER (specifier);
2676   struct gcpro gcpro1;
2677   Lisp_Object built_up_list = Qnil;
2678
2679   CHECK_SPECIFIER (specifier);
2680   check_valid_specifier_matchspec (matchspec, XSPECIFIER (specifier)->methods,
2681                                    ERROR_ME);
2682   check_valid_domain (domain);
2683   check_valid_inst_list (inst_list, sp->methods, ERROR_ME);
2684   GCPRO1 (built_up_list);
2685   built_up_list = build_up_processed_list (specifier, domain, inst_list);
2686   if (!NILP (built_up_list))
2687     val = specifier_instance_from_inst_list (specifier, matchspec, domain,
2688                                              built_up_list, ERROR_ME,
2689                                              0, Qzero);
2690   UNGCPRO;
2691   return UNBOUNDP (val) ? default_ : val;
2692 }
2693
2694 \f
2695 /************************************************************************/
2696 /*                 Caching in the struct window or frame                */
2697 /************************************************************************/
2698
2699 /* Either STRUCT_WINDOW_OFFSET or STRUCT_FRAME_OFFSET can be 0 to indicate
2700    no caching in that sort of object. */
2701
2702 /* #### It would be nice if the specifier caching automatically knew
2703    about specifier fallbacks, so we didn't have to do it ourselves. */
2704
2705 void
2706 set_specifier_caching (Lisp_Object specifier, int struct_window_offset,
2707                        void (*value_changed_in_window)
2708                        (Lisp_Object specifier, struct window *w,
2709                         Lisp_Object oldval),
2710                        int struct_frame_offset,
2711                        void (*value_changed_in_frame)
2712                        (Lisp_Object specifier, struct frame *f,
2713                         Lisp_Object oldval))
2714 {
2715   struct Lisp_Specifier *sp = XSPECIFIER (specifier);
2716   assert (!GHOST_SPECIFIER_P (sp));
2717
2718   if (!sp->caching)
2719     sp->caching = xnew_and_zero (struct specifier_caching);
2720   sp->caching->offset_into_struct_window = struct_window_offset;
2721   sp->caching->value_changed_in_window = value_changed_in_window;
2722   sp->caching->offset_into_struct_frame = struct_frame_offset;
2723   sp->caching->value_changed_in_frame = value_changed_in_frame;
2724   Vcached_specifiers = Fcons (specifier, Vcached_specifiers);
2725   if (BODILY_SPECIFIER_P (sp))
2726     GHOST_SPECIFIER(sp)->caching = sp->caching;
2727   recompute_cached_specifier_everywhere (specifier);
2728 }
2729
2730 static void
2731 recompute_one_cached_specifier_in_window (Lisp_Object specifier,
2732                                           struct window *w)
2733 {
2734   Lisp_Object window;
2735   Lisp_Object newval, *location;
2736
2737   assert (!GHOST_SPECIFIER_P (XSPECIFIER (specifier)));
2738
2739   XSETWINDOW (window, w);
2740
2741   newval = specifier_instance (specifier, Qunbound, window, ERROR_ME_WARN,
2742                                0, 0, Qzero);
2743   /* If newval ended up Qunbound, then the calling functions
2744      better be able to deal.  If not, set a default so this
2745      never happens or correct it in the value_changed_in_window
2746      method. */
2747   location = (Lisp_Object *)
2748     ((char *) w + XSPECIFIER (specifier)->caching->offset_into_struct_window);
2749   if (!EQ (newval, *location))
2750     {
2751       Lisp_Object oldval = *location;
2752       *location = newval;
2753       (XSPECIFIER (specifier)->caching->value_changed_in_window)
2754         (specifier, w, oldval);
2755     }
2756 }
2757
2758 static void
2759 recompute_one_cached_specifier_in_frame (Lisp_Object specifier,
2760                                          struct frame *f)
2761 {
2762   Lisp_Object frame;
2763   Lisp_Object newval, *location;
2764
2765   assert (!GHOST_SPECIFIER_P (XSPECIFIER (specifier)));
2766
2767   XSETFRAME (frame, f);
2768
2769   newval = specifier_instance (specifier, Qunbound, frame, ERROR_ME_WARN,
2770                                0, 0, Qzero);
2771   /* If newval ended up Qunbound, then the calling functions
2772      better be able to deal.  If not, set a default so this
2773      never happens or correct it in the value_changed_in_frame
2774      method. */
2775   location = (Lisp_Object *)
2776     ((char *) f + XSPECIFIER (specifier)->caching->offset_into_struct_frame);
2777   if (!EQ (newval, *location))
2778     {
2779       Lisp_Object oldval = *location;
2780       *location = newval;
2781       (XSPECIFIER (specifier)->caching->value_changed_in_frame)
2782         (specifier, f, oldval);
2783     }
2784 }
2785
2786 void
2787 recompute_all_cached_specifiers_in_window (struct window *w)
2788 {
2789   Lisp_Object rest;
2790
2791   LIST_LOOP (rest, Vcached_specifiers)
2792     {
2793       Lisp_Object specifier = XCAR (rest);
2794       if (XSPECIFIER (specifier)->caching->offset_into_struct_window)
2795         recompute_one_cached_specifier_in_window (specifier, w);
2796     }
2797 }
2798
2799 void
2800 recompute_all_cached_specifiers_in_frame (struct frame *f)
2801 {
2802   Lisp_Object rest;
2803
2804   LIST_LOOP (rest, Vcached_specifiers)
2805     {
2806       Lisp_Object specifier = XCAR (rest);
2807       if (XSPECIFIER (specifier)->caching->offset_into_struct_frame)
2808         recompute_one_cached_specifier_in_frame (specifier, f);
2809     }
2810 }
2811
2812 static int
2813 recompute_cached_specifier_everywhere_mapfun (struct window *w,
2814                                               void *closure)
2815 {
2816   Lisp_Object specifier = Qnil;
2817
2818   VOID_TO_LISP (specifier, closure);
2819   recompute_one_cached_specifier_in_window (specifier, w);
2820   return 0;
2821 }
2822
2823 static void
2824 recompute_cached_specifier_everywhere (Lisp_Object specifier)
2825 {
2826   Lisp_Object frmcons, devcons, concons;
2827
2828   specifier = bodily_specifier (specifier);
2829
2830   if (!XSPECIFIER (specifier)->caching)
2831     return;
2832
2833   if (XSPECIFIER (specifier)->caching->offset_into_struct_window)
2834     {
2835       FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
2836         map_windows (XFRAME (XCAR (frmcons)),
2837                      recompute_cached_specifier_everywhere_mapfun,
2838                      LISP_TO_VOID (specifier));
2839     }
2840
2841   if (XSPECIFIER (specifier)->caching->offset_into_struct_frame)
2842     {
2843       FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
2844         recompute_one_cached_specifier_in_frame (specifier,
2845                                                  XFRAME (XCAR (frmcons)));
2846     }
2847 }
2848
2849 DEFUN ("set-specifier-dirty-flag", Fset_specifier_dirty_flag, 1, 1, 0, /*
2850 Force recomputation of any caches associated with SPECIFIER.
2851 Note that this automatically happens whenever you change a specification
2852  in SPECIFIER; you do not have to call this function then.
2853 One example of where this function is useful is when you have a
2854  toolbar button whose `active-p' field is an expression to be
2855  evaluated.  Calling `set-specifier-dirty-flag' on the
2856  toolbar specifier will force the `active-p' fields to be
2857  recomputed.
2858 */
2859        (specifier))
2860 {
2861   CHECK_SPECIFIER (specifier);
2862   recompute_cached_specifier_everywhere (specifier);
2863   return Qnil;
2864 }
2865
2866 \f
2867 /************************************************************************/
2868 /*                        Generic specifier type                        */
2869 /************************************************************************/
2870
2871 DEFINE_SPECIFIER_TYPE (generic);
2872
2873 #if 0
2874
2875 /* This is the string that used to be in `generic-specifier-p'.
2876    The idea is good, but it doesn't quite work in the form it's
2877    in. (One major problem is that validating an instantiator
2878    is supposed to require only that the specifier type is passed,
2879    while with this approach the actual specifier is needed.)
2880
2881    What really needs to be done is to write a function
2882    `make-specifier-type' that creates new specifier types.
2883    #### I'll look into this for 19.14.
2884  */
2885
2886 "A generic specifier is a generalized kind of specifier with user-defined\n"
2887 "semantics.  The instantiator can be any kind of Lisp object, and the\n"
2888 "instance computed from it is likewise any kind of Lisp object.  The\n"
2889 "SPECIFIER-DATA should be an alist of methods governing how the specifier\n"
2890 "works.  All methods are optional, and reasonable default methods will be\n"
2891 "provided.  Currently there are two defined methods: 'instantiate and\n"
2892 "'validate.\n"
2893 "\n"
2894 "'instantiate specifies how to do the instantiation; if omitted, the\n"
2895 "instantiator itself is simply returned as the instance.  The method\n"
2896 "should be a function that accepts three parameters (a specifier, the\n"
2897 "instantiator that matched the domain being instantiated over, and that\n"
2898 "domain), and should return a one-element list containing the instance,\n"
2899 "or nil if no instance exists.  Note that the domain passed to this function\n"
2900 "is the domain being instantiated over, which may not be the same as the\n"
2901 "locale contained in the specification corresponding to the instantiator\n"
2902 "(for example, the domain being instantiated over could be a window, but\n"
2903 "the locale corresponding to the passed instantiator could be the window's\n"
2904 "buffer or frame).\n"
2905 "\n"
2906 "'validate specifies whether a given instantiator is valid; if omitted,\n"
2907 "all instantiators are considered valid.  It should be a function of\n"
2908 "two arguments: an instantiator and a flag CAN-SIGNAL-ERROR.  If this\n"
2909 "flag is false, the function must simply return t or nil indicating\n"
2910 "whether the instantiator is valid.  If this flag is true, the function\n"
2911 "is free to signal an error if it encounters an invalid instantiator\n"
2912 "(this can be useful for issuing a specific error about exactly why the\n"
2913 "instantiator is valid).  It can also return nil to indicate an invalid\n"
2914 "instantiator; in this case, a general error will be signalled."
2915
2916 #endif /* 0 */
2917
2918 DEFUN ("generic-specifier-p", Fgeneric_specifier_p, 1, 1, 0, /*
2919 Return non-nil if OBJECT is a generic specifier.
2920
2921 A generic specifier allows any kind of Lisp object as an instantiator,
2922 and returns back the Lisp object unchanged when it is instantiated.
2923 */
2924        (object))
2925 {
2926   return GENERIC_SPECIFIERP (object) ? Qt : Qnil;
2927 }
2928
2929
2930 /************************************************************************/
2931 /*                        Integer specifier type                        */
2932 /************************************************************************/
2933
2934 DEFINE_SPECIFIER_TYPE (integer);
2935
2936 static void
2937 integer_validate (Lisp_Object instantiator)
2938 {
2939   CHECK_INT (instantiator);
2940 }
2941
2942 DEFUN ("integer-specifier-p", Finteger_specifier_p, 1, 1, 0, /*
2943 Return non-nil if OBJECT is an integer specifier.
2944 */
2945        (object))
2946 {
2947   return INTEGER_SPECIFIERP (object) ? Qt : Qnil;
2948 }
2949
2950 /************************************************************************/
2951 /*                   Non-negative-integer specifier type                */
2952 /************************************************************************/
2953
2954 DEFINE_SPECIFIER_TYPE (natnum);
2955
2956 static void
2957 natnum_validate (Lisp_Object instantiator)
2958 {
2959   CHECK_NATNUM (instantiator);
2960 }
2961
2962 DEFUN ("natnum-specifier-p", Fnatnum_specifier_p, 1, 1, 0, /*
2963 Return non-nil if OBJECT is a natnum (non-negative-integer) specifier.
2964 */
2965        (object))
2966 {
2967   return NATNUM_SPECIFIERP (object) ? Qt : Qnil;
2968 }
2969
2970 /************************************************************************/
2971 /*                        Boolean specifier type                        */
2972 /************************************************************************/
2973
2974 DEFINE_SPECIFIER_TYPE (boolean);
2975
2976 static void
2977 boolean_validate (Lisp_Object instantiator)
2978 {
2979   if (!EQ (instantiator, Qt) && !EQ (instantiator, Qnil))
2980     signal_simple_error ("Must be t or nil", instantiator);
2981 }
2982
2983 DEFUN ("boolean-specifier-p", Fboolean_specifier_p, 1, 1, 0, /*
2984 Return non-nil if OBJECT is a boolean specifier.
2985 */
2986        (object))
2987 {
2988   return BOOLEAN_SPECIFIERP (object) ? Qt : Qnil;
2989 }
2990
2991 /************************************************************************/
2992 /*                        Display table specifier type                  */
2993 /************************************************************************/
2994
2995 DEFINE_SPECIFIER_TYPE (display_table);
2996
2997 static void
2998 display_table_validate (Lisp_Object instantiator)
2999 {
3000   if (!NILP(instantiator) &&
3001       (!VECTORP (instantiator) ||
3002        XVECTOR_LENGTH (instantiator) != DISP_TABLE_SIZE))
3003     dead_wrong_type_argument (display_table_specifier_methods->predicate_symbol,
3004                               instantiator);
3005 }
3006
3007 DEFUN ("display-table-specifier-p", Fdisplay_table_specifier_p, 1, 1, 0, /*
3008 Return non-nil if OBJECT is a display-table specifier.
3009 */
3010        (object))
3011 {
3012   return DISPLAYTABLE_SPECIFIERP (object) ? Qt : Qnil;
3013 }
3014
3015 \f
3016 /************************************************************************/
3017 /*                           Initialization                             */
3018 /************************************************************************/
3019
3020 void
3021 syms_of_specifier (void)
3022 {
3023   defsymbol (&Qspecifierp, "specifierp");
3024
3025   defsymbol (&Qconsole_type, "console-type");
3026   defsymbol (&Qdevice_class, "device-class");
3027
3028   /* Qinteger, Qboolean, Qgeneric defined in general.c */
3029   defsymbol (&Qnatnum, "natnum");
3030
3031   DEFSUBR (Fvalid_specifier_type_p);
3032   DEFSUBR (Fspecifier_type_list);
3033   DEFSUBR (Fmake_specifier);
3034   DEFSUBR (Fspecifierp);
3035   DEFSUBR (Fspecifier_type);
3036
3037   DEFSUBR (Fvalid_specifier_locale_p);
3038   DEFSUBR (Fvalid_specifier_domain_p);
3039   DEFSUBR (Fvalid_specifier_locale_type_p);
3040   DEFSUBR (Fspecifier_locale_type_from_locale);
3041
3042   DEFSUBR (Fvalid_specifier_tag_p);
3043   DEFSUBR (Fvalid_specifier_tag_set_p);
3044   DEFSUBR (Fcanonicalize_tag_set);
3045   DEFSUBR (Fdevice_matches_specifier_tag_set_p);
3046   DEFSUBR (Fdefine_specifier_tag);
3047   DEFSUBR (Fdevice_matching_specifier_tag_list);
3048   DEFSUBR (Fspecifier_tag_list);
3049   DEFSUBR (Fspecifier_tag_predicate);
3050
3051   DEFSUBR (Fcheck_valid_instantiator);
3052   DEFSUBR (Fvalid_instantiator_p);
3053   DEFSUBR (Fcheck_valid_inst_list);
3054   DEFSUBR (Fvalid_inst_list_p);
3055   DEFSUBR (Fcheck_valid_spec_list);
3056   DEFSUBR (Fvalid_spec_list_p);
3057   DEFSUBR (Fadd_spec_to_specifier);
3058   DEFSUBR (Fadd_spec_list_to_specifier);
3059   DEFSUBR (Fspecifier_spec_list);
3060   DEFSUBR (Fspecifier_specs);
3061   DEFSUBR (Fremove_specifier);
3062   DEFSUBR (Fcopy_specifier);
3063
3064   DEFSUBR (Fcheck_valid_specifier_matchspec);
3065   DEFSUBR (Fvalid_specifier_matchspec_p);
3066   DEFSUBR (Fspecifier_fallback);
3067   DEFSUBR (Fspecifier_instance);
3068   DEFSUBR (Fspecifier_matching_instance);
3069   DEFSUBR (Fspecifier_instance_from_inst_list);
3070   DEFSUBR (Fspecifier_matching_instance_from_inst_list);
3071   DEFSUBR (Fset_specifier_dirty_flag);
3072
3073   DEFSUBR (Fgeneric_specifier_p);
3074   DEFSUBR (Finteger_specifier_p);
3075   DEFSUBR (Fnatnum_specifier_p);
3076   DEFSUBR (Fboolean_specifier_p);
3077   DEFSUBR (Fdisplay_table_specifier_p);
3078
3079   /* Symbols pertaining to specifier creation.  Specifiers are created
3080      in the syms_of() functions. */
3081
3082   /* locales are defined in general.c. */
3083
3084   defsymbol (&Qprepend, "prepend");
3085   defsymbol (&Qappend, "append");
3086   defsymbol (&Qremove_tag_set_prepend, "remove-tag-set-prepend");
3087   defsymbol (&Qremove_tag_set_append, "remove-tag-set-append");
3088   defsymbol (&Qremove_locale, "remove-locale");
3089   defsymbol (&Qremove_locale_type, "remove-locale-type");
3090   defsymbol (&Qremove_all, "remove-all");
3091
3092   defsymbol (&Qfallback, "fallback");
3093 }
3094
3095 void
3096 specifier_type_create (void)
3097 {
3098   the_specifier_type_entry_dynarr = Dynarr_new (specifier_type_entry);
3099
3100   Vspecifier_type_list = Qnil;
3101   staticpro (&Vspecifier_type_list);
3102
3103   INITIALIZE_SPECIFIER_TYPE (generic, "generic", "generic-specifier-p");
3104
3105   INITIALIZE_SPECIFIER_TYPE (integer, "integer", "integer-specifier-p");
3106
3107   SPECIFIER_HAS_METHOD (integer, validate);
3108
3109   INITIALIZE_SPECIFIER_TYPE (natnum, "natnum", "natnum-specifier-p");
3110
3111   SPECIFIER_HAS_METHOD (natnum, validate);
3112
3113   INITIALIZE_SPECIFIER_TYPE (boolean, "boolean", "boolean-specifier-p");
3114
3115   SPECIFIER_HAS_METHOD (boolean, validate);
3116
3117   INITIALIZE_SPECIFIER_TYPE (display_table, "display-table", "display-table-p");
3118
3119   SPECIFIER_HAS_METHOD (display_table, validate);
3120 }
3121
3122 void
3123 vars_of_specifier (void)
3124 {
3125   Vcached_specifiers = Qnil;
3126   staticpro (&Vcached_specifiers);
3127
3128   /* Do NOT mark through this, or specifiers will never be GC'd.
3129      This is the same deal as for weak hashtables. */
3130   Vall_specifiers = Qnil;
3131
3132   Vuser_defined_tags = Qnil;
3133   staticpro (&Vuser_defined_tags);
3134
3135   Vunlock_ghost_specifiers = Qnil;
3136   staticpro (&Vunlock_ghost_specifiers);
3137 }