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);
253 if ( UNBOUNDP (retval) )
254 retval = Vchise_system_db_directory;
256 if ( STRINGP (retval) )
258 retval = Fconcord_open_ds (retval, Qnil, Qnil, Qnil);
259 if ( !NILP (retval) )
260 Fputhash (genre, retval, Vconcord_genre_hash_table);
263 else if ( CONCORD_DS_P (retval) )
269 struct closure_to_list_feature
271 Lisp_Object feature_list;
272 } *concord_feature_list_closure;
275 add_feature_to_list_mapper (CONCORD_Genre genre, char* name)
277 /* This function can GC */
278 concord_feature_list_closure->feature_list
279 = Fcons (intern (name), concord_feature_list_closure->feature_list);
283 DEFUN ("concord-feature-list", Fconcord_feature_list, 1, 2, 0, /*
284 Return the list of all existing features in GENRE.
288 Lisp_CONCORD_DS* lds;
290 CONCORD_Genre c_genre;
293 CHECK_SYMBOL (genre);
295 ds = Fconcord_genre_ds (genre);
296 CHECK_CONCORD_DS (ds);
297 lds = XCONCORD_DS (ds);
300 genre = Fsymbol_name (genre);
301 TO_EXTERNAL_FORMAT (LISP_STRING, genre,
302 C_STRING_ALLOCA, genre_name,
304 c_genre = concord_ds_get_genre (lds->ds, genre_name);
307 concord_feature_list_closure
308 = alloca (sizeof (struct closure_to_list_feature));
309 concord_feature_list_closure->feature_list = Qnil;
310 GCPRO1 (concord_feature_list_closure->feature_list);
311 concord_genre_foreach_feature_name (c_genre,
312 add_feature_to_list_mapper);
314 return concord_feature_list_closure->feature_list;
322 Lisp_Object Qconcord_objectp;
324 static Lisp_CONCORD_Object*
325 allocate_concord_object (void)
327 Lisp_CONCORD_Object* lcobj
328 = alloc_lcrecord_type (Lisp_CONCORD_Object, &lrecord_concord_object);
331 lcobj->id = Qunbound;
336 mark_concord_object (Lisp_Object object)
338 mark_object (XCONCORD_OBJECT_ID(object));
343 print_concord_object (Lisp_Object obj,
344 Lisp_Object printcharfun, int escapeflag)
346 Lisp_CONCORD_Object* lcobj = XCONCORD_OBJECT (obj);
347 struct gcpro gcpro1, gcpro2;
350 if ( print_readably )
353 write_c_string ("#s(concord-object", printcharfun);
354 write_c_string (" genre ", printcharfun);
355 write_c_string (concord_genre_get_name (lcobj->genre), printcharfun);
356 write_c_string (" =id ", printcharfun);
357 GCPRO2 (obj, printcharfun);
358 print_internal (lcobj->id, printcharfun, escapeflag);
360 write_c_string (")", printcharfun);
365 write_c_string ("#<concord-object \"", printcharfun);
366 write_c_string (concord_genre_get_name (lcobj->genre), printcharfun);
367 write_c_string (";", printcharfun);
368 GCPRO2 (obj, printcharfun);
369 print_internal (lcobj->id, printcharfun, escapeflag);
371 write_c_string ("\">", printcharfun);
377 finalize_concord_object (void *header, int for_disksave)
379 Lisp_CONCORD_Object* lcobj = (Lisp_CONCORD_Object *) header;
384 XSET_CONCORD_OBJECT (object, lcobj);
387 ("Can't dump an emacs containing concord_object objects", object);
392 concord_object_equal (Lisp_Object cobj1, Lisp_Object cobj2, int depth)
394 return internal_equal ( XCONCORD_OBJECT_ID(cobj1),
395 XCONCORD_OBJECT_ID(cobj2), depth);
398 static const struct lrecord_description concord_object_description[] = {
399 { XD_LISP_OBJECT, offsetof (Lisp_CONCORD_Object, id) },
403 DEFINE_LRECORD_IMPLEMENTATION ("concord_object", concord_object,
404 mark_concord_object, print_concord_object,
405 finalize_concord_object,
406 concord_object_equal, 0,
407 concord_object_description,
408 Lisp_CONCORD_Object);
411 concord_genre_cache_get_object (Lisp_Object genre, Lisp_Object id)
413 Lisp_Object obj_hash;
415 obj_hash = Fgethash (genre, Vconcord_genre_object_hash_table, Qunbound);
416 if (UNBOUNDP (obj_hash))
418 return Fgethash (id, obj_hash, Qunbound);
422 concord_genre_cache_put_object (Lisp_Object genre, Lisp_Object id,
425 Lisp_Object obj_hash;
427 obj_hash = Fgethash (genre, Vconcord_genre_object_hash_table, Qunbound);
428 if (UNBOUNDP (obj_hash))
431 = make_lisp_hash_table (256, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
432 Fputhash (genre, obj_hash, Vconcord_genre_object_hash_table);
434 return Fputhash (id, object, obj_hash);
437 DEFUN ("concord-make-object", Fconcord_make_object, 1, 3, 0, /*
438 Make and return a Concord-object from ID and GENRE.
439 Optional argument DS specifies the data-source of the GENRE.
443 Lisp_CONCORD_DS* lds;
444 Lisp_Object genre_string;
445 char* genre_name_str;
446 CONCORD_Genre c_genre;
447 Lisp_CONCORD_Object* lcobj;
452 retval = concord_genre_cache_get_object (genre, id);
453 if (!UNBOUNDP (retval))
459 ds = Fconcord_genre_ds (genre);
460 CHECK_CONCORD_DS (ds);
461 lds = XCONCORD_DS (ds);
464 if ( STRINGP(genre) )
465 genre_string = genre;
467 genre_string = Fsymbol_name (genre);
468 TO_EXTERNAL_FORMAT (LISP_STRING, genre_string,
469 C_STRING_ALLOCA, genre_name_str,
471 c_genre = concord_ds_get_genre (lds->ds, genre_name_str);
474 lcobj = allocate_concord_object ();
475 lcobj->genre = c_genre;
477 XSET_CONCORD_OBJECT (retval, lcobj);
480 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
482 GCPRO4 (retval, id, genre, ds);
483 concord_genre_cache_put_object (genre, id, retval);
485 if (!EQ (Fconcord_object_get (retval, Q_id), id))
486 Fconcord_object_put (retval, Q_id, id);
493 DEFUN ("concord-object-p", Fconcord_object_p, 1, 1, 0, /*
494 Return t if OBJECT is a concord-object.
498 return CONCORD_OBJECT_P (object) ? Qt : Qnil;
501 DEFUN ("concord-object-id", Fconcord_object_id, 1, 1, 0, /*
502 Return an id of Concord-object OBJECT.
506 CHECK_CONCORD_OBJECT (object);
507 return XCONCORD_OBJECT_ID (object);
510 DEFUN ("concord-object-genre", Fconcord_object_genre, 1, 1, 0, /*
511 Return genre of Concord-object OBJECT.
515 CHECK_CONCORD_OBJECT (object);
516 return intern (concord_genre_get_name (XCONCORD_OBJECT_GENRE (object)));
519 DEFUN ("concord-decode-object", Fconcord_decode_object, 2, 4, 0, /*
520 Make and return a Concord-object from FEATURE and VALUE.
521 Optional argument GENRE specifies the GENRE of the object.
522 Optional argument DS specifies the data-source of the GENRE.
524 (feature, value, genre, ds))
526 Lisp_CONCORD_DS* lds;
528 CONCORD_Genre c_genre;
530 CONCORD_INDEX c_index;
531 Lisp_Object value_string;
533 CONCORD_String_Tank st_id;
536 int previous_print_readably;
537 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
540 ds = Fconcord_genre_ds (genre);
541 CHECK_CONCORD_DS (ds);
542 lds = XCONCORD_DS (ds);
545 if ( !STRINGP(feature) )
546 feature = Fsymbol_name (feature);
547 if ( !STRINGP(genre) )
548 genre = Fsymbol_name (genre);
549 TO_EXTERNAL_FORMAT (LISP_STRING, genre,
550 C_STRING_ALLOCA, genre_name,
552 c_genre = concord_ds_get_genre (lds->ds, genre_name);
558 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
559 C_STRING_ALLOCA, feature_name,
561 c_index = concord_genre_get_index (c_genre, feature_name);
567 previous_print_readably = print_readably;
569 GCPRO5 (feature, value, genre, ds, value_string);
570 value_string = Fprin1_to_string (value, Qnil);
572 print_readably = previous_print_readably;
573 TO_EXTERNAL_FORMAT (LISP_STRING,
574 value_string, C_STRING_ALLOCA, strid,
576 status = concord_index_strid_get_obj_string (c_index, strid, &st_id);
581 GCPRO4 (genre, ds, obj, retval);
583 obj = read_from_c_string (CONCORD_String_data (&st_id),
584 CONCORD_String_size (&st_id) );
586 obj = Fcar (Fread_from_string (make_ext_string
587 ((char*)CONCORD_String_data (&st_id),
588 CONCORD_String_size (&st_id),
592 retval = Fconcord_make_object (genre, obj, ds);
599 DEFUN ("concord-object-get", Fconcord_object_get, 2, 2, 0, /*
600 Return the value of OBJECT's FEATURE.
604 struct gcpro gcpro1, gcpro2;
605 int previous_print_readably;
606 Lisp_Object obj_string;
608 CONCORD_Genre c_genre;
610 CONCORD_Feature c_feature;
612 CONCORD_String_Tank st_value;
614 CHECK_CONCORD_OBJECT (object);
615 if ( !STRINGP(feature) )
616 feature = Fsymbol_name (feature);
617 previous_print_readably = print_readably;
619 GCPRO2 (object, feature);
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 status = concord_obj_get_feature_value_string (c_obj, c_feature,
639 Fcar (Fread_from_string (make_ext_string
640 ((char*)CONCORD_String_data (&st_value),
641 CONCORD_String_size (&st_value),
649 concord_object_put (Lisp_Object object, Lisp_Object feature,
652 struct gcpro gcpro1, gcpro2, gcpro3;
653 int previous_print_readably;
654 Lisp_Object obj_string;
656 CONCORD_Genre c_genre;
658 CONCORD_Feature c_feature;
660 Lisp_Object value_string;
663 if ( !STRINGP(feature) )
664 feature = Fsymbol_name (feature);
665 previous_print_readably = print_readably;
667 GCPRO3 (object, feature, value);
668 obj_string = Fprin1_to_string (XCONCORD_OBJECT_ID(object), Qnil);
670 print_readably = previous_print_readably;
671 TO_EXTERNAL_FORMAT (LISP_STRING, obj_string,
672 C_STRING_ALLOCA, c_obj, Qfile_name);
673 c_genre = XCONCORD_OBJECT_GENRE(object);
674 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
675 C_STRING_ALLOCA, feature_name,
677 c_feature = concord_genre_get_feature (c_genre, feature_name);
678 if (c_feature == NULL)
682 previous_print_readably = print_readably;
684 GCPRO3 (object, feature, value);
685 value_string = Fprin1_to_string (value, Qnil);
687 print_readably = previous_print_readably;
688 TO_EXTERNAL_FORMAT (LISP_STRING, value_string,
689 C_STRING_ALLOCA, c_value,
691 status = concord_obj_put_feature_value_str (c_obj, c_feature,
692 (unsigned char*)c_value);
695 status = chise_feature_sync (c_feature);
698 if (XSTRING_DATA(feature)[0] == '=')
700 CONCORD_INDEX c_index
701 = concord_genre_get_index (c_genre, feature_name);
703 concord_index_strid_put_obj (c_index, c_value, c_obj);
704 concord_index_sync (c_index);
709 DEFUN ("concord-object-put", Fconcord_object_put, 3, 3, 0, /*
710 Store a VALUE of OBJECT's FEATURE.
712 (object, feature, value))
717 CHECK_CONCORD_OBJECT (object);
718 CHECK_SYMBOL (feature);
719 name = symbol_name (XSYMBOL (feature));
720 name_str = string_data (name);
721 if ( NILP (concord_object_put (object, feature, value)) )
723 if ( EQ (feature, Q_subsumptive) ||
724 EQ (feature, Q_subsumptive_from) ||
725 EQ (feature, Q_denotational) ||
726 EQ (feature, Q_denotational_from) ||
727 ( ( ((name_str[0] == '-') && (name_str[1] == '>')) ||
728 ((name_str[0] == '<') && (name_str[1] == '-')) )
729 && (memchr (name_str, '*', name->size) == NULL) ) )
731 Lisp_Object rest = value;
733 Lisp_Object rev_feature = Qnil;
736 GCPRO1 (rev_feature);
737 if (EQ (feature, Q_subsumptive))
738 rev_feature = Q_subsumptive_from;
739 else if (EQ (feature, Q_subsumptive_from))
740 rev_feature = Q_subsumptive;
741 else if (EQ (feature, Q_denotational))
742 rev_feature = Q_denotational_from;
743 else if (EQ (feature, Q_denotational_from))
744 rev_feature = Q_denotational;
747 Bytecount length = string_length (name);
748 Bufbyte *rev_name_str = alloca (length + 1);
750 memcpy (rev_name_str + 2, name_str + 2, length - 2);
751 if (name_str[0] == '<')
753 rev_name_str[0] = '-';
754 rev_name_str[1] = '>';
758 rev_name_str[0] = '<';
759 rev_name_str[1] = '-';
761 rev_name_str[length] = 0;
762 rev_feature = intern (rev_name_str);
769 if ( CONCORD_OBJECT_P (ret) && !EQ (ret, object) )
773 ffv = Fconcord_object_get (ret, rev_feature);
775 concord_object_put (ret, rev_feature, list1 (object));
776 else if (NILP (Fmember (object, ffv)))
779 nconc2 (Fcopy_sequence (ffv), list1 (object)));
789 DEFUN ("concord-object-adjoin", Fconcord_object_adjoin, 3, 3, 0, /*
790 Cons ITEM onto the front of FEATURE's value of OBJECT only if it's not already there.
792 (object, feature, item))
794 Lisp_Object ret = Fconcord_object_get (object, feature);
796 if ( NILP (Fmember (item, ret)) )
797 return Fconcord_object_put (object, feature, Fcons (item, ret));
801 DEFUN ("concord-object-adjoin*", Fconcord_object_adjoinX, 3, 3, 0, /*
802 Append ITEM onto the end of FEATURE's value of OBJECT only if it's not already there.
804 (object, feature, item))
806 Lisp_Object ret = Fconcord_object_get (object, feature);
808 if ( NILP (Fmember (item, ret)) )
809 return Fconcord_object_put (object, feature, nconc2 (ret, list1 (item)));
813 struct closure_for_object_spec
817 } *concord_object_spec_closure;
820 add_feature_to_spec_mapper (CONCORD_Genre genre, char* name)
822 /* This function can GC */
823 CONCORD_String_Tank st_value;
824 CONCORD_Feature c_feature;
827 c_feature = concord_genre_get_feature (genre, name);
828 if (c_feature == NULL)
832 concord_obj_get_feature_value_string
833 (concord_object_spec_closure->object_id, c_feature, &st_value);
836 concord_object_spec_closure->spec
837 = Fcons (Fcons (intern (name),
838 Fcar (Fread_from_string
840 ((char*)CONCORD_String_data (&st_value),
841 CONCORD_String_size (&st_value),
844 concord_object_spec_closure->spec);
849 DEFUN ("concord-object-spec", Fconcord_object_spec, 1, 1, 0, /*
850 Return the spec of OBJECT.
854 Lisp_Object obj_string;
856 CONCORD_Genre c_genre;
857 struct gcpro gcpro1, gcpro2;
858 int previous_print_readably;
860 CHECK_CONCORD_OBJECT (object);
861 previous_print_readably = print_readably;
864 obj_string = Fprin1_to_string (XCONCORD_OBJECT_ID(object), Qnil);
866 print_readably = previous_print_readably;
867 TO_EXTERNAL_FORMAT (LISP_STRING, obj_string,
868 C_STRING_ALLOCA, c_obj, Qfile_name);
869 c_genre = XCONCORD_OBJECT_GENRE(object);
870 concord_object_spec_closure
871 = alloca (sizeof (struct closure_for_object_spec));
872 concord_object_spec_closure->object_id = c_obj;
873 concord_object_spec_closure->spec = Qnil;
874 GCPRO2 (object, concord_object_spec_closure->spec);
875 concord_genre_foreach_feature_name (c_genre,
876 add_feature_to_spec_mapper);
878 return concord_object_spec_closure->spec;
881 DEFUN ("concord-define-object", Fconcord_define_object, 2, 3, 0, /*
882 Define an object of which spec is a set of features SPEC.
886 Lisp_Object id = Fcdr (Fassq (Q_id, spec));
891 Lisp_Object rest = spec;
894 obj = Fconcord_make_object (genre, id, ds);
898 Fconcord_object_put (obj, Fcar (cell), Fcdr (cell));
906 struct closure_for_each_object
908 Lisp_Object function;
912 } *for_each_object_closure;
915 func_for_each_object (CONCORD_String object_id,
916 CONCORD_Feature feature,
917 CONCORD_String value)
919 struct gcpro gcpro1, gcpro2;
920 Lisp_Object obj, val, ret;
923 obj = read_from_c_string (CONCORD_String_data (object_id),
924 CONCORD_String_size (object_id) );
926 obj = Fcar (Fread_from_string (make_ext_string
927 ((char*)CONCORD_String_data (object_id),
928 CONCORD_String_size (object_id),
933 obj = Fconcord_make_object (for_each_object_closure->genre,
935 for_each_object_closure->ds);
937 val = read_from_c_string (CONCORD_String_data (value),
938 CONCORD_String_size (value) );
940 val = Fcar (Fread_from_string (make_ext_string
941 ((char*)CONCORD_String_data (value),
942 CONCORD_String_size (value),
948 ret = call2 (for_each_object_closure->function, obj, val);
950 for_each_object_closure->ret = ret;
954 DEFUN ("concord-for-each-object-in-feature",
955 Fconcord_foreach_object_in_feature, 2, 4, 0, /*
956 Do FUNCTION over objects in FEATURE, calling it with two args,
957 each key and value in the FEATURE table.
958 Optional argument GENRE specifies the genre of the FEATURE.
959 When the FUNCTION returns non-nil, it breaks the repeat.
961 (function, feature, genre, ds))
963 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
964 Lisp_CONCORD_DS* lds;
966 CONCORD_Genre c_genre;
968 CONCORD_Feature c_feature;
971 ds = Fconcord_genre_ds (genre);
972 CHECK_CONCORD_DS (ds);
973 lds = XCONCORD_DS (ds);
976 if ( !STRINGP(feature) )
977 feature = Fsymbol_name (feature);
978 if ( !STRINGP(genre) )
979 genre = Fsymbol_name (genre);
980 TO_EXTERNAL_FORMAT (LISP_STRING, genre,
981 C_STRING_ALLOCA, genre_name,
983 c_genre = concord_ds_get_genre (lds->ds, genre_name);
987 CHECK_STRING (feature);
988 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
989 C_STRING_ALLOCA, feature_name,
991 c_feature = concord_genre_get_feature (c_genre, feature_name);
992 if (c_feature == NULL)
994 for_each_object_closure
995 = alloca (sizeof (struct closure_for_each_object));
996 for_each_object_closure->function = function;
997 for_each_object_closure->genre = genre;
998 for_each_object_closure->ds = ds;
999 for_each_object_closure->ret = Qnil;
1000 GCPRO4 (for_each_object_closure->function,
1001 for_each_object_closure->genre,
1002 for_each_object_closure->ds,
1003 for_each_object_closure->ret);
1004 concord_feature_foreach_obj_string (c_feature, func_for_each_object);
1007 return for_each_object_closure->ret;
1012 concord_name_validate (Lisp_Object keyword, Lisp_Object value,
1013 Error_behavior errb)
1015 if (ERRB_EQ (errb, ERROR_ME))
1017 CHECK_SYMBOL (value);
1021 return SYMBOLP (value);
1025 concord_id_validate (Lisp_Object keyword, Lisp_Object value,
1026 Error_behavior errb)
1028 if (ERRB_EQ (errb, ERROR_ME))
1030 /* CHECK_SYMBOL (value); */
1031 if ( INTP (value) || CHARP (value) || SYMBOLP (value) )
1034 dead_wrong_type_argument (Qsymbolp, value);
1038 return INTP (value) || CHARP (value) || SYMBOLP (value);
1042 concord_object_validate (Lisp_Object data, Error_behavior errb)
1044 struct gcpro gcpro1, gcpro2, gcpro3;
1046 Lisp_Object valw = Qnil;
1047 Lisp_Object genre = Qnil;
1048 Lisp_Object oid = Qnil;
1050 data = Fcdr (data); /* skip over Qconcord_object */
1051 while (!NILP (data))
1053 Lisp_Object keyw = Fcar (data);
1058 if (EQ (keyw, Qgenre))
1060 else if (EQ (keyw, Q_id))
1068 maybe_error (Qconcord_object, errb, "No genre given");
1073 maybe_error (Qconcord_object, errb, "No object-id given");
1077 GCPRO3 (genre, oid, retval);
1078 retval = Fconcord_make_object (genre, oid, Qnil);
1082 maybe_signal_simple_error_2 ("No such Concord-object",
1083 oid, genre, Qconcord_object, errb);
1091 concord_object_instantiate (Lisp_Object data)
1093 struct gcpro gcpro1, gcpro2;
1096 GCPRO2 (data, retval);
1097 retval = Fconcord_make_object (Fplist_get (data, Qgenre, Qnil),
1098 Fplist_get (data, Q_id, Qnil),
1106 syms_of_concord (void)
1108 INIT_LRECORD_IMPLEMENTATION (concord_ds);
1109 INIT_LRECORD_IMPLEMENTATION (concord_object);
1111 defsymbol (&Qconcord, "concord");
1112 defsymbol (&Qconcord_dsp, "concord-dsp");
1113 defsymbol (&Qconcord_objectp, "concord-objectp");
1114 defsymbol (&Qconcord_object, "concord-object");
1115 defsymbol (&Qgenre, "genre");
1116 defsymbol (&Q_id, "=id");
1117 #ifdef HAVE_LIBCHISE
1118 defsymbol (&Qcharacter, "character");
1119 defsymbol (&Qfeature, "feature");
1122 DEFSUBR (Fconcord_open_ds);
1123 DEFSUBR (Fconcord_ds_p);
1124 DEFSUBR (Fconcord_close_ds);
1125 DEFSUBR (Fconcord_ds_directory);
1127 DEFSUBR (Fconcord_assign_genre);
1128 DEFSUBR (Fconcord_genre_directory);
1129 DEFSUBR (Fconcord_genre_ds);
1130 DEFSUBR (Fconcord_feature_list);
1132 DEFSUBR (Fconcord_make_object);
1133 DEFSUBR (Fconcord_object_p);
1134 DEFSUBR (Fconcord_object_id);
1135 DEFSUBR (Fconcord_object_genre);
1136 DEFSUBR (Fconcord_decode_object);
1137 DEFSUBR (Fconcord_object_get);
1138 DEFSUBR (Fconcord_object_put);
1139 DEFSUBR (Fconcord_object_adjoin);
1140 DEFSUBR (Fconcord_object_adjoinX);
1141 DEFSUBR (Fconcord_define_object);
1142 DEFSUBR (Fconcord_object_spec);
1143 DEFSUBR (Fconcord_foreach_object_in_feature);
1147 structure_type_create_concord (void)
1149 struct structure_type *st;
1151 st = define_structure_type (Qconcord_object,
1152 concord_object_validate,
1153 concord_object_instantiate);
1155 define_structure_type_keyword (st, Qgenre, concord_name_validate);
1156 define_structure_type_keyword (st, Q_id, concord_id_validate);
1160 vars_of_concord (void)
1162 Fprovide (Qconcord);
1164 staticpro (&Vconcord_ds_hash_table);
1165 Vconcord_ds_hash_table
1166 = make_lisp_hash_table (8, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
1168 staticpro (&Vconcord_genre_hash_table);
1169 Vconcord_genre_hash_table
1170 = make_lisp_hash_table (16, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
1172 staticpro (&Vconcord_genre_object_hash_table);
1173 Vconcord_genre_object_hash_table
1174 = make_lisp_hash_table (16, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
1178 complex_vars_of_concord (void)
1180 #ifdef HAVE_LIBCHISE
1181 Fconcord_assign_genre (Qcharacter, Vchise_system_db_directory);
1182 Fconcord_assign_genre (Qfeature, Vchise_system_db_directory);