1 /* XEmacs routines to deal with CONCORD.
2 Copyright (C) 2005,2006,2008,2010 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 */
30 #include "elconcord.h"
36 EXFUN (Fread_from_string, 3);
40 Lisp_Object Qconcord_object;
41 Lisp_Object Qgenre, Q_id;
43 Lisp_Object Qcharacter;
47 Lisp_Object Vconcord_ds_hash_table;
48 Lisp_Object Vconcord_genre_hash_table;
49 Lisp_Object Vconcord_genre_object_hash_table;
56 Lisp_Object Qconcord_dsp;
58 static Lisp_CONCORD_DS*
59 allocate_concord_ds (void)
62 = alloc_lcrecord_type (Lisp_CONCORD_DS, &lrecord_concord_ds);
69 mark_concord_ds (Lisp_Object object)
75 print_concord_ds (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
77 Lisp_CONCORD_DS* lds = XCONCORD_DS (obj);
80 error ("printing unreadable object #<concord_ds 0x%x>", lds->header.uid);
82 write_c_string ("#<concord_ds \"", printcharfun);
83 write_c_string (concord_ds_location (lds->ds), printcharfun);
84 write_c_string ("\">", printcharfun);
88 finalize_concord_ds (void *header, int for_disksave)
90 Lisp_CONCORD_DS *lds = (Lisp_CONCORD_DS *) header;
95 XSET_CONCORD_DS (object, lds);
98 ("Can't dump an emacs containing concord_ds objects", object);
100 if ( lds->ds != NULL)
101 concord_close_ds (lds->ds);
104 DEFINE_LRECORD_IMPLEMENTATION ("concord_ds", concord_ds,
105 mark_concord_ds, print_concord_ds,
106 finalize_concord_ds, 0, 0, 0,
109 DEFUN ("concord-close-ds", Fconcord_close_ds, 1, 1, 0, /*
110 Close concord-ds CONCORD-DS.
114 Lisp_CONCORD_DS* lds;
115 lds = XCONCORD_DS (concord_ds);
116 if ( lds->ds != NULL)
117 concord_close_ds (lds->ds);
122 DEFUN ("concord-ds-p", Fconcord_ds_p, 1, 1, 0, /*
123 Return t if OBJECT is a concord-ds.
127 return CONCORD_DS_P (object) ? Qt : Qnil;
130 DEFUN ("concord-open-ds", Fconcord_open_ds, 1, 4, 0, /*
131 Return a new concord-ds object opened on DIRECTORY.
132 Optional arguments TYPE and SUBTYPE specify the concord_ds type.
133 Optional argument MODE gives the permissions to use when opening DIRECTORY,
134 and defaults to 0755.
136 (directory, type, subtype, mode))
139 Lisp_CONCORD_DS* lds = NULL;
145 CHECK_STRING (directory);
147 directory = Ffile_name_as_directory (Fexpand_file_name (directory, Qnil));
150 retval = Fgethash (directory, Vconcord_ds_hash_table, Qunbound);
151 if (!UNBOUNDP (retval))
156 TO_EXTERNAL_FORMAT (LISP_STRING, directory,
157 C_STRING_ALLOCA, pathname,
162 modemask = 0755; /* rwxr-xr-x */
167 modemask = XINT (mode);
170 ds = concord_open_ds (CONCORD_Backend_Berkeley_DB,
171 pathname, 0, modemask);
175 lds = allocate_concord_ds ();
177 XSET_CONCORD_DS (retval, lds);
178 Fputhash (directory, retval, Vconcord_ds_hash_table);
182 DEFUN ("concord-ds-directory", Fconcord_ds_directory, 1, 1, 0, /*
183 Return directory of concord-ds DS.
187 Lisp_CONCORD_DS* lds;
190 CHECK_CONCORD_DS (ds);
191 lds = XCONCORD_DS (ds);
195 directory = concord_ds_location (lds->ds);
196 if (directory == NULL)
199 return build_ext_string (directory, Qfile_name);
203 DEFUN ("concord-assign-genre", Fconcord_assign_genre, 2, 2, 0, /*
204 Assign data-source DIRECTORY to GENRE.
210 CHECK_SYMBOL (genre);
211 if ( CONCORD_DS_P (directory) )
216 CHECK_STRING (directory);
219 = Ffile_name_as_directory (Fexpand_file_name (directory, Qnil));
222 Fputhash (genre, directory, Vconcord_genre_hash_table);
226 DEFUN ("concord-genre-directory", Fconcord_genre_directory, 1, 1, 0, /*
227 Return pathname of GENRE.
232 CHECK_SYMBOL (genre);
234 retval = Fgethash (genre, Vconcord_genre_hash_table, Qunbound);
235 if ( STRINGP (retval) )
237 else if ( CONCORD_DS_P (retval) )
238 return Fconcord_ds_directory (retval);
242 DEFUN ("concord-genre-ds", Fconcord_genre_ds, 1, 1, 0, /*
243 Return concord-ds of GENRE.
249 CHECK_SYMBOL (genre);
251 retval = Fgethash (genre, Vconcord_genre_hash_table, Qunbound);
252 if ( UNBOUNDP (retval) )
253 retval = Vchise_system_db_directory;
254 if ( STRINGP (retval) )
256 retval = Fconcord_open_ds (retval, Qnil, Qnil, Qnil);
257 if ( !NILP (retval) )
258 Fputhash (genre, retval, Vconcord_genre_hash_table);
261 else if ( CONCORD_DS_P (retval) )
267 struct closure_to_list_feature
269 Lisp_Object feature_list;
270 } *concord_feature_list_closure;
273 add_feature_to_list_mapper (CONCORD_Genre genre, char* name)
275 /* This function can GC */
276 concord_feature_list_closure->feature_list
277 = Fcons (intern (name), concord_feature_list_closure->feature_list);
281 DEFUN ("concord-feature-list", Fconcord_feature_list, 1, 2, 0, /*
282 Return the list of all existing features in GENRE.
286 Lisp_CONCORD_DS* lds;
288 CONCORD_Genre c_genre;
291 CHECK_SYMBOL (genre);
293 ds = Fconcord_genre_ds (genre);
294 CHECK_CONCORD_DS (ds);
295 lds = XCONCORD_DS (ds);
298 genre = Fsymbol_name (genre);
299 TO_EXTERNAL_FORMAT (LISP_STRING, genre,
300 C_STRING_ALLOCA, genre_name,
302 c_genre = concord_ds_get_genre (lds->ds, genre_name);
305 concord_feature_list_closure
306 = alloca (sizeof (struct closure_to_list_feature));
307 concord_feature_list_closure->feature_list = Qnil;
308 GCPRO1 (concord_feature_list_closure->feature_list);
309 concord_genre_foreach_feature_name (c_genre,
310 add_feature_to_list_mapper);
312 return concord_feature_list_closure->feature_list;
320 Lisp_Object Qconcord_objectp;
322 static Lisp_CONCORD_Object*
323 allocate_concord_object (void)
325 Lisp_CONCORD_Object* lcobj
326 = alloc_lcrecord_type (Lisp_CONCORD_Object, &lrecord_concord_object);
329 lcobj->id = Qunbound;
334 mark_concord_object (Lisp_Object object)
336 mark_object (XCONCORD_OBJECT_ID(object));
341 print_concord_object (Lisp_Object obj,
342 Lisp_Object printcharfun, int escapeflag)
344 Lisp_CONCORD_Object* lcobj = XCONCORD_OBJECT (obj);
345 struct gcpro gcpro1, gcpro2;
348 if ( print_readably )
351 write_c_string ("#s(concord-object", printcharfun);
352 write_c_string (" genre ", printcharfun);
353 write_c_string (concord_genre_get_name (lcobj->genre), printcharfun);
354 write_c_string (" =id ", printcharfun);
355 GCPRO2 (obj, printcharfun);
356 print_internal (lcobj->id, printcharfun, escapeflag);
358 write_c_string (")", printcharfun);
363 write_c_string ("#<concord-object \"", printcharfun);
364 write_c_string (concord_genre_get_name (lcobj->genre), printcharfun);
365 write_c_string (";", printcharfun);
366 GCPRO2 (obj, printcharfun);
367 print_internal (lcobj->id, printcharfun, escapeflag);
369 write_c_string ("\">", printcharfun);
375 finalize_concord_object (void *header, int for_disksave)
377 Lisp_CONCORD_Object* lcobj = (Lisp_CONCORD_Object *) header;
382 XSET_CONCORD_OBJECT (object, lcobj);
385 ("Can't dump an emacs containing concord_object objects", object);
390 concord_object_equal (Lisp_Object cobj1, Lisp_Object cobj2, int depth)
392 return internal_equal ( XCONCORD_OBJECT_ID(cobj1),
393 XCONCORD_OBJECT_ID(cobj2), depth);
396 static const struct lrecord_description concord_object_description[] = {
397 { XD_LISP_OBJECT, offsetof (Lisp_CONCORD_Object, id) },
401 DEFINE_LRECORD_IMPLEMENTATION ("concord_object", concord_object,
402 mark_concord_object, print_concord_object,
403 finalize_concord_object,
404 concord_object_equal, 0,
405 concord_object_description,
406 Lisp_CONCORD_Object);
409 concord_genre_cache_get_object (Lisp_Object genre, Lisp_Object id)
411 Lisp_Object obj_hash;
413 obj_hash = Fgethash (genre, Vconcord_genre_object_hash_table, Qunbound);
414 if (UNBOUNDP (obj_hash))
416 return Fgethash (id, obj_hash, Qunbound);
420 concord_genre_cache_put_object (Lisp_Object genre, Lisp_Object id,
423 Lisp_Object obj_hash;
425 obj_hash = Fgethash (genre, Vconcord_genre_object_hash_table, Qunbound);
426 if (UNBOUNDP (obj_hash))
429 = make_lisp_hash_table (256, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
430 Fputhash (genre, obj_hash, Vconcord_genre_object_hash_table);
432 return Fputhash (id, object, obj_hash);
435 DEFUN ("concord-make-object", Fconcord_make_object, 1, 3, 0, /*
436 Make and return a Concord-object from ID and GENRE.
437 Optional argument DS specifies the data-source of the GENRE.
441 Lisp_CONCORD_DS* lds;
442 Lisp_Object genre_string;
443 char* genre_name_str;
444 CONCORD_Genre c_genre;
445 Lisp_CONCORD_Object* lcobj;
450 retval = concord_genre_cache_get_object (genre, id);
451 if (!UNBOUNDP (retval))
457 ds = Fconcord_genre_ds (genre);
458 CHECK_CONCORD_DS (ds);
459 lds = XCONCORD_DS (ds);
462 if ( STRINGP(genre) )
463 genre_string = genre;
465 genre_string = Fsymbol_name (genre);
466 TO_EXTERNAL_FORMAT (LISP_STRING, genre_string,
467 C_STRING_ALLOCA, genre_name_str,
469 c_genre = concord_ds_get_genre (lds->ds, genre_name_str);
472 lcobj = allocate_concord_object ();
473 lcobj->genre = c_genre;
475 XSET_CONCORD_OBJECT (retval, lcobj);
478 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
480 GCPRO4 (retval, id, genre, ds);
481 concord_genre_cache_put_object (genre, id, retval);
483 if (!EQ (Fconcord_object_get (retval, Q_id), id))
484 Fconcord_object_put (retval, Q_id, id);
491 DEFUN ("concord-object-p", Fconcord_object_p, 1, 1, 0, /*
492 Return t if OBJECT is a concord-object.
496 return CONCORD_OBJECT_P (object) ? Qt : Qnil;
499 DEFUN ("concord-object-id", Fconcord_object_id, 1, 1, 0, /*
500 Return an id of Concord-object OBJECT.
504 CHECK_CONCORD_OBJECT (object);
505 return XCONCORD_OBJECT_ID (object);
508 DEFUN ("concord-object-genre", Fconcord_object_genre, 1, 1, 0, /*
509 Return genre of Concord-object OBJECT.
513 CHECK_CONCORD_OBJECT (object);
514 return intern (concord_genre_get_name (XCONCORD_OBJECT_GENRE (object)));
517 DEFUN ("concord-decode-object", Fconcord_decode_object, 2, 4, 0, /*
518 Make and return a Concord-object from FEATURE and VALUE.
519 Optional argument GENRE specifies the GENRE of the object.
520 Optional argument DS specifies the data-source of the GENRE.
522 (feature, value, genre, ds))
524 Lisp_CONCORD_DS* lds;
526 CONCORD_Genre c_genre;
528 CONCORD_INDEX c_index;
529 Lisp_Object value_string;
531 CONCORD_String_Tank st_id;
534 int previous_print_readably;
535 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
538 ds = Fconcord_genre_ds (genre);
539 CHECK_CONCORD_DS (ds);
540 lds = XCONCORD_DS (ds);
543 if ( !STRINGP(feature) )
544 feature = Fsymbol_name (feature);
545 if ( !STRINGP(genre) )
546 genre = Fsymbol_name (genre);
547 TO_EXTERNAL_FORMAT (LISP_STRING, genre,
548 C_STRING_ALLOCA, genre_name,
550 c_genre = concord_ds_get_genre (lds->ds, genre_name);
556 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
557 C_STRING_ALLOCA, feature_name,
559 c_index = concord_genre_get_index (c_genre, feature_name);
565 previous_print_readably = print_readably;
567 GCPRO5 (feature, value, genre, ds, value_string);
568 value_string = Fprin1_to_string (value, Qnil);
570 print_readably = previous_print_readably;
571 TO_EXTERNAL_FORMAT (LISP_STRING,
572 value_string, C_STRING_ALLOCA, strid,
574 status = concord_index_strid_get_obj_string (c_index, strid, &st_id);
579 GCPRO4 (genre, ds, obj, retval);
581 obj = read_from_c_string (CONCORD_String_data (&st_id),
582 CONCORD_String_size (&st_id) );
584 obj = Fcar (Fread_from_string (make_ext_string
585 ((char*)CONCORD_String_data (&st_id),
586 CONCORD_String_size (&st_id),
590 retval = Fconcord_make_object (genre, obj, ds);
597 DEFUN ("concord-object-get", Fconcord_object_get, 2, 2, 0, /*
598 Return the value of OBJECT's FEATURE.
602 struct gcpro gcpro1, gcpro2;
603 int previous_print_readably;
604 Lisp_Object obj_string;
606 CONCORD_Genre c_genre;
608 CONCORD_Feature c_feature;
610 CONCORD_String_Tank st_value;
612 CHECK_CONCORD_OBJECT (object);
613 if ( !STRINGP(feature) )
614 feature = Fsymbol_name (feature);
615 previous_print_readably = print_readably;
617 GCPRO2 (object, feature);
618 obj_string = Fprin1_to_string (XCONCORD_OBJECT_ID(object), Qnil);
620 print_readably = previous_print_readably;
621 TO_EXTERNAL_FORMAT (LISP_STRING, obj_string,
622 C_STRING_ALLOCA, c_obj, Qfile_name);
623 c_genre = XCONCORD_OBJECT_GENRE(object);
624 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
625 C_STRING_ALLOCA, feature_name,
627 c_feature = concord_genre_get_feature (c_genre, feature_name);
628 if (c_feature == NULL)
632 status = concord_obj_get_feature_value_string (c_obj, c_feature,
637 Fcar (Fread_from_string (make_ext_string
638 ((char*)CONCORD_String_data (&st_value),
639 CONCORD_String_size (&st_value),
647 concord_object_put (Lisp_Object object, Lisp_Object feature,
650 struct gcpro gcpro1, gcpro2, gcpro3;
651 int previous_print_readably;
652 Lisp_Object obj_string;
654 CONCORD_Genre c_genre;
656 CONCORD_Feature c_feature;
658 Lisp_Object value_string;
661 if ( !STRINGP(feature) )
662 feature = Fsymbol_name (feature);
663 previous_print_readably = print_readably;
665 GCPRO3 (object, feature, value);
666 obj_string = Fprin1_to_string (XCONCORD_OBJECT_ID(object), Qnil);
668 print_readably = previous_print_readably;
669 TO_EXTERNAL_FORMAT (LISP_STRING, obj_string,
670 C_STRING_ALLOCA, c_obj, Qfile_name);
671 c_genre = XCONCORD_OBJECT_GENRE(object);
672 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
673 C_STRING_ALLOCA, feature_name,
675 c_feature = concord_genre_get_feature (c_genre, feature_name);
676 if (c_feature == NULL)
680 previous_print_readably = print_readably;
682 GCPRO3 (object, feature, value);
683 value_string = Fprin1_to_string (value, Qnil);
685 print_readably = previous_print_readably;
686 TO_EXTERNAL_FORMAT (LISP_STRING, value_string,
687 C_STRING_ALLOCA, c_value,
689 status = concord_obj_put_feature_value_str (c_obj, c_feature,
690 (unsigned char*)c_value);
693 status = chise_feature_sync (c_feature);
696 if (XSTRING_DATA(feature)[0] == '=')
698 CONCORD_INDEX c_index
699 = concord_genre_get_index (c_genre, feature_name);
701 concord_index_strid_put_obj (c_index, c_value, c_obj);
702 concord_index_sync (c_index);
707 DEFUN ("concord-object-put", Fconcord_object_put, 3, 3, 0, /*
708 Store a VALUE of OBJECT's FEATURE.
710 (object, feature, value))
715 CHECK_CONCORD_OBJECT (object);
716 CHECK_SYMBOL (feature);
717 name = symbol_name (XSYMBOL (feature));
718 name_str = string_data (name);
719 if ( NILP (concord_object_put (object, feature, value)) )
721 if ( EQ (feature, Q_subsumptive) ||
722 EQ (feature, Q_subsumptive_from) ||
723 EQ (feature, Q_denotational) ||
724 EQ (feature, Q_denotational_from) ||
725 ( ( ((name_str[0] == '-') && (name_str[1] == '>')) ||
726 ((name_str[0] == '<') && (name_str[1] == '-')) )
727 && (memchr (name_str, '*', name->size) == NULL) ) )
729 Lisp_Object rest = value;
731 Lisp_Object rev_feature = Qnil;
734 GCPRO1 (rev_feature);
735 if (EQ (feature, Q_subsumptive))
736 rev_feature = Q_subsumptive_from;
737 else if (EQ (feature, Q_subsumptive_from))
738 rev_feature = Q_subsumptive;
739 else if (EQ (feature, Q_denotational))
740 rev_feature = Q_denotational_from;
741 else if (EQ (feature, Q_denotational_from))
742 rev_feature = Q_denotational;
745 Bytecount length = string_length (name);
746 Bufbyte *rev_name_str = alloca (length + 1);
748 memcpy (rev_name_str + 2, name_str + 2, length - 2);
749 if (name_str[0] == '<')
751 rev_name_str[0] = '-';
752 rev_name_str[1] = '>';
756 rev_name_str[0] = '<';
757 rev_name_str[1] = '-';
759 rev_name_str[length] = 0;
760 rev_feature = intern (rev_name_str);
767 if ( CONCORD_OBJECT_P (ret) && !EQ (ret, object) )
771 ffv = Fconcord_object_get (ret, rev_feature);
773 concord_object_put (ret, rev_feature, list1 (object));
774 else if (NILP (Fmemq (object, ffv)))
777 nconc2 (Fcopy_sequence (ffv), list1 (object)));
787 struct closure_for_object_spec
791 } *concord_object_spec_closure;
794 add_feature_to_spec_mapper (CONCORD_Genre genre, char* name)
796 /* This function can GC */
797 CONCORD_String_Tank st_value;
798 CONCORD_Feature c_feature;
801 c_feature = concord_genre_get_feature (genre, name);
802 if (c_feature == NULL)
806 concord_obj_get_feature_value_string
807 (concord_object_spec_closure->object_id, c_feature, &st_value);
810 concord_object_spec_closure->spec
811 = Fcons (Fcons (intern (name),
812 Fcar (Fread_from_string
814 ((char*)CONCORD_String_data (&st_value),
815 CONCORD_String_size (&st_value),
818 concord_object_spec_closure->spec);
823 DEFUN ("concord-object-spec", Fconcord_object_spec, 1, 1, 0, /*
824 Return the spec of OBJECT.
828 Lisp_Object obj_string;
830 CONCORD_Genre c_genre;
831 struct gcpro gcpro1, gcpro2;
832 int previous_print_readably;
834 CHECK_CONCORD_OBJECT (object);
835 previous_print_readably = print_readably;
838 obj_string = Fprin1_to_string (XCONCORD_OBJECT_ID(object), Qnil);
840 print_readably = previous_print_readably;
841 TO_EXTERNAL_FORMAT (LISP_STRING, obj_string,
842 C_STRING_ALLOCA, c_obj, Qfile_name);
843 c_genre = XCONCORD_OBJECT_GENRE(object);
844 concord_object_spec_closure
845 = alloca (sizeof (struct closure_for_object_spec));
846 concord_object_spec_closure->object_id = c_obj;
847 concord_object_spec_closure->spec = Qnil;
848 GCPRO2 (object, concord_object_spec_closure->spec);
849 concord_genre_foreach_feature_name (c_genre,
850 add_feature_to_spec_mapper);
852 return concord_object_spec_closure->spec;
855 DEFUN ("concord-define-object", Fconcord_define_object, 2, 3, 0, /*
856 Define an object of which spec is a set of features SPEC.
860 Lisp_Object id = Fcdr (Fassq (Q_id, spec));
865 Lisp_Object rest = spec;
868 obj = Fconcord_make_object (genre, id, ds);
872 Fconcord_object_put (obj, Fcar (cell), Fcdr (cell));
880 struct closure_for_each_object
882 Lisp_Object function;
886 } *for_each_object_closure;
889 func_for_each_object (CONCORD_String object_id,
890 CONCORD_Feature feature,
891 CONCORD_String value)
893 struct gcpro gcpro1, gcpro2;
894 Lisp_Object obj, val, ret;
897 obj = read_from_c_string (CONCORD_String_data (object_id),
898 CONCORD_String_size (object_id) );
900 obj = Fcar (Fread_from_string (make_ext_string
901 ((char*)CONCORD_String_data (object_id),
902 CONCORD_String_size (object_id),
907 obj = Fconcord_make_object (for_each_object_closure->genre,
909 for_each_object_closure->ds);
911 val = read_from_c_string (CONCORD_String_data (value),
912 CONCORD_String_size (value) );
914 val = Fcar (Fread_from_string (make_ext_string
915 ((char*)CONCORD_String_data (value),
916 CONCORD_String_size (value),
922 ret = call2 (for_each_object_closure->function, obj, val);
924 for_each_object_closure->ret = ret;
928 DEFUN ("concord-for-each-object-in-feature",
929 Fconcord_foreach_object_in_feature, 2, 4, 0, /*
930 Do FUNCTION over objects in FEATURE, calling it with two args,
931 each key and value in the FEATURE table.
932 Optional argument GENRE specifies the genre of the FEATURE.
933 When the FUNCTION returns non-nil, it breaks the repeat.
935 (function, feature, genre, ds))
937 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
938 Lisp_CONCORD_DS* lds;
940 CONCORD_Genre c_genre;
942 CONCORD_Feature c_feature;
945 ds = Fconcord_genre_ds (genre);
946 CHECK_CONCORD_DS (ds);
947 lds = XCONCORD_DS (ds);
950 if ( !STRINGP(feature) )
951 feature = Fsymbol_name (feature);
952 if ( !STRINGP(genre) )
953 genre = Fsymbol_name (genre);
954 TO_EXTERNAL_FORMAT (LISP_STRING, genre,
955 C_STRING_ALLOCA, genre_name,
957 c_genre = concord_ds_get_genre (lds->ds, genre_name);
961 CHECK_STRING (feature);
962 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
963 C_STRING_ALLOCA, feature_name,
965 c_feature = concord_genre_get_feature (c_genre, feature_name);
966 if (c_feature == NULL)
968 for_each_object_closure
969 = alloca (sizeof (struct closure_for_each_object));
970 for_each_object_closure->function = function;
971 for_each_object_closure->genre = genre;
972 for_each_object_closure->ds = ds;
973 for_each_object_closure->ret = Qnil;
974 GCPRO4 (for_each_object_closure->function,
975 for_each_object_closure->genre,
976 for_each_object_closure->ds,
977 for_each_object_closure->ret);
978 concord_feature_foreach_obj_string (c_feature, func_for_each_object);
981 return for_each_object_closure->ret;
986 concord_name_validate (Lisp_Object keyword, Lisp_Object value,
989 if (ERRB_EQ (errb, ERROR_ME))
991 CHECK_SYMBOL (value);
995 return SYMBOLP (value);
999 concord_id_validate (Lisp_Object keyword, Lisp_Object value,
1000 Error_behavior errb)
1002 if (ERRB_EQ (errb, ERROR_ME))
1004 /* CHECK_SYMBOL (value); */
1005 if ( INTP (value) || CHARP (value) || SYMBOLP (value) )
1008 dead_wrong_type_argument (Qsymbolp, value);
1012 return INTP (value) || CHARP (value) || SYMBOLP (value);
1016 concord_object_validate (Lisp_Object data, Error_behavior errb)
1018 struct gcpro gcpro1, gcpro2, gcpro3;
1020 Lisp_Object valw = Qnil;
1021 Lisp_Object genre = Qnil;
1022 Lisp_Object oid = Qnil;
1024 data = Fcdr (data); /* skip over Qconcord_object */
1025 while (!NILP (data))
1027 Lisp_Object keyw = Fcar (data);
1032 if (EQ (keyw, Qgenre))
1034 else if (EQ (keyw, Q_id))
1042 maybe_error (Qconcord_object, errb, "No genre given");
1047 maybe_error (Qconcord_object, errb, "No object-id given");
1051 GCPRO3 (genre, oid, retval);
1052 retval = Fconcord_make_object (genre, oid, Qnil);
1056 maybe_signal_simple_error_2 ("No such Concord-object",
1057 oid, genre, Qconcord_object, errb);
1065 concord_object_instantiate (Lisp_Object data)
1067 struct gcpro gcpro1, gcpro2;
1070 GCPRO2 (data, retval);
1071 retval = Fconcord_make_object (Fplist_get (data, Qgenre, Qnil),
1072 Fplist_get (data, Q_id, Qnil),
1080 syms_of_concord (void)
1082 INIT_LRECORD_IMPLEMENTATION (concord_ds);
1083 INIT_LRECORD_IMPLEMENTATION (concord_object);
1085 defsymbol (&Qconcord, "concord");
1086 defsymbol (&Qconcord_dsp, "concord-dsp");
1087 defsymbol (&Qconcord_objectp, "concord-objectp");
1088 defsymbol (&Qconcord_object, "concord-object");
1089 defsymbol (&Qgenre, "genre");
1090 defsymbol (&Q_id, "=id");
1091 #ifdef HAVE_LIBCHISE
1092 defsymbol (&Qcharacter, "character");
1093 defsymbol (&Qfeature, "feature");
1096 DEFSUBR (Fconcord_open_ds);
1097 DEFSUBR (Fconcord_ds_p);
1098 DEFSUBR (Fconcord_close_ds);
1099 DEFSUBR (Fconcord_ds_directory);
1101 DEFSUBR (Fconcord_assign_genre);
1102 DEFSUBR (Fconcord_genre_directory);
1103 DEFSUBR (Fconcord_genre_ds);
1104 DEFSUBR (Fconcord_feature_list);
1106 DEFSUBR (Fconcord_make_object);
1107 DEFSUBR (Fconcord_object_p);
1108 DEFSUBR (Fconcord_object_id);
1109 DEFSUBR (Fconcord_object_genre);
1110 DEFSUBR (Fconcord_decode_object);
1111 DEFSUBR (Fconcord_object_get);
1112 DEFSUBR (Fconcord_object_put);
1113 DEFSUBR (Fconcord_define_object);
1114 DEFSUBR (Fconcord_object_spec);
1115 DEFSUBR (Fconcord_foreach_object_in_feature);
1119 structure_type_create_concord (void)
1121 struct structure_type *st;
1123 st = define_structure_type (Qconcord_object,
1124 concord_object_validate,
1125 concord_object_instantiate);
1127 define_structure_type_keyword (st, Qgenre, concord_name_validate);
1128 define_structure_type_keyword (st, Q_id, concord_id_validate);
1132 vars_of_concord (void)
1134 Fprovide (Qconcord);
1136 staticpro (&Vconcord_ds_hash_table);
1137 Vconcord_ds_hash_table
1138 = make_lisp_hash_table (8, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
1140 staticpro (&Vconcord_genre_hash_table);
1141 Vconcord_genre_hash_table
1142 = make_lisp_hash_table (16, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
1144 staticpro (&Vconcord_genre_object_hash_table);
1145 Vconcord_genre_object_hash_table
1146 = make_lisp_hash_table (16, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
1150 complex_vars_of_concord (void)
1152 #ifdef HAVE_LIBCHISE
1153 Fconcord_assign_genre (Qcharacter, Vchise_system_db_directory);
1154 Fconcord_assign_genre (Qfeature, Vchise_system_db_directory);