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 (Fmember (object, ffv)))
777 nconc2 (Fcopy_sequence (ffv), list1 (object)));
787 DEFUN ("concord-object-adjoin", Fconcord_object_adjoin, 3, 3, 0, /*
788 Cons ITEM onto the front of FEATURE's value of OBJECT only if it's not already there.
790 (object, feature, item))
792 Lisp_Object ret = Fconcord_object_get (object, feature);
794 if ( NILP (Fmember (item, ret)) )
795 return Fconcord_object_put (object, feature, Fcons (item, ret));
799 DEFUN ("concord-object-adjoin*", Fconcord_object_adjoinX, 3, 3, 0, /*
800 Append ITEM onto the end of FEATURE's value of OBJECT only if it's not already there.
802 (object, feature, item))
804 Lisp_Object ret = Fconcord_object_get (object, feature);
806 if ( NILP (Fmember (item, ret)) )
807 return Fconcord_object_put (object, feature, nconc2 (ret, list1 (item)));
811 struct closure_for_object_spec
815 } *concord_object_spec_closure;
818 add_feature_to_spec_mapper (CONCORD_Genre genre, char* name)
820 /* This function can GC */
821 CONCORD_String_Tank st_value;
822 CONCORD_Feature c_feature;
825 c_feature = concord_genre_get_feature (genre, name);
826 if (c_feature == NULL)
830 concord_obj_get_feature_value_string
831 (concord_object_spec_closure->object_id, c_feature, &st_value);
834 concord_object_spec_closure->spec
835 = Fcons (Fcons (intern (name),
836 Fcar (Fread_from_string
838 ((char*)CONCORD_String_data (&st_value),
839 CONCORD_String_size (&st_value),
842 concord_object_spec_closure->spec);
847 DEFUN ("concord-object-spec", Fconcord_object_spec, 1, 1, 0, /*
848 Return the spec of OBJECT.
852 Lisp_Object obj_string;
854 CONCORD_Genre c_genre;
855 struct gcpro gcpro1, gcpro2;
856 int previous_print_readably;
858 CHECK_CONCORD_OBJECT (object);
859 previous_print_readably = print_readably;
862 obj_string = Fprin1_to_string (XCONCORD_OBJECT_ID(object), Qnil);
864 print_readably = previous_print_readably;
865 TO_EXTERNAL_FORMAT (LISP_STRING, obj_string,
866 C_STRING_ALLOCA, c_obj, Qfile_name);
867 c_genre = XCONCORD_OBJECT_GENRE(object);
868 concord_object_spec_closure
869 = alloca (sizeof (struct closure_for_object_spec));
870 concord_object_spec_closure->object_id = c_obj;
871 concord_object_spec_closure->spec = Qnil;
872 GCPRO2 (object, concord_object_spec_closure->spec);
873 concord_genre_foreach_feature_name (c_genre,
874 add_feature_to_spec_mapper);
876 return concord_object_spec_closure->spec;
879 DEFUN ("concord-define-object", Fconcord_define_object, 2, 3, 0, /*
880 Define an object of which spec is a set of features SPEC.
884 Lisp_Object id = Fcdr (Fassq (Q_id, spec));
889 Lisp_Object rest = spec;
892 obj = Fconcord_make_object (genre, id, ds);
896 Fconcord_object_put (obj, Fcar (cell), Fcdr (cell));
904 struct closure_for_each_object
906 Lisp_Object function;
910 } *for_each_object_closure;
913 func_for_each_object (CONCORD_String object_id,
914 CONCORD_Feature feature,
915 CONCORD_String value)
917 struct gcpro gcpro1, gcpro2;
918 Lisp_Object obj, val, ret;
921 obj = read_from_c_string (CONCORD_String_data (object_id),
922 CONCORD_String_size (object_id) );
924 obj = Fcar (Fread_from_string (make_ext_string
925 ((char*)CONCORD_String_data (object_id),
926 CONCORD_String_size (object_id),
931 obj = Fconcord_make_object (for_each_object_closure->genre,
933 for_each_object_closure->ds);
935 val = read_from_c_string (CONCORD_String_data (value),
936 CONCORD_String_size (value) );
938 val = Fcar (Fread_from_string (make_ext_string
939 ((char*)CONCORD_String_data (value),
940 CONCORD_String_size (value),
946 ret = call2 (for_each_object_closure->function, obj, val);
948 for_each_object_closure->ret = ret;
952 DEFUN ("concord-for-each-object-in-feature",
953 Fconcord_foreach_object_in_feature, 2, 4, 0, /*
954 Do FUNCTION over objects in FEATURE, calling it with two args,
955 each key and value in the FEATURE table.
956 Optional argument GENRE specifies the genre of the FEATURE.
957 When the FUNCTION returns non-nil, it breaks the repeat.
959 (function, feature, genre, ds))
961 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
962 Lisp_CONCORD_DS* lds;
964 CONCORD_Genre c_genre;
966 CONCORD_Feature c_feature;
969 ds = Fconcord_genre_ds (genre);
970 CHECK_CONCORD_DS (ds);
971 lds = XCONCORD_DS (ds);
974 if ( !STRINGP(feature) )
975 feature = Fsymbol_name (feature);
976 if ( !STRINGP(genre) )
977 genre = Fsymbol_name (genre);
978 TO_EXTERNAL_FORMAT (LISP_STRING, genre,
979 C_STRING_ALLOCA, genre_name,
981 c_genre = concord_ds_get_genre (lds->ds, genre_name);
985 CHECK_STRING (feature);
986 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
987 C_STRING_ALLOCA, feature_name,
989 c_feature = concord_genre_get_feature (c_genre, feature_name);
990 if (c_feature == NULL)
992 for_each_object_closure
993 = alloca (sizeof (struct closure_for_each_object));
994 for_each_object_closure->function = function;
995 for_each_object_closure->genre = genre;
996 for_each_object_closure->ds = ds;
997 for_each_object_closure->ret = Qnil;
998 GCPRO4 (for_each_object_closure->function,
999 for_each_object_closure->genre,
1000 for_each_object_closure->ds,
1001 for_each_object_closure->ret);
1002 concord_feature_foreach_obj_string (c_feature, func_for_each_object);
1005 return for_each_object_closure->ret;
1010 concord_name_validate (Lisp_Object keyword, Lisp_Object value,
1011 Error_behavior errb)
1013 if (ERRB_EQ (errb, ERROR_ME))
1015 CHECK_SYMBOL (value);
1019 return SYMBOLP (value);
1023 concord_id_validate (Lisp_Object keyword, Lisp_Object value,
1024 Error_behavior errb)
1026 if (ERRB_EQ (errb, ERROR_ME))
1028 /* CHECK_SYMBOL (value); */
1029 if ( INTP (value) || CHARP (value) || SYMBOLP (value) )
1032 dead_wrong_type_argument (Qsymbolp, value);
1036 return INTP (value) || CHARP (value) || SYMBOLP (value);
1040 concord_object_validate (Lisp_Object data, Error_behavior errb)
1042 struct gcpro gcpro1, gcpro2, gcpro3;
1044 Lisp_Object valw = Qnil;
1045 Lisp_Object genre = Qnil;
1046 Lisp_Object oid = Qnil;
1048 data = Fcdr (data); /* skip over Qconcord_object */
1049 while (!NILP (data))
1051 Lisp_Object keyw = Fcar (data);
1056 if (EQ (keyw, Qgenre))
1058 else if (EQ (keyw, Q_id))
1066 maybe_error (Qconcord_object, errb, "No genre given");
1071 maybe_error (Qconcord_object, errb, "No object-id given");
1075 GCPRO3 (genre, oid, retval);
1076 retval = Fconcord_make_object (genre, oid, Qnil);
1080 maybe_signal_simple_error_2 ("No such Concord-object",
1081 oid, genre, Qconcord_object, errb);
1089 concord_object_instantiate (Lisp_Object data)
1091 struct gcpro gcpro1, gcpro2;
1094 GCPRO2 (data, retval);
1095 retval = Fconcord_make_object (Fplist_get (data, Qgenre, Qnil),
1096 Fplist_get (data, Q_id, Qnil),
1104 syms_of_concord (void)
1106 INIT_LRECORD_IMPLEMENTATION (concord_ds);
1107 INIT_LRECORD_IMPLEMENTATION (concord_object);
1109 defsymbol (&Qconcord, "concord");
1110 defsymbol (&Qconcord_dsp, "concord-dsp");
1111 defsymbol (&Qconcord_objectp, "concord-objectp");
1112 defsymbol (&Qconcord_object, "concord-object");
1113 defsymbol (&Qgenre, "genre");
1114 defsymbol (&Q_id, "=id");
1115 #ifdef HAVE_LIBCHISE
1116 defsymbol (&Qcharacter, "character");
1117 defsymbol (&Qfeature, "feature");
1120 DEFSUBR (Fconcord_open_ds);
1121 DEFSUBR (Fconcord_ds_p);
1122 DEFSUBR (Fconcord_close_ds);
1123 DEFSUBR (Fconcord_ds_directory);
1125 DEFSUBR (Fconcord_assign_genre);
1126 DEFSUBR (Fconcord_genre_directory);
1127 DEFSUBR (Fconcord_genre_ds);
1128 DEFSUBR (Fconcord_feature_list);
1130 DEFSUBR (Fconcord_make_object);
1131 DEFSUBR (Fconcord_object_p);
1132 DEFSUBR (Fconcord_object_id);
1133 DEFSUBR (Fconcord_object_genre);
1134 DEFSUBR (Fconcord_decode_object);
1135 DEFSUBR (Fconcord_object_get);
1136 DEFSUBR (Fconcord_object_put);
1137 DEFSUBR (Fconcord_object_adjoin);
1138 DEFSUBR (Fconcord_object_adjoinX);
1139 DEFSUBR (Fconcord_define_object);
1140 DEFSUBR (Fconcord_object_spec);
1141 DEFSUBR (Fconcord_foreach_object_in_feature);
1145 structure_type_create_concord (void)
1147 struct structure_type *st;
1149 st = define_structure_type (Qconcord_object,
1150 concord_object_validate,
1151 concord_object_instantiate);
1153 define_structure_type_keyword (st, Qgenre, concord_name_validate);
1154 define_structure_type_keyword (st, Q_id, concord_id_validate);
1158 vars_of_concord (void)
1160 Fprovide (Qconcord);
1162 staticpro (&Vconcord_ds_hash_table);
1163 Vconcord_ds_hash_table
1164 = make_lisp_hash_table (8, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
1166 staticpro (&Vconcord_genre_hash_table);
1167 Vconcord_genre_hash_table
1168 = make_lisp_hash_table (16, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
1170 staticpro (&Vconcord_genre_object_hash_table);
1171 Vconcord_genre_object_hash_table
1172 = make_lisp_hash_table (16, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
1176 complex_vars_of_concord (void)
1178 #ifdef HAVE_LIBCHISE
1179 Fconcord_assign_genre (Qcharacter, Vchise_system_db_directory);
1180 Fconcord_assign_genre (Qfeature, Vchise_system_db_directory);