1 /* XEmacs routines to deal with CONCORD.
2 Copyright (C) 2005,2006 MORIOKA Tomohiko
4 This file is part of XEmacs.
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Synched up with: Not in FSF. */
23 /* Written by MORIOKA Tomohiko */
33 EXFUN (Fread_from_string, 3);
37 Lisp_Object Qconcord_object;
38 Lisp_Object Qgenre, Q_id;
40 Lisp_Object Vconcord_ds_hash_table;
41 Lisp_Object Vconcord_genre_hash_table;
44 typedef struct Lisp_CONCORD_DS Lisp_CONCORD_DS;
45 DECLARE_LRECORD (concord_ds, Lisp_CONCORD_DS);
47 Lisp_Object Qconcord_dsp;
49 struct Lisp_CONCORD_DS
51 struct lcrecord_header header;
55 #define XCONCORD_DS(x) XRECORD (x, concord_ds, Lisp_CONCORD_DS)
56 #define XSET_CONCORD_DS(x, p) XSETRECORD (x, p, concord_ds)
57 #define CONCORD_DS_P(x) RECORDP (x, concord_ds)
58 #define CHECK_CONCORD_DS(x) CHECK_RECORD (x, concord_ds)
59 #define CONCHECK_CONCORD_DS(x) CONCHECK_RECORD (x, concord_ds)
61 static Lisp_CONCORD_DS*
62 allocate_concord_ds (void)
65 = alloc_lcrecord_type (Lisp_CONCORD_DS, &lrecord_concord_ds);
72 mark_concord_ds (Lisp_Object object)
78 print_concord_ds (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
80 Lisp_CONCORD_DS* lds = XCONCORD_DS (obj);
83 error ("printing unreadable object #<concord_ds 0x%x>", lds->header.uid);
85 write_c_string ("#<concord_ds \"", printcharfun);
86 write_c_string (concord_ds_location (lds->ds), printcharfun);
87 write_c_string ("\">", printcharfun);
91 finalize_concord_ds (void *header, int for_disksave)
93 Lisp_CONCORD_DS *lds = (Lisp_CONCORD_DS *) header;
98 XSET_CONCORD_DS (object, lds);
101 ("Can't dump an emacs containing concord_ds objects", object);
103 if ( lds->ds != NULL)
104 concord_close_ds (lds->ds);
107 DEFINE_LRECORD_IMPLEMENTATION ("concord_ds", concord_ds,
108 mark_concord_ds, print_concord_ds,
109 finalize_concord_ds, 0, 0, 0,
112 DEFUN ("concord-close-ds", Fconcord_close_ds, 1, 1, 0, /*
113 Close concord-ds CONCORD-DS.
117 Lisp_CONCORD_DS* lds;
118 lds = XCONCORD_DS (concord_ds);
119 if ( lds->ds != NULL)
120 concord_close_ds (lds->ds);
125 DEFUN ("concord-ds-p", Fconcord_ds_p, 1, 1, 0, /*
126 Return t if OBJECT is a concord-ds.
130 return CONCORD_DS_P (object) ? Qt : Qnil;
133 DEFUN ("concord-open-ds", Fconcord_open_ds, 1, 4, 0, /*
134 Return a new concord-ds object opened on DIRECTORY.
135 Optional arguments TYPE and SUBTYPE specify the concord_ds type.
136 Optional argument MODE gives the permissions to use when opening DIRECTORY,
137 and defaults to 0755.
139 (directory, type, subtype, mode))
142 Lisp_CONCORD_DS* lds = NULL;
148 CHECK_STRING (directory);
150 directory = Ffile_name_as_directory (Fexpand_file_name (directory, Qnil));
153 retval = Fgethash (directory, Vconcord_ds_hash_table, Qunbound);
154 if (!UNBOUNDP (retval))
159 TO_EXTERNAL_FORMAT (LISP_STRING, directory,
160 C_STRING_ALLOCA, pathname,
165 modemask = 0755; /* rwxr-xr-x */
170 modemask = XINT (mode);
173 ds = concord_open_ds (CONCORD_Backend_Berkeley_DB,
174 pathname, 0, modemask);
178 lds = allocate_concord_ds ();
180 XSET_CONCORD_DS (retval, lds);
181 Fputhash (directory, retval, Vconcord_ds_hash_table);
185 DEFUN ("concord-ds-directory", Fconcord_ds_directory, 1, 1, 0, /*
186 Return directory of concord-ds DS.
190 Lisp_CONCORD_DS* lds;
193 CHECK_CONCORD_DS (ds);
194 lds = XCONCORD_DS (ds);
198 directory = concord_ds_location (lds->ds);
199 if (directory == NULL)
202 return build_ext_string (directory, Qfile_name);
206 DEFUN ("concord-assign-genre", Fconcord_assign_genre, 2, 2, 0, /*
207 Assign data-source DIRECTORY to GENRE.
213 CHECK_SYMBOL (genre);
214 if ( CONCORD_DS_P (directory) )
219 CHECK_STRING (directory);
222 = Ffile_name_as_directory (Fexpand_file_name (directory, Qnil));
225 Fputhash (genre, directory, Vconcord_genre_hash_table);
229 DEFUN ("concord-genre-directory", Fconcord_genre_directory, 1, 1, 0, /*
230 Return pathname of GENRE.
235 CHECK_SYMBOL (genre);
237 retval = Fgethash (genre, Vconcord_genre_hash_table, Qunbound);
238 if ( STRINGP (retval) )
240 else if ( CONCORD_DS_P (retval) )
241 return Fconcord_ds_directory (retval);
245 DEFUN ("concord-genre-ds", Fconcord_genre_ds, 1, 1, 0, /*
246 Return concord-ds of GENRE.
252 CHECK_SYMBOL (genre);
254 retval = Fgethash (genre, Vconcord_genre_hash_table, Qunbound);
255 if ( STRINGP (retval) )
257 retval = Fconcord_open_ds (retval, Qnil, Qnil, Qnil);
258 if ( !NILP (retval) )
259 Fputhash (genre, retval, Vconcord_genre_hash_table);
262 else if ( CONCORD_DS_P (retval) )
268 struct closure_to_list_feature
270 Lisp_Object feature_list;
271 } *concord_feature_list_closure;
274 add_feature_to_list_mapper (CONCORD_Genre genre, char* name)
276 /* This function can GC */
277 concord_feature_list_closure->feature_list
278 = Fcons (intern (name), concord_feature_list_closure->feature_list);
282 DEFUN ("concord-feature-list", Fconcord_feature_list, 1, 2, 0, /*
283 Return the list of all existing features in GENRE.
287 Lisp_CONCORD_DS* lds;
289 CONCORD_Genre c_genre;
292 CHECK_SYMBOL (genre);
294 ds = Fconcord_genre_ds (genre);
295 CHECK_CONCORD_DS (ds);
296 lds = XCONCORD_DS (ds);
299 genre = Fsymbol_name (genre);
300 TO_EXTERNAL_FORMAT (LISP_STRING, genre,
301 C_STRING_ALLOCA, genre_name,
303 c_genre = concord_ds_get_genre (lds->ds, genre_name);
306 concord_feature_list_closure
307 = alloca (sizeof (struct closure_to_list_feature));
308 concord_feature_list_closure->feature_list = Qnil;
309 GCPRO1 (concord_feature_list_closure->feature_list);
310 concord_genre_foreach_feature_name (c_genre,
311 add_feature_to_list_mapper);
313 return concord_feature_list_closure->feature_list;
317 typedef struct Lisp_CONCORD_Object Lisp_CONCORD_Object;
318 DECLARE_LRECORD (concord_object, Lisp_CONCORD_Object);
320 Lisp_Object Qconcord_objectp;
322 struct Lisp_CONCORD_Object
324 struct lcrecord_header header;
329 #define XCONCORD_OBJECT(x) XRECORD (x, concord_object, Lisp_CONCORD_Object)
330 #define XSET_CONCORD_OBJECT(x, p) XSETRECORD (x, p, concord_object)
331 #define CONCORD_OBJECT_P(x) RECORDP (x, concord_object)
332 #define CHECK_CONCORD_OBJECT(x) CHECK_RECORD (x, concord_object)
333 #define CONCHECK_CONCORD_OBJECT(x) CONCHECK_RECORD (x, concord_object)
334 #define CONCORD_OBJECT_GENRE(x) ((x)->genre)
335 #define CONCORD_OBJECT_ID(x) ((x)->id)
336 #define XCONCORD_OBJECT_ID(x) CONCORD_OBJECT_ID (XCONCORD_OBJECT(x))
337 #define XCONCORD_OBJECT_GENRE(x) CONCORD_OBJECT_GENRE (XCONCORD_OBJECT(x))
339 static Lisp_CONCORD_Object*
340 allocate_concord_object (void)
342 Lisp_CONCORD_Object* lcobj
343 = alloc_lcrecord_type (Lisp_CONCORD_Object, &lrecord_concord_object);
346 lcobj->id = Qunbound;
351 mark_concord_object (Lisp_Object object)
353 mark_object (XCONCORD_OBJECT_ID(object));
358 print_concord_object (Lisp_Object obj,
359 Lisp_Object printcharfun, int escapeflag)
361 Lisp_CONCORD_Object* lcobj = XCONCORD_OBJECT (obj);
362 struct gcpro gcpro1, gcpro2;
366 write_c_string ("#s(concord-object", printcharfun);
367 write_c_string (" genre ", printcharfun);
368 write_c_string (concord_genre_get_name (lcobj->genre), printcharfun);
369 write_c_string (" =id ", printcharfun);
370 GCPRO2 (obj, printcharfun);
371 print_internal (lcobj->id, printcharfun, escapeflag);
373 write_c_string (")", printcharfun);
377 write_c_string ("#<concord-object \"", printcharfun);
378 write_c_string (concord_ds_location
379 (concord_genre_get_data_source (lcobj->genre)),
381 write_c_string (":", printcharfun);
382 write_c_string (concord_genre_get_name (lcobj->genre), printcharfun);
383 write_c_string (";", printcharfun);
384 GCPRO2 (obj, printcharfun);
385 print_internal (lcobj->id, printcharfun, escapeflag);
387 write_c_string ("\">", printcharfun);
392 finalize_concord_object (void *header, int for_disksave)
394 Lisp_CONCORD_Object* lcobj = (Lisp_CONCORD_Object *) header;
399 XSET_CONCORD_OBJECT (object, lcobj);
402 ("Can't dump an emacs containing concord_object objects", object);
406 static const struct lrecord_description concord_object_description[] = {
407 { XD_LISP_OBJECT, offsetof (Lisp_CONCORD_Object, id) },
411 DEFINE_LRECORD_IMPLEMENTATION ("concord_object", concord_object,
412 mark_concord_object, print_concord_object,
413 finalize_concord_object, 0, 0,
414 concord_object_description,
415 Lisp_CONCORD_Object);
417 DEFUN ("concord-make-object",
418 Fconcord_make_object, 1, 3, 0, /*
419 Make and return a Concord-object from ID and GENRE.
420 Optional argument DS specifies the data-source of the GENRE.
424 Lisp_CONCORD_DS* lds;
426 CONCORD_Genre c_genre;
427 Lisp_CONCORD_Object* lcobj;
431 ds = Fconcord_genre_ds (genre);
432 CHECK_CONCORD_DS (ds);
433 lds = XCONCORD_DS (ds);
436 if ( !STRINGP(genre) )
437 genre = Fsymbol_name (genre);
438 TO_EXTERNAL_FORMAT (LISP_STRING, genre,
439 C_STRING_ALLOCA, genre_name,
441 c_genre = concord_ds_get_genre (lds->ds, genre_name);
444 lcobj = allocate_concord_object ();
445 lcobj->genre = c_genre;
447 XSET_CONCORD_OBJECT (retval, lcobj);
451 DEFUN ("concord-object-p",
452 Fconcord_object_p, 1, 1, 0, /*
453 Return t if OBJECT is a concord-object.
457 return CONCORD_OBJECT_P (object) ? Qt : Qnil;
460 DEFUN ("concord-object-id",
461 Fconcord_object_id, 1, 1, 0, /*
462 Return an id of Concord-object OBJECT.
466 CHECK_CONCORD_OBJECT (object);
467 return XCONCORD_OBJECT_ID (object);
470 DEFUN ("concord-decode-object",
471 Fconcord_decode_object, 2, 4, 0, /*
472 Make and return a Concord-object from FEATURE and VALUE.
473 Optional argument GENRE specifies the GENRE of the object.
474 Optional argument DS specifies the data-source of the GENRE.
476 (feature, value, genre, ds))
478 Lisp_CONCORD_DS* lds;
480 CONCORD_Genre c_genre;
482 CONCORD_INDEX c_index;
483 Lisp_Object value_string;
485 CONCORD_String_Tank st_id;
488 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
491 ds = Fconcord_genre_ds (genre);
492 CHECK_CONCORD_DS (ds);
493 lds = XCONCORD_DS (ds);
496 if ( !STRINGP(feature) )
497 feature = Fsymbol_name (feature);
498 if ( !STRINGP(genre) )
499 genre = Fsymbol_name (genre);
500 TO_EXTERNAL_FORMAT (LISP_STRING, genre,
501 C_STRING_ALLOCA, genre_name,
503 c_genre = concord_ds_get_genre (lds->ds, genre_name);
509 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
510 C_STRING_ALLOCA, feature_name,
512 c_index = concord_genre_get_index (c_genre, feature_name);
518 GCPRO5 (feature, value, genre, ds, value_string);
519 value_string = Fprin1_to_string (value, Qnil);
521 TO_EXTERNAL_FORMAT (LISP_STRING,
522 value_string, C_STRING_ALLOCA, strid,
524 status = concord_index_strid_get_obj_string (c_index, strid, &st_id);
527 GCPRO3 (genre, ds, obj);
529 obj = read_from_c_string (CONCORD_String_data (&st_id),
530 CONCORD_String_size (&st_id) );
532 obj = Fcar (Fread_from_string (make_ext_string
533 ((char*)CONCORD_String_data (&st_id),
534 CONCORD_String_size (&st_id),
539 return Fconcord_make_object (obj, genre, ds);
544 DEFUN ("concord-object-get",
545 Fconcord_object_get, 2, 2, 0, /*
546 Return the value of OBJECT's FEATURE.
550 struct gcpro gcpro1, gcpro2;
551 Lisp_Object obj_string;
553 CONCORD_Genre c_genre;
555 CONCORD_Feature c_feature;
557 CONCORD_String_Tank st_value;
559 CHECK_CONCORD_OBJECT (object);
560 if ( !STRINGP(feature) )
561 feature = Fsymbol_name (feature);
562 GCPRO2 (object, feature);
563 obj_string = Fprin1_to_string (XCONCORD_OBJECT_ID(object), Qnil);
565 TO_EXTERNAL_FORMAT (LISP_STRING, obj_string,
566 C_STRING_ALLOCA, c_obj, Qfile_name);
567 c_genre = XCONCORD_OBJECT_GENRE(object);
568 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
569 C_STRING_ALLOCA, feature_name,
571 c_feature = concord_genre_get_feature (c_genre, feature_name);
572 if (c_feature == NULL)
576 status = concord_obj_get_feature_value_string (c_obj, c_feature,
581 Fcar (Fread_from_string (make_ext_string
582 ((char*)CONCORD_String_data (&st_value),
583 CONCORD_String_size (&st_value),
590 DEFUN ("concord-object-put",
591 Fconcord_object_put, 3, 3, 0, /*
592 Store a VALUE of OBJECT's FEATURE.
594 (object, feature, value))
596 struct gcpro gcpro1, gcpro2, gcpro3;
597 Lisp_Object obj_string;
599 CONCORD_Genre c_genre;
601 CONCORD_Feature c_feature;
603 Lisp_Object value_string;
606 CHECK_CONCORD_OBJECT (object);
607 if ( !STRINGP(feature) )
608 feature = Fsymbol_name (feature);
609 GCPRO3 (object, feature, value);
610 obj_string = Fprin1_to_string (XCONCORD_OBJECT_ID(object), Qnil);
612 TO_EXTERNAL_FORMAT (LISP_STRING, obj_string,
613 C_STRING_ALLOCA, c_obj, Qfile_name);
614 c_genre = XCONCORD_OBJECT_GENRE(object);
615 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
616 C_STRING_ALLOCA, feature_name,
618 c_feature = concord_genre_get_feature (c_genre, feature_name);
619 if (c_feature == NULL)
623 GCPRO3 (object, feature, value);
624 value_string = Fprin1_to_string (value, Qnil);
626 TO_EXTERNAL_FORMAT (LISP_STRING, value_string,
627 C_STRING_ALLOCA, c_value,
629 status = concord_obj_put_feature_value_str (c_obj, c_feature,
630 (unsigned char*)c_value);
633 status = chise_feature_sync (c_feature);
639 struct closure_for_object_spec
643 } *concord_object_spec_closure;
646 add_feature_to_spec_mapper (CONCORD_Genre genre, char* name)
648 /* This function can GC */
649 CONCORD_String_Tank st_value;
650 CONCORD_Feature c_feature;
653 c_feature = concord_genre_get_feature (genre, name);
654 if (c_feature == NULL)
658 concord_obj_get_feature_value_string
659 (concord_object_spec_closure->object_id, c_feature, &st_value);
662 concord_object_spec_closure->spec
663 = Fcons (Fcons (intern (name),
664 Fcar (Fread_from_string
666 ((char*)CONCORD_String_data (&st_value),
667 CONCORD_String_size (&st_value),
670 concord_object_spec_closure->spec);
675 DEFUN ("concord-object-spec", Fconcord_object_spec, 1, 1, 0, /*
676 Return the spec of OBJECT.
680 Lisp_Object obj_string;
682 CONCORD_Genre c_genre;
683 struct gcpro gcpro1, gcpro2;
685 CHECK_CONCORD_OBJECT (object);
687 obj_string = Fprin1_to_string (XCONCORD_OBJECT_ID(object), Qnil);
689 TO_EXTERNAL_FORMAT (LISP_STRING, obj_string,
690 C_STRING_ALLOCA, c_obj, Qfile_name);
691 c_genre = XCONCORD_OBJECT_GENRE(object);
692 concord_object_spec_closure
693 = alloca (sizeof (struct closure_for_object_spec));
694 concord_object_spec_closure->object_id = c_obj;
695 concord_object_spec_closure->spec = Qnil;
696 GCPRO2 (object, concord_object_spec_closure->spec);
697 concord_genre_foreach_feature_name (c_genre,
698 add_feature_to_spec_mapper);
700 return concord_object_spec_closure->spec;
703 struct closure_for_each_object
705 Lisp_Object function;
709 } *for_each_object_closure;
712 func_for_each_object (CONCORD_String object_id,
713 CONCORD_Feature feature,
714 CONCORD_String value)
716 Lisp_Object obj, val, ret;
719 obj = read_from_c_string (CONCORD_String_data (object_id),
720 CONCORD_String_size (object_id) );
722 obj = Fcar (Fread_from_string (make_ext_string
723 ((char*)CONCORD_String_data (object_id),
724 CONCORD_String_size (object_id),
728 obj = Fconcord_make_object (obj,
729 for_each_object_closure->genre,
730 for_each_object_closure->ds);
732 val = read_from_c_string (CONCORD_String_data (value),
733 CONCORD_String_size (value) );
735 val = Fcar (Fread_from_string (make_ext_string
736 ((char*)CONCORD_String_data (value),
737 CONCORD_String_size (value),
741 ret = call2 (for_each_object_closure->function, obj, val);
742 for_each_object_closure->ret = ret;
746 DEFUN ("concord-for-each-object-in-feature",
747 Fconcord_foreach_object_in_feature, 2, 4, 0, /*
748 Do FUNCTION over objects in FEATURE, calling it with two args,
749 each key and value in the FEATURE table.
750 Optional argument GENRE specifies the genre of the FEATURE.
751 When the FUNCTION returns non-nil, it breaks the repeat.
753 (function, feature, genre, ds))
755 Lisp_CONCORD_DS* lds;
757 CONCORD_Genre c_genre;
759 CONCORD_Feature c_feature;
762 ds = Fconcord_genre_ds (genre);
763 CHECK_CONCORD_DS (ds);
764 lds = XCONCORD_DS (ds);
767 if ( !STRINGP(feature) )
768 feature = Fsymbol_name (feature);
769 if ( !STRINGP(genre) )
770 genre = Fsymbol_name (genre);
771 TO_EXTERNAL_FORMAT (LISP_STRING, genre,
772 C_STRING_ALLOCA, genre_name,
774 c_genre = concord_ds_get_genre (lds->ds, genre_name);
778 CHECK_STRING (feature);
779 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
780 C_STRING_ALLOCA, feature_name,
782 c_feature = concord_genre_get_feature (c_genre, feature_name);
783 if (c_feature == NULL)
785 for_each_object_closure
786 = alloca (sizeof (struct closure_for_each_object));
787 for_each_object_closure->function = function;
788 for_each_object_closure->genre = genre;
789 for_each_object_closure->ds = ds;
790 for_each_object_closure->ret = Qnil;
791 concord_feature_foreach_obj_string (c_feature, func_for_each_object);
793 return for_each_object_closure->ret;
798 concord_name_validate (Lisp_Object keyword, Lisp_Object value,
801 if (ERRB_EQ (errb, ERROR_ME))
803 CHECK_SYMBOL (value);
807 return SYMBOLP (value);
811 concord_object_validate (Lisp_Object data, Error_behavior errb)
813 Lisp_Object valw = Qnil;
814 Lisp_Object genre = Qnil;
815 Lisp_Object oid = Qnil;
817 data = Fcdr (data); /* skip over Qconcord_object */
820 Lisp_Object keyw = Fcar (data);
825 if (EQ (keyw, Qgenre))
827 else if (EQ (keyw, Q_id))
835 maybe_error (Qconcord_object, errb, "No genre given");
840 maybe_error (Qconcord_object, errb, "No object-id given");
844 if (NILP (Fconcord_make_object (oid, genre, Qnil)))
846 maybe_signal_simple_error_2 ("No such Concord-object",
847 oid, genre, Qconcord_object, errb);
855 concord_object_instantiate (Lisp_Object data)
857 return Fconcord_make_object (Fplist_get (data, Q_id, Qnil),
858 Fplist_get (data, Qgenre, Qnil),
864 syms_of_concord (void)
866 INIT_LRECORD_IMPLEMENTATION (concord_ds);
867 INIT_LRECORD_IMPLEMENTATION (concord_object);
869 defsymbol (&Qconcord, "concord");
870 defsymbol (&Qconcord_dsp, "concord-dsp");
871 defsymbol (&Qconcord_objectp, "concord-objectp");
872 defsymbol (&Qconcord_object, "concord-object");
873 defsymbol (&Qgenre, "genre");
874 defsymbol (&Q_id, "=id");
876 DEFSUBR (Fconcord_open_ds);
877 DEFSUBR (Fconcord_ds_p);
878 DEFSUBR (Fconcord_close_ds);
879 DEFSUBR (Fconcord_ds_directory);
881 DEFSUBR (Fconcord_assign_genre);
882 DEFSUBR (Fconcord_genre_directory);
883 DEFSUBR (Fconcord_genre_ds);
884 DEFSUBR (Fconcord_feature_list);
886 DEFSUBR (Fconcord_make_object);
887 DEFSUBR (Fconcord_object_p);
888 DEFSUBR (Fconcord_object_id);
889 DEFSUBR (Fconcord_decode_object);
890 DEFSUBR (Fconcord_object_get);
891 DEFSUBR (Fconcord_object_put);
892 DEFSUBR (Fconcord_object_spec);
893 DEFSUBR (Fconcord_foreach_object_in_feature);
897 structure_type_create_concord (void)
899 struct structure_type *st;
901 st = define_structure_type (Qconcord_object,
902 concord_object_validate,
903 concord_object_instantiate);
905 define_structure_type_keyword (st, Qgenre, concord_name_validate);
906 define_structure_type_keyword (st, Q_id, concord_name_validate);
910 vars_of_concord (void)
914 staticpro (&Vconcord_ds_hash_table);
915 Vconcord_ds_hash_table
916 = make_lisp_hash_table (8, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
918 staticpro (&Vconcord_genre_hash_table);
919 Vconcord_genre_hash_table
920 = make_lisp_hash_table (16, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);