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);
36 EXFUN (Fconcord_decode_object, 4);
37 EXFUN (Fconcord_object_put, 3);
40 Lisp_Object Qconcord_object;
41 Lisp_Object Qgenre, Q_id;
43 Lisp_Object Vconcord_ds_hash_table;
44 Lisp_Object Vconcord_genre_hash_table;
47 typedef struct Lisp_CONCORD_DS Lisp_CONCORD_DS;
48 DECLARE_LRECORD (concord_ds, Lisp_CONCORD_DS);
50 Lisp_Object Qconcord_dsp;
52 struct Lisp_CONCORD_DS
54 struct lcrecord_header header;
58 #define XCONCORD_DS(x) XRECORD (x, concord_ds, Lisp_CONCORD_DS)
59 #define XSET_CONCORD_DS(x, p) XSETRECORD (x, p, concord_ds)
60 #define CONCORD_DS_P(x) RECORDP (x, concord_ds)
61 #define CHECK_CONCORD_DS(x) CHECK_RECORD (x, concord_ds)
62 #define CONCHECK_CONCORD_DS(x) CONCHECK_RECORD (x, concord_ds)
64 static Lisp_CONCORD_DS*
65 allocate_concord_ds (void)
68 = alloc_lcrecord_type (Lisp_CONCORD_DS, &lrecord_concord_ds);
75 mark_concord_ds (Lisp_Object object)
81 print_concord_ds (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
83 Lisp_CONCORD_DS* lds = XCONCORD_DS (obj);
86 error ("printing unreadable object #<concord_ds 0x%x>", lds->header.uid);
88 write_c_string ("#<concord_ds \"", printcharfun);
89 write_c_string (concord_ds_location (lds->ds), printcharfun);
90 write_c_string ("\">", printcharfun);
94 finalize_concord_ds (void *header, int for_disksave)
96 Lisp_CONCORD_DS *lds = (Lisp_CONCORD_DS *) header;
101 XSET_CONCORD_DS (object, lds);
104 ("Can't dump an emacs containing concord_ds objects", object);
106 if ( lds->ds != NULL)
107 concord_close_ds (lds->ds);
110 DEFINE_LRECORD_IMPLEMENTATION ("concord_ds", concord_ds,
111 mark_concord_ds, print_concord_ds,
112 finalize_concord_ds, 0, 0, 0,
115 DEFUN ("concord-close-ds", Fconcord_close_ds, 1, 1, 0, /*
116 Close concord-ds CONCORD-DS.
120 Lisp_CONCORD_DS* lds;
121 lds = XCONCORD_DS (concord_ds);
122 if ( lds->ds != NULL)
123 concord_close_ds (lds->ds);
128 DEFUN ("concord-ds-p", Fconcord_ds_p, 1, 1, 0, /*
129 Return t if OBJECT is a concord-ds.
133 return CONCORD_DS_P (object) ? Qt : Qnil;
136 DEFUN ("concord-open-ds", Fconcord_open_ds, 1, 4, 0, /*
137 Return a new concord-ds object opened on DIRECTORY.
138 Optional arguments TYPE and SUBTYPE specify the concord_ds type.
139 Optional argument MODE gives the permissions to use when opening DIRECTORY,
140 and defaults to 0755.
142 (directory, type, subtype, mode))
145 Lisp_CONCORD_DS* lds = NULL;
151 CHECK_STRING (directory);
153 directory = Ffile_name_as_directory (Fexpand_file_name (directory, Qnil));
156 retval = Fgethash (directory, Vconcord_ds_hash_table, Qunbound);
157 if (!UNBOUNDP (retval))
162 TO_EXTERNAL_FORMAT (LISP_STRING, directory,
163 C_STRING_ALLOCA, pathname,
168 modemask = 0755; /* rwxr-xr-x */
173 modemask = XINT (mode);
176 ds = concord_open_ds (CONCORD_Backend_Berkeley_DB,
177 pathname, 0, modemask);
181 lds = allocate_concord_ds ();
183 XSET_CONCORD_DS (retval, lds);
184 Fputhash (directory, retval, Vconcord_ds_hash_table);
188 DEFUN ("concord-ds-directory", Fconcord_ds_directory, 1, 1, 0, /*
189 Return directory of concord-ds DS.
193 Lisp_CONCORD_DS* lds;
196 CHECK_CONCORD_DS (ds);
197 lds = XCONCORD_DS (ds);
201 directory = concord_ds_location (lds->ds);
202 if (directory == NULL)
205 return build_ext_string (directory, Qfile_name);
209 DEFUN ("concord-assign-genre", Fconcord_assign_genre, 2, 2, 0, /*
210 Assign data-source DIRECTORY to GENRE.
216 CHECK_SYMBOL (genre);
217 if ( CONCORD_DS_P (directory) )
222 CHECK_STRING (directory);
225 = Ffile_name_as_directory (Fexpand_file_name (directory, Qnil));
228 Fputhash (genre, directory, Vconcord_genre_hash_table);
232 DEFUN ("concord-genre-directory", Fconcord_genre_directory, 1, 1, 0, /*
233 Return pathname of GENRE.
238 CHECK_SYMBOL (genre);
240 retval = Fgethash (genre, Vconcord_genre_hash_table, Qunbound);
241 if ( STRINGP (retval) )
243 else if ( CONCORD_DS_P (retval) )
244 return Fconcord_ds_directory (retval);
248 DEFUN ("concord-genre-ds", Fconcord_genre_ds, 1, 1, 0, /*
249 Return concord-ds of GENRE.
255 CHECK_SYMBOL (genre);
257 retval = Fgethash (genre, Vconcord_genre_hash_table, Qunbound);
258 if ( STRINGP (retval) )
260 retval = Fconcord_open_ds (retval, Qnil, Qnil, Qnil);
261 if ( !NILP (retval) )
262 Fputhash (genre, retval, Vconcord_genre_hash_table);
265 else if ( CONCORD_DS_P (retval) )
271 struct closure_to_list_feature
273 Lisp_Object feature_list;
274 } *concord_feature_list_closure;
277 add_feature_to_list_mapper (CONCORD_Genre genre, char* name)
279 /* This function can GC */
280 concord_feature_list_closure->feature_list
281 = Fcons (intern (name), concord_feature_list_closure->feature_list);
285 DEFUN ("concord-feature-list", Fconcord_feature_list, 1, 2, 0, /*
286 Return the list of all existing features in GENRE.
290 Lisp_CONCORD_DS* lds;
292 CONCORD_Genre c_genre;
295 CHECK_SYMBOL (genre);
297 ds = Fconcord_genre_ds (genre);
298 CHECK_CONCORD_DS (ds);
299 lds = XCONCORD_DS (ds);
302 genre = Fsymbol_name (genre);
303 TO_EXTERNAL_FORMAT (LISP_STRING, genre,
304 C_STRING_ALLOCA, genre_name,
306 c_genre = concord_ds_get_genre (lds->ds, genre_name);
309 concord_feature_list_closure
310 = alloca (sizeof (struct closure_to_list_feature));
311 concord_feature_list_closure->feature_list = Qnil;
312 GCPRO1 (concord_feature_list_closure->feature_list);
313 concord_genre_foreach_feature_name (c_genre,
314 add_feature_to_list_mapper);
316 return concord_feature_list_closure->feature_list;
320 typedef struct Lisp_CONCORD_Object Lisp_CONCORD_Object;
321 DECLARE_LRECORD (concord_object, Lisp_CONCORD_Object);
323 Lisp_Object Qconcord_objectp;
325 struct Lisp_CONCORD_Object
327 struct lcrecord_header header;
332 #define XCONCORD_OBJECT(x) XRECORD (x, concord_object, Lisp_CONCORD_Object)
333 #define XSET_CONCORD_OBJECT(x, p) XSETRECORD (x, p, concord_object)
334 #define CONCORD_OBJECT_P(x) RECORDP (x, concord_object)
335 #define CHECK_CONCORD_OBJECT(x) CHECK_RECORD (x, concord_object)
336 #define CONCHECK_CONCORD_OBJECT(x) CONCHECK_RECORD (x, concord_object)
337 #define CONCORD_OBJECT_GENRE(x) ((x)->genre)
338 #define CONCORD_OBJECT_ID(x) ((x)->id)
339 #define XCONCORD_OBJECT_ID(x) CONCORD_OBJECT_ID (XCONCORD_OBJECT(x))
340 #define XCONCORD_OBJECT_GENRE(x) CONCORD_OBJECT_GENRE (XCONCORD_OBJECT(x))
342 static Lisp_CONCORD_Object*
343 allocate_concord_object (void)
345 Lisp_CONCORD_Object* lcobj
346 = alloc_lcrecord_type (Lisp_CONCORD_Object, &lrecord_concord_object);
349 lcobj->id = Qunbound;
354 mark_concord_object (Lisp_Object object)
356 mark_object (XCONCORD_OBJECT_ID(object));
361 print_concord_object (Lisp_Object obj,
362 Lisp_Object printcharfun, int escapeflag)
364 Lisp_CONCORD_Object* lcobj = XCONCORD_OBJECT (obj);
365 struct gcpro gcpro1, gcpro2;
369 write_c_string ("#s(concord-object", printcharfun);
370 write_c_string (" genre ", printcharfun);
371 write_c_string (concord_genre_get_name (lcobj->genre), printcharfun);
372 write_c_string (" =id ", printcharfun);
373 GCPRO2 (obj, printcharfun);
374 print_internal (lcobj->id, printcharfun, escapeflag);
376 write_c_string (")", printcharfun);
380 write_c_string ("#<concord-object \"", printcharfun);
381 write_c_string (concord_ds_location
382 (concord_genre_get_data_source (lcobj->genre)),
384 write_c_string (":", printcharfun);
385 write_c_string (concord_genre_get_name (lcobj->genre), printcharfun);
386 write_c_string (";", printcharfun);
387 GCPRO2 (obj, printcharfun);
388 print_internal (lcobj->id, printcharfun, escapeflag);
390 write_c_string ("\">", printcharfun);
395 finalize_concord_object (void *header, int for_disksave)
397 Lisp_CONCORD_Object* lcobj = (Lisp_CONCORD_Object *) header;
402 XSET_CONCORD_OBJECT (object, lcobj);
405 ("Can't dump an emacs containing concord_object objects", object);
409 static const struct lrecord_description concord_object_description[] = {
410 { XD_LISP_OBJECT, offsetof (Lisp_CONCORD_Object, id) },
414 DEFINE_LRECORD_IMPLEMENTATION ("concord_object", concord_object,
415 mark_concord_object, print_concord_object,
416 finalize_concord_object, 0, 0,
417 concord_object_description,
418 Lisp_CONCORD_Object);
420 DEFUN ("concord-make-object", Fconcord_make_object, 1, 3, 0, /*
421 Make and return a Concord-object from ID and GENRE.
422 Optional argument DS specifies the data-source of the GENRE.
426 Lisp_CONCORD_DS* lds;
428 CONCORD_Genre c_genre;
429 Lisp_CONCORD_Object* lcobj;
433 ds = Fconcord_genre_ds (genre);
434 CHECK_CONCORD_DS (ds);
435 lds = XCONCORD_DS (ds);
438 if ( !STRINGP(genre) )
439 genre = Fsymbol_name (genre);
440 TO_EXTERNAL_FORMAT (LISP_STRING, genre,
441 C_STRING_ALLOCA, genre_name,
443 c_genre = concord_ds_get_genre (lds->ds, genre_name);
449 retval = Fconcord_decode_object (Q_id, id, genre, ds);
454 lcobj = allocate_concord_object ();
455 lcobj->genre = c_genre;
457 XSET_CONCORD_OBJECT (retval, lcobj);
461 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
463 GCPRO4 (retval, id, genre, ds);
464 Fconcord_object_put (retval, Q_id, id);
471 DEFUN ("concord-object-p", Fconcord_object_p, 1, 1, 0, /*
472 Return t if OBJECT is a concord-object.
476 return CONCORD_OBJECT_P (object) ? Qt : Qnil;
479 DEFUN ("concord-object-id", Fconcord_object_id, 1, 1, 0, /*
480 Return an id of Concord-object OBJECT.
484 CHECK_CONCORD_OBJECT (object);
485 return XCONCORD_OBJECT_ID (object);
488 DEFUN ("concord-decode-object", Fconcord_decode_object, 2, 4, 0, /*
489 Make and return a Concord-object from FEATURE and VALUE.
490 Optional argument GENRE specifies the GENRE of the object.
491 Optional argument DS specifies the data-source of the GENRE.
493 (feature, value, genre, ds))
495 Lisp_CONCORD_DS* lds;
497 CONCORD_Genre c_genre;
499 CONCORD_INDEX c_index;
500 Lisp_Object value_string;
502 CONCORD_String_Tank st_id;
505 int previous_print_readably;
506 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
509 ds = Fconcord_genre_ds (genre);
510 CHECK_CONCORD_DS (ds);
511 lds = XCONCORD_DS (ds);
514 if ( !STRINGP(feature) )
515 feature = Fsymbol_name (feature);
516 if ( !STRINGP(genre) )
517 genre = Fsymbol_name (genre);
518 TO_EXTERNAL_FORMAT (LISP_STRING, genre,
519 C_STRING_ALLOCA, genre_name,
521 c_genre = concord_ds_get_genre (lds->ds, genre_name);
527 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
528 C_STRING_ALLOCA, feature_name,
530 c_index = concord_genre_get_index (c_genre, feature_name);
536 previous_print_readably = print_readably;
538 GCPRO5 (feature, value, genre, ds, value_string);
539 value_string = Fprin1_to_string (value, Qnil);
541 print_readably = previous_print_readably;
542 TO_EXTERNAL_FORMAT (LISP_STRING,
543 value_string, C_STRING_ALLOCA, strid,
545 status = concord_index_strid_get_obj_string (c_index, strid, &st_id);
548 GCPRO3 (genre, ds, obj);
550 obj = read_from_c_string (CONCORD_String_data (&st_id),
551 CONCORD_String_size (&st_id) );
553 obj = Fcar (Fread_from_string (make_ext_string
554 ((char*)CONCORD_String_data (&st_id),
555 CONCORD_String_size (&st_id),
560 return Fconcord_make_object (genre, obj, ds);
565 DEFUN ("concord-object-get", Fconcord_object_get, 2, 2, 0, /*
566 Return the value of OBJECT's FEATURE.
570 struct gcpro gcpro1, gcpro2;
571 int previous_print_readably;
572 Lisp_Object obj_string;
574 CONCORD_Genre c_genre;
576 CONCORD_Feature c_feature;
578 CONCORD_String_Tank st_value;
580 CHECK_CONCORD_OBJECT (object);
581 if ( !STRINGP(feature) )
582 feature = Fsymbol_name (feature);
583 previous_print_readably = print_readably;
585 GCPRO2 (object, feature);
586 obj_string = Fprin1_to_string (XCONCORD_OBJECT_ID(object), Qnil);
588 print_readably = previous_print_readably;
589 TO_EXTERNAL_FORMAT (LISP_STRING, obj_string,
590 C_STRING_ALLOCA, c_obj, Qfile_name);
591 c_genre = XCONCORD_OBJECT_GENRE(object);
592 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
593 C_STRING_ALLOCA, feature_name,
595 c_feature = concord_genre_get_feature (c_genre, feature_name);
596 if (c_feature == NULL)
600 status = concord_obj_get_feature_value_string (c_obj, c_feature,
605 Fcar (Fread_from_string (make_ext_string
606 ((char*)CONCORD_String_data (&st_value),
607 CONCORD_String_size (&st_value),
614 DEFUN ("concord-object-put", Fconcord_object_put, 3, 3, 0, /*
615 Store a VALUE of OBJECT's FEATURE.
617 (object, feature, value))
619 struct gcpro gcpro1, gcpro2, gcpro3;
620 int previous_print_readably;
621 Lisp_Object obj_string;
623 CONCORD_Genre c_genre;
625 CONCORD_Feature c_feature;
627 Lisp_Object value_string;
630 CHECK_CONCORD_OBJECT (object);
631 if ( !STRINGP(feature) )
632 feature = Fsymbol_name (feature);
633 previous_print_readably = print_readably;
635 GCPRO3 (object, feature, value);
636 obj_string = Fprin1_to_string (XCONCORD_OBJECT_ID(object), Qnil);
638 print_readably = previous_print_readably;
639 TO_EXTERNAL_FORMAT (LISP_STRING, obj_string,
640 C_STRING_ALLOCA, c_obj, Qfile_name);
641 c_genre = XCONCORD_OBJECT_GENRE(object);
642 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
643 C_STRING_ALLOCA, feature_name,
645 c_feature = concord_genre_get_feature (c_genre, feature_name);
646 if (c_feature == NULL)
650 previous_print_readably = print_readably;
652 GCPRO3 (object, feature, value);
653 value_string = Fprin1_to_string (value, Qnil);
655 print_readably = previous_print_readably;
656 TO_EXTERNAL_FORMAT (LISP_STRING, value_string,
657 C_STRING_ALLOCA, c_value,
659 status = concord_obj_put_feature_value_str (c_obj, c_feature,
660 (unsigned char*)c_value);
663 status = chise_feature_sync (c_feature);
666 if (feature_name[0] == '=')
668 CONCORD_INDEX c_index
669 = concord_genre_get_index (c_genre, feature_name);
671 status = concord_index_strid_put_obj (c_index, c_value, c_obj);
676 struct closure_for_object_spec
680 } *concord_object_spec_closure;
683 add_feature_to_spec_mapper (CONCORD_Genre genre, char* name)
685 /* This function can GC */
686 CONCORD_String_Tank st_value;
687 CONCORD_Feature c_feature;
690 c_feature = concord_genre_get_feature (genre, name);
691 if (c_feature == NULL)
695 concord_obj_get_feature_value_string
696 (concord_object_spec_closure->object_id, c_feature, &st_value);
699 concord_object_spec_closure->spec
700 = Fcons (Fcons (intern (name),
701 Fcar (Fread_from_string
703 ((char*)CONCORD_String_data (&st_value),
704 CONCORD_String_size (&st_value),
707 concord_object_spec_closure->spec);
712 DEFUN ("concord-object-spec", Fconcord_object_spec, 1, 1, 0, /*
713 Return the spec of OBJECT.
717 Lisp_Object obj_string;
719 CONCORD_Genre c_genre;
720 struct gcpro gcpro1, gcpro2;
721 int previous_print_readably;
723 CHECK_CONCORD_OBJECT (object);
724 previous_print_readably = print_readably;
727 obj_string = Fprin1_to_string (XCONCORD_OBJECT_ID(object), Qnil);
729 print_readably = previous_print_readably;
730 TO_EXTERNAL_FORMAT (LISP_STRING, obj_string,
731 C_STRING_ALLOCA, c_obj, Qfile_name);
732 c_genre = XCONCORD_OBJECT_GENRE(object);
733 concord_object_spec_closure
734 = alloca (sizeof (struct closure_for_object_spec));
735 concord_object_spec_closure->object_id = c_obj;
736 concord_object_spec_closure->spec = Qnil;
737 GCPRO2 (object, concord_object_spec_closure->spec);
738 concord_genre_foreach_feature_name (c_genre,
739 add_feature_to_spec_mapper);
741 return concord_object_spec_closure->spec;
744 struct closure_for_each_object
746 Lisp_Object function;
750 } *for_each_object_closure;
753 func_for_each_object (CONCORD_String object_id,
754 CONCORD_Feature feature,
755 CONCORD_String value)
757 Lisp_Object obj, val, ret;
760 obj = read_from_c_string (CONCORD_String_data (object_id),
761 CONCORD_String_size (object_id) );
763 obj = Fcar (Fread_from_string (make_ext_string
764 ((char*)CONCORD_String_data (object_id),
765 CONCORD_String_size (object_id),
769 obj = Fconcord_make_object (for_each_object_closure->genre,
771 for_each_object_closure->ds);
773 val = read_from_c_string (CONCORD_String_data (value),
774 CONCORD_String_size (value) );
776 val = Fcar (Fread_from_string (make_ext_string
777 ((char*)CONCORD_String_data (value),
778 CONCORD_String_size (value),
782 ret = call2 (for_each_object_closure->function, obj, val);
783 for_each_object_closure->ret = ret;
787 DEFUN ("concord-for-each-object-in-feature",
788 Fconcord_foreach_object_in_feature, 2, 4, 0, /*
789 Do FUNCTION over objects in FEATURE, calling it with two args,
790 each key and value in the FEATURE table.
791 Optional argument GENRE specifies the genre of the FEATURE.
792 When the FUNCTION returns non-nil, it breaks the repeat.
794 (function, feature, genre, ds))
796 Lisp_CONCORD_DS* lds;
798 CONCORD_Genre c_genre;
800 CONCORD_Feature c_feature;
803 ds = Fconcord_genre_ds (genre);
804 CHECK_CONCORD_DS (ds);
805 lds = XCONCORD_DS (ds);
808 if ( !STRINGP(feature) )
809 feature = Fsymbol_name (feature);
810 if ( !STRINGP(genre) )
811 genre = Fsymbol_name (genre);
812 TO_EXTERNAL_FORMAT (LISP_STRING, genre,
813 C_STRING_ALLOCA, genre_name,
815 c_genre = concord_ds_get_genre (lds->ds, genre_name);
819 CHECK_STRING (feature);
820 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
821 C_STRING_ALLOCA, feature_name,
823 c_feature = concord_genre_get_feature (c_genre, feature_name);
824 if (c_feature == NULL)
826 for_each_object_closure
827 = alloca (sizeof (struct closure_for_each_object));
828 for_each_object_closure->function = function;
829 for_each_object_closure->genre = genre;
830 for_each_object_closure->ds = ds;
831 for_each_object_closure->ret = Qnil;
832 concord_feature_foreach_obj_string (c_feature, func_for_each_object);
834 return for_each_object_closure->ret;
839 concord_name_validate (Lisp_Object keyword, Lisp_Object value,
842 if (ERRB_EQ (errb, ERROR_ME))
844 CHECK_SYMBOL (value);
848 return SYMBOLP (value);
852 concord_object_validate (Lisp_Object data, Error_behavior errb)
854 Lisp_Object valw = Qnil;
855 Lisp_Object genre = Qnil;
856 Lisp_Object oid = Qnil;
858 data = Fcdr (data); /* skip over Qconcord_object */
861 Lisp_Object keyw = Fcar (data);
866 if (EQ (keyw, Qgenre))
868 else if (EQ (keyw, Q_id))
876 maybe_error (Qconcord_object, errb, "No genre given");
881 maybe_error (Qconcord_object, errb, "No object-id given");
885 if (NILP (Fconcord_make_object (genre, oid, Qnil)))
887 maybe_signal_simple_error_2 ("No such Concord-object",
888 oid, genre, Qconcord_object, errb);
896 concord_object_instantiate (Lisp_Object data)
898 struct gcpro gcpro1, gcpro2;
901 GCPRO2 (data, retval);
902 retval = Fconcord_make_object (Fplist_get (data, Qgenre, Qnil),
903 Fplist_get (data, Q_id, Qnil),
911 syms_of_concord (void)
913 INIT_LRECORD_IMPLEMENTATION (concord_ds);
914 INIT_LRECORD_IMPLEMENTATION (concord_object);
916 defsymbol (&Qconcord, "concord");
917 defsymbol (&Qconcord_dsp, "concord-dsp");
918 defsymbol (&Qconcord_objectp, "concord-objectp");
919 defsymbol (&Qconcord_object, "concord-object");
920 defsymbol (&Qgenre, "genre");
921 defsymbol (&Q_id, "=id");
923 DEFSUBR (Fconcord_open_ds);
924 DEFSUBR (Fconcord_ds_p);
925 DEFSUBR (Fconcord_close_ds);
926 DEFSUBR (Fconcord_ds_directory);
928 DEFSUBR (Fconcord_assign_genre);
929 DEFSUBR (Fconcord_genre_directory);
930 DEFSUBR (Fconcord_genre_ds);
931 DEFSUBR (Fconcord_feature_list);
933 DEFSUBR (Fconcord_make_object);
934 DEFSUBR (Fconcord_object_p);
935 DEFSUBR (Fconcord_object_id);
936 DEFSUBR (Fconcord_decode_object);
937 DEFSUBR (Fconcord_object_get);
938 DEFSUBR (Fconcord_object_put);
939 DEFSUBR (Fconcord_object_spec);
940 DEFSUBR (Fconcord_foreach_object_in_feature);
944 structure_type_create_concord (void)
946 struct structure_type *st;
948 st = define_structure_type (Qconcord_object,
949 concord_object_validate,
950 concord_object_instantiate);
952 define_structure_type_keyword (st, Qgenre, concord_name_validate);
953 define_structure_type_keyword (st, Q_id, concord_name_validate);
957 vars_of_concord (void)
961 staticpro (&Vconcord_ds_hash_table);
962 Vconcord_ds_hash_table
963 = make_lisp_hash_table (8, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
965 staticpro (&Vconcord_genre_hash_table);
966 Vconcord_genre_hash_table
967 = make_lisp_hash_table (16, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);