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 int previous_print_readably;
489 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
492 ds = Fconcord_genre_ds (genre);
493 CHECK_CONCORD_DS (ds);
494 lds = XCONCORD_DS (ds);
497 if ( !STRINGP(feature) )
498 feature = Fsymbol_name (feature);
499 if ( !STRINGP(genre) )
500 genre = Fsymbol_name (genre);
501 TO_EXTERNAL_FORMAT (LISP_STRING, genre,
502 C_STRING_ALLOCA, genre_name,
504 c_genre = concord_ds_get_genre (lds->ds, genre_name);
510 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
511 C_STRING_ALLOCA, feature_name,
513 c_index = concord_genre_get_index (c_genre, feature_name);
519 previous_print_readably = print_readably;
521 GCPRO5 (feature, value, genre, ds, value_string);
522 value_string = Fprin1_to_string (value, Qnil);
524 print_readably = previous_print_readably;
525 TO_EXTERNAL_FORMAT (LISP_STRING,
526 value_string, C_STRING_ALLOCA, strid,
528 status = concord_index_strid_get_obj_string (c_index, strid, &st_id);
531 GCPRO3 (genre, ds, obj);
533 obj = read_from_c_string (CONCORD_String_data (&st_id),
534 CONCORD_String_size (&st_id) );
536 obj = Fcar (Fread_from_string (make_ext_string
537 ((char*)CONCORD_String_data (&st_id),
538 CONCORD_String_size (&st_id),
543 return Fconcord_make_object (obj, genre, ds);
548 DEFUN ("concord-object-get",
549 Fconcord_object_get, 2, 2, 0, /*
550 Return the value of OBJECT's FEATURE.
554 struct gcpro gcpro1, gcpro2;
555 int previous_print_readably;
556 Lisp_Object obj_string;
558 CONCORD_Genre c_genre;
560 CONCORD_Feature c_feature;
562 CONCORD_String_Tank st_value;
564 CHECK_CONCORD_OBJECT (object);
565 if ( !STRINGP(feature) )
566 feature = Fsymbol_name (feature);
567 previous_print_readably = print_readably;
569 GCPRO2 (object, feature);
570 obj_string = Fprin1_to_string (XCONCORD_OBJECT_ID(object), Qnil);
572 print_readably = previous_print_readably;
573 TO_EXTERNAL_FORMAT (LISP_STRING, obj_string,
574 C_STRING_ALLOCA, c_obj, Qfile_name);
575 c_genre = XCONCORD_OBJECT_GENRE(object);
576 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
577 C_STRING_ALLOCA, feature_name,
579 c_feature = concord_genre_get_feature (c_genre, feature_name);
580 if (c_feature == NULL)
584 status = concord_obj_get_feature_value_string (c_obj, c_feature,
589 Fcar (Fread_from_string (make_ext_string
590 ((char*)CONCORD_String_data (&st_value),
591 CONCORD_String_size (&st_value),
598 DEFUN ("concord-object-put", Fconcord_object_put, 3, 3, 0, /*
599 Store a VALUE of OBJECT's FEATURE.
601 (object, feature, value))
603 struct gcpro gcpro1, gcpro2, gcpro3;
604 int previous_print_readably;
605 Lisp_Object obj_string;
607 CONCORD_Genre c_genre;
609 CONCORD_Feature c_feature;
611 Lisp_Object value_string;
614 CHECK_CONCORD_OBJECT (object);
615 if ( !STRINGP(feature) )
616 feature = Fsymbol_name (feature);
617 previous_print_readably = print_readably;
619 GCPRO3 (object, feature, value);
620 obj_string = Fprin1_to_string (XCONCORD_OBJECT_ID(object), Qnil);
622 print_readably = previous_print_readably;
623 TO_EXTERNAL_FORMAT (LISP_STRING, obj_string,
624 C_STRING_ALLOCA, c_obj, Qfile_name);
625 c_genre = XCONCORD_OBJECT_GENRE(object);
626 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
627 C_STRING_ALLOCA, feature_name,
629 c_feature = concord_genre_get_feature (c_genre, feature_name);
630 if (c_feature == NULL)
634 previous_print_readably = print_readably;
636 GCPRO3 (object, feature, value);
637 value_string = Fprin1_to_string (value, Qnil);
639 print_readably = previous_print_readably;
640 TO_EXTERNAL_FORMAT (LISP_STRING, value_string,
641 C_STRING_ALLOCA, c_value,
643 status = concord_obj_put_feature_value_str (c_obj, c_feature,
644 (unsigned char*)c_value);
647 status = chise_feature_sync (c_feature);
650 if (feature_name[0] == '=')
652 CONCORD_INDEX c_index
653 = concord_genre_get_index (c_genre, feature_name);
655 status = concord_index_strid_put_obj (c_index, c_value, c_obj);
660 struct closure_for_object_spec
664 } *concord_object_spec_closure;
667 add_feature_to_spec_mapper (CONCORD_Genre genre, char* name)
669 /* This function can GC */
670 CONCORD_String_Tank st_value;
671 CONCORD_Feature c_feature;
674 c_feature = concord_genre_get_feature (genre, name);
675 if (c_feature == NULL)
679 concord_obj_get_feature_value_string
680 (concord_object_spec_closure->object_id, c_feature, &st_value);
683 concord_object_spec_closure->spec
684 = Fcons (Fcons (intern (name),
685 Fcar (Fread_from_string
687 ((char*)CONCORD_String_data (&st_value),
688 CONCORD_String_size (&st_value),
691 concord_object_spec_closure->spec);
696 DEFUN ("concord-object-spec", Fconcord_object_spec, 1, 1, 0, /*
697 Return the spec of OBJECT.
701 Lisp_Object obj_string;
703 CONCORD_Genre c_genre;
704 struct gcpro gcpro1, gcpro2;
705 int previous_print_readably;
707 CHECK_CONCORD_OBJECT (object);
708 previous_print_readably = print_readably;
711 obj_string = Fprin1_to_string (XCONCORD_OBJECT_ID(object), Qnil);
713 print_readably = previous_print_readably;
714 TO_EXTERNAL_FORMAT (LISP_STRING, obj_string,
715 C_STRING_ALLOCA, c_obj, Qfile_name);
716 c_genre = XCONCORD_OBJECT_GENRE(object);
717 concord_object_spec_closure
718 = alloca (sizeof (struct closure_for_object_spec));
719 concord_object_spec_closure->object_id = c_obj;
720 concord_object_spec_closure->spec = Qnil;
721 GCPRO2 (object, concord_object_spec_closure->spec);
722 concord_genre_foreach_feature_name (c_genre,
723 add_feature_to_spec_mapper);
725 return concord_object_spec_closure->spec;
728 struct closure_for_each_object
730 Lisp_Object function;
734 } *for_each_object_closure;
737 func_for_each_object (CONCORD_String object_id,
738 CONCORD_Feature feature,
739 CONCORD_String value)
741 Lisp_Object obj, val, ret;
744 obj = read_from_c_string (CONCORD_String_data (object_id),
745 CONCORD_String_size (object_id) );
747 obj = Fcar (Fread_from_string (make_ext_string
748 ((char*)CONCORD_String_data (object_id),
749 CONCORD_String_size (object_id),
753 obj = Fconcord_make_object (obj,
754 for_each_object_closure->genre,
755 for_each_object_closure->ds);
757 val = read_from_c_string (CONCORD_String_data (value),
758 CONCORD_String_size (value) );
760 val = Fcar (Fread_from_string (make_ext_string
761 ((char*)CONCORD_String_data (value),
762 CONCORD_String_size (value),
766 ret = call2 (for_each_object_closure->function, obj, val);
767 for_each_object_closure->ret = ret;
771 DEFUN ("concord-for-each-object-in-feature",
772 Fconcord_foreach_object_in_feature, 2, 4, 0, /*
773 Do FUNCTION over objects in FEATURE, calling it with two args,
774 each key and value in the FEATURE table.
775 Optional argument GENRE specifies the genre of the FEATURE.
776 When the FUNCTION returns non-nil, it breaks the repeat.
778 (function, feature, genre, ds))
780 Lisp_CONCORD_DS* lds;
782 CONCORD_Genre c_genre;
784 CONCORD_Feature c_feature;
787 ds = Fconcord_genre_ds (genre);
788 CHECK_CONCORD_DS (ds);
789 lds = XCONCORD_DS (ds);
792 if ( !STRINGP(feature) )
793 feature = Fsymbol_name (feature);
794 if ( !STRINGP(genre) )
795 genre = Fsymbol_name (genre);
796 TO_EXTERNAL_FORMAT (LISP_STRING, genre,
797 C_STRING_ALLOCA, genre_name,
799 c_genre = concord_ds_get_genre (lds->ds, genre_name);
803 CHECK_STRING (feature);
804 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
805 C_STRING_ALLOCA, feature_name,
807 c_feature = concord_genre_get_feature (c_genre, feature_name);
808 if (c_feature == NULL)
810 for_each_object_closure
811 = alloca (sizeof (struct closure_for_each_object));
812 for_each_object_closure->function = function;
813 for_each_object_closure->genre = genre;
814 for_each_object_closure->ds = ds;
815 for_each_object_closure->ret = Qnil;
816 concord_feature_foreach_obj_string (c_feature, func_for_each_object);
818 return for_each_object_closure->ret;
823 concord_name_validate (Lisp_Object keyword, Lisp_Object value,
826 if (ERRB_EQ (errb, ERROR_ME))
828 CHECK_SYMBOL (value);
832 return SYMBOLP (value);
836 concord_object_validate (Lisp_Object data, Error_behavior errb)
838 Lisp_Object valw = Qnil;
839 Lisp_Object genre = Qnil;
840 Lisp_Object oid = Qnil;
842 data = Fcdr (data); /* skip over Qconcord_object */
845 Lisp_Object keyw = Fcar (data);
850 if (EQ (keyw, Qgenre))
852 else if (EQ (keyw, Q_id))
860 maybe_error (Qconcord_object, errb, "No genre given");
865 maybe_error (Qconcord_object, errb, "No object-id given");
869 if (NILP (Fconcord_make_object (oid, genre, Qnil)))
871 maybe_signal_simple_error_2 ("No such Concord-object",
872 oid, genre, Qconcord_object, errb);
880 concord_object_instantiate (Lisp_Object data)
882 return Fconcord_make_object (Fplist_get (data, Q_id, Qnil),
883 Fplist_get (data, Qgenre, Qnil),
889 syms_of_concord (void)
891 INIT_LRECORD_IMPLEMENTATION (concord_ds);
892 INIT_LRECORD_IMPLEMENTATION (concord_object);
894 defsymbol (&Qconcord, "concord");
895 defsymbol (&Qconcord_dsp, "concord-dsp");
896 defsymbol (&Qconcord_objectp, "concord-objectp");
897 defsymbol (&Qconcord_object, "concord-object");
898 defsymbol (&Qgenre, "genre");
899 defsymbol (&Q_id, "=id");
901 DEFSUBR (Fconcord_open_ds);
902 DEFSUBR (Fconcord_ds_p);
903 DEFSUBR (Fconcord_close_ds);
904 DEFSUBR (Fconcord_ds_directory);
906 DEFSUBR (Fconcord_assign_genre);
907 DEFSUBR (Fconcord_genre_directory);
908 DEFSUBR (Fconcord_genre_ds);
909 DEFSUBR (Fconcord_feature_list);
911 DEFSUBR (Fconcord_make_object);
912 DEFSUBR (Fconcord_object_p);
913 DEFSUBR (Fconcord_object_id);
914 DEFSUBR (Fconcord_decode_object);
915 DEFSUBR (Fconcord_object_get);
916 DEFSUBR (Fconcord_object_put);
917 DEFSUBR (Fconcord_object_spec);
918 DEFSUBR (Fconcord_foreach_object_in_feature);
922 structure_type_create_concord (void)
924 struct structure_type *st;
926 st = define_structure_type (Qconcord_object,
927 concord_object_validate,
928 concord_object_instantiate);
930 define_structure_type_keyword (st, Qgenre, concord_name_validate);
931 define_structure_type_keyword (st, Q_id, concord_name_validate);
935 vars_of_concord (void)
939 staticpro (&Vconcord_ds_hash_table);
940 Vconcord_ds_hash_table
941 = make_lisp_hash_table (8, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
943 staticpro (&Vconcord_genre_hash_table);
944 Vconcord_genre_hash_table
945 = make_lisp_hash_table (16, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);