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 */
36 EXFUN (Fread_from_string, 3);
39 EXFUN (Fconcord_decode_object, 4);
40 EXFUN (Fconcord_object_put, 3);
41 EXFUN (Fconcord_object_get, 2);
44 Lisp_Object Qconcord_object;
45 Lisp_Object Qgenre, Q_id;
47 Lisp_Object Qcharacter;
51 Lisp_Object Vconcord_ds_hash_table;
52 Lisp_Object Vconcord_genre_hash_table;
53 Lisp_Object Vconcord_genre_object_hash_table;
56 typedef struct Lisp_CONCORD_DS Lisp_CONCORD_DS;
57 DECLARE_LRECORD (concord_ds, Lisp_CONCORD_DS);
59 Lisp_Object Qconcord_dsp;
61 struct Lisp_CONCORD_DS
63 struct lcrecord_header header;
67 #define XCONCORD_DS(x) XRECORD (x, concord_ds, Lisp_CONCORD_DS)
68 #define XSET_CONCORD_DS(x, p) XSETRECORD (x, p, concord_ds)
69 #define CONCORD_DS_P(x) RECORDP (x, concord_ds)
70 #define CHECK_CONCORD_DS(x) CHECK_RECORD (x, concord_ds)
71 #define CONCHECK_CONCORD_DS(x) CONCHECK_RECORD (x, concord_ds)
73 static Lisp_CONCORD_DS*
74 allocate_concord_ds (void)
77 = alloc_lcrecord_type (Lisp_CONCORD_DS, &lrecord_concord_ds);
84 mark_concord_ds (Lisp_Object object)
90 print_concord_ds (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
92 Lisp_CONCORD_DS* lds = XCONCORD_DS (obj);
95 error ("printing unreadable object #<concord_ds 0x%x>", lds->header.uid);
97 write_c_string ("#<concord_ds \"", printcharfun);
98 write_c_string (concord_ds_location (lds->ds), printcharfun);
99 write_c_string ("\">", printcharfun);
103 finalize_concord_ds (void *header, int for_disksave)
105 Lisp_CONCORD_DS *lds = (Lisp_CONCORD_DS *) header;
110 XSET_CONCORD_DS (object, lds);
113 ("Can't dump an emacs containing concord_ds objects", object);
115 if ( lds->ds != NULL)
116 concord_close_ds (lds->ds);
119 DEFINE_LRECORD_IMPLEMENTATION ("concord_ds", concord_ds,
120 mark_concord_ds, print_concord_ds,
121 finalize_concord_ds, 0, 0, 0,
124 DEFUN ("concord-close-ds", Fconcord_close_ds, 1, 1, 0, /*
125 Close concord-ds CONCORD-DS.
129 Lisp_CONCORD_DS* lds;
130 lds = XCONCORD_DS (concord_ds);
131 if ( lds->ds != NULL)
132 concord_close_ds (lds->ds);
137 DEFUN ("concord-ds-p", Fconcord_ds_p, 1, 1, 0, /*
138 Return t if OBJECT is a concord-ds.
142 return CONCORD_DS_P (object) ? Qt : Qnil;
145 DEFUN ("concord-open-ds", Fconcord_open_ds, 1, 4, 0, /*
146 Return a new concord-ds object opened on DIRECTORY.
147 Optional arguments TYPE and SUBTYPE specify the concord_ds type.
148 Optional argument MODE gives the permissions to use when opening DIRECTORY,
149 and defaults to 0755.
151 (directory, type, subtype, mode))
154 Lisp_CONCORD_DS* lds = NULL;
160 CHECK_STRING (directory);
162 directory = Ffile_name_as_directory (Fexpand_file_name (directory, Qnil));
165 retval = Fgethash (directory, Vconcord_ds_hash_table, Qunbound);
166 if (!UNBOUNDP (retval))
171 TO_EXTERNAL_FORMAT (LISP_STRING, directory,
172 C_STRING_ALLOCA, pathname,
177 modemask = 0755; /* rwxr-xr-x */
182 modemask = XINT (mode);
185 ds = concord_open_ds (CONCORD_Backend_Berkeley_DB,
186 pathname, 0, modemask);
190 lds = allocate_concord_ds ();
192 XSET_CONCORD_DS (retval, lds);
193 Fputhash (directory, retval, Vconcord_ds_hash_table);
197 DEFUN ("concord-ds-directory", Fconcord_ds_directory, 1, 1, 0, /*
198 Return directory of concord-ds DS.
202 Lisp_CONCORD_DS* lds;
205 CHECK_CONCORD_DS (ds);
206 lds = XCONCORD_DS (ds);
210 directory = concord_ds_location (lds->ds);
211 if (directory == NULL)
214 return build_ext_string (directory, Qfile_name);
218 DEFUN ("concord-assign-genre", Fconcord_assign_genre, 2, 2, 0, /*
219 Assign data-source DIRECTORY to GENRE.
225 CHECK_SYMBOL (genre);
226 if ( CONCORD_DS_P (directory) )
231 CHECK_STRING (directory);
234 = Ffile_name_as_directory (Fexpand_file_name (directory, Qnil));
237 Fputhash (genre, directory, Vconcord_genre_hash_table);
241 DEFUN ("concord-genre-directory", Fconcord_genre_directory, 1, 1, 0, /*
242 Return pathname of GENRE.
247 CHECK_SYMBOL (genre);
249 retval = Fgethash (genre, Vconcord_genre_hash_table, Qunbound);
250 if ( STRINGP (retval) )
252 else if ( CONCORD_DS_P (retval) )
253 return Fconcord_ds_directory (retval);
257 DEFUN ("concord-genre-ds", Fconcord_genre_ds, 1, 1, 0, /*
258 Return concord-ds of GENRE.
264 CHECK_SYMBOL (genre);
266 retval = Fgethash (genre, Vconcord_genre_hash_table, Qunbound);
267 if ( STRINGP (retval) )
269 retval = Fconcord_open_ds (retval, Qnil, Qnil, Qnil);
270 if ( !NILP (retval) )
271 Fputhash (genre, retval, Vconcord_genre_hash_table);
274 else if ( CONCORD_DS_P (retval) )
280 struct closure_to_list_feature
282 Lisp_Object feature_list;
283 } *concord_feature_list_closure;
286 add_feature_to_list_mapper (CONCORD_Genre genre, char* name)
288 /* This function can GC */
289 concord_feature_list_closure->feature_list
290 = Fcons (intern (name), concord_feature_list_closure->feature_list);
294 DEFUN ("concord-feature-list", Fconcord_feature_list, 1, 2, 0, /*
295 Return the list of all existing features in GENRE.
299 Lisp_CONCORD_DS* lds;
301 CONCORD_Genre c_genre;
304 CHECK_SYMBOL (genre);
306 ds = Fconcord_genre_ds (genre);
307 CHECK_CONCORD_DS (ds);
308 lds = XCONCORD_DS (ds);
311 genre = Fsymbol_name (genre);
312 TO_EXTERNAL_FORMAT (LISP_STRING, genre,
313 C_STRING_ALLOCA, genre_name,
315 c_genre = concord_ds_get_genre (lds->ds, genre_name);
318 concord_feature_list_closure
319 = alloca (sizeof (struct closure_to_list_feature));
320 concord_feature_list_closure->feature_list = Qnil;
321 GCPRO1 (concord_feature_list_closure->feature_list);
322 concord_genre_foreach_feature_name (c_genre,
323 add_feature_to_list_mapper);
325 return concord_feature_list_closure->feature_list;
329 typedef struct Lisp_CONCORD_Object Lisp_CONCORD_Object;
330 DECLARE_LRECORD (concord_object, Lisp_CONCORD_Object);
332 Lisp_Object Qconcord_objectp;
334 struct Lisp_CONCORD_Object
336 struct lcrecord_header header;
341 #define XCONCORD_OBJECT(x) XRECORD (x, concord_object, Lisp_CONCORD_Object)
342 #define XSET_CONCORD_OBJECT(x, p) XSETRECORD (x, p, concord_object)
343 #define CONCORD_OBJECT_P(x) RECORDP (x, concord_object)
344 #define CHECK_CONCORD_OBJECT(x) CHECK_RECORD (x, concord_object)
345 #define CONCHECK_CONCORD_OBJECT(x) CONCHECK_RECORD (x, concord_object)
346 #define CONCORD_OBJECT_GENRE(x) ((x)->genre)
347 #define CONCORD_OBJECT_ID(x) ((x)->id)
348 #define XCONCORD_OBJECT_ID(x) CONCORD_OBJECT_ID (XCONCORD_OBJECT(x))
349 #define XCONCORD_OBJECT_GENRE(x) CONCORD_OBJECT_GENRE (XCONCORD_OBJECT(x))
351 static Lisp_CONCORD_Object*
352 allocate_concord_object (void)
354 Lisp_CONCORD_Object* lcobj
355 = alloc_lcrecord_type (Lisp_CONCORD_Object, &lrecord_concord_object);
358 lcobj->id = Qunbound;
363 mark_concord_object (Lisp_Object object)
365 mark_object (XCONCORD_OBJECT_ID(object));
370 print_concord_object (Lisp_Object obj,
371 Lisp_Object printcharfun, int escapeflag)
373 Lisp_CONCORD_Object* lcobj = XCONCORD_OBJECT (obj);
374 struct gcpro gcpro1, gcpro2;
378 write_c_string ("#s(concord-object", printcharfun);
379 write_c_string (" genre ", printcharfun);
380 write_c_string (concord_genre_get_name (lcobj->genre), printcharfun);
381 write_c_string (" =id ", printcharfun);
382 GCPRO2 (obj, printcharfun);
383 print_internal (lcobj->id, printcharfun, escapeflag);
385 write_c_string (")", printcharfun);
389 write_c_string ("#<concord-object \"", printcharfun);
390 write_c_string (concord_ds_location
391 (concord_genre_get_data_source (lcobj->genre)),
393 write_c_string (":", printcharfun);
394 write_c_string (concord_genre_get_name (lcobj->genre), printcharfun);
395 write_c_string (";", printcharfun);
396 GCPRO2 (obj, printcharfun);
397 print_internal (lcobj->id, printcharfun, escapeflag);
399 write_c_string ("\">", printcharfun);
404 finalize_concord_object (void *header, int for_disksave)
406 Lisp_CONCORD_Object* lcobj = (Lisp_CONCORD_Object *) header;
411 XSET_CONCORD_OBJECT (object, lcobj);
414 ("Can't dump an emacs containing concord_object objects", object);
418 static const struct lrecord_description concord_object_description[] = {
419 { XD_LISP_OBJECT, offsetof (Lisp_CONCORD_Object, id) },
423 DEFINE_LRECORD_IMPLEMENTATION ("concord_object", concord_object,
424 mark_concord_object, print_concord_object,
425 finalize_concord_object, 0, 0,
426 concord_object_description,
427 Lisp_CONCORD_Object);
430 concord_genre_cache_get_object (Lisp_Object genre, Lisp_Object id)
432 Lisp_Object obj_hash;
434 obj_hash = Fgethash (genre, Vconcord_genre_object_hash_table, Qunbound);
435 if (UNBOUNDP (obj_hash))
437 return Fgethash (id, obj_hash, Qunbound);
441 concord_genre_cache_put_object (Lisp_Object genre, Lisp_Object id,
444 Lisp_Object obj_hash;
446 obj_hash = Fgethash (genre, Vconcord_genre_object_hash_table, Qunbound);
447 if (UNBOUNDP (obj_hash))
450 = make_lisp_hash_table (256, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
451 Fputhash (genre, obj_hash, Vconcord_genre_object_hash_table);
453 return Fputhash (id, object, obj_hash);
456 DEFUN ("concord-make-object", Fconcord_make_object, 1, 3, 0, /*
457 Make and return a Concord-object from ID and GENRE.
458 Optional argument DS specifies the data-source of the GENRE.
462 Lisp_CONCORD_DS* lds;
463 Lisp_Object genre_string;
464 char* genre_name_str;
465 CONCORD_Genre c_genre;
466 Lisp_CONCORD_Object* lcobj;
471 retval = concord_genre_cache_get_object (genre, id);
472 if (!UNBOUNDP (retval))
478 ds = Fconcord_genre_ds (genre);
479 CHECK_CONCORD_DS (ds);
480 lds = XCONCORD_DS (ds);
483 if ( STRINGP(genre) )
484 genre_string = genre;
486 genre_string = Fsymbol_name (genre);
487 TO_EXTERNAL_FORMAT (LISP_STRING, genre_string,
488 C_STRING_ALLOCA, genre_name_str,
490 c_genre = concord_ds_get_genre (lds->ds, genre_name_str);
493 lcobj = allocate_concord_object ();
494 lcobj->genre = c_genre;
496 XSET_CONCORD_OBJECT (retval, lcobj);
499 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
501 GCPRO4 (retval, id, genre, ds);
502 concord_genre_cache_put_object (genre, id, retval);
504 if (!EQ (Fconcord_object_get (retval, Q_id), id))
505 Fconcord_object_put (retval, Q_id, id);
512 DEFUN ("concord-object-p", Fconcord_object_p, 1, 1, 0, /*
513 Return t if OBJECT is a concord-object.
517 return CONCORD_OBJECT_P (object) ? Qt : Qnil;
520 DEFUN ("concord-object-id", Fconcord_object_id, 1, 1, 0, /*
521 Return an id of Concord-object OBJECT.
525 CHECK_CONCORD_OBJECT (object);
526 return XCONCORD_OBJECT_ID (object);
529 DEFUN ("concord-object-genre", Fconcord_object_genre, 1, 1, 0, /*
530 Return genre of Concord-object OBJECT.
534 CHECK_CONCORD_OBJECT (object);
535 return intern (concord_genre_get_name (XCONCORD_OBJECT_GENRE (object)));
538 DEFUN ("concord-decode-object", Fconcord_decode_object, 2, 4, 0, /*
539 Make and return a Concord-object from FEATURE and VALUE.
540 Optional argument GENRE specifies the GENRE of the object.
541 Optional argument DS specifies the data-source of the GENRE.
543 (feature, value, genre, ds))
545 Lisp_CONCORD_DS* lds;
547 CONCORD_Genre c_genre;
549 CONCORD_INDEX c_index;
550 Lisp_Object value_string;
552 CONCORD_String_Tank st_id;
555 int previous_print_readably;
556 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
559 ds = Fconcord_genre_ds (genre);
560 CHECK_CONCORD_DS (ds);
561 lds = XCONCORD_DS (ds);
564 if ( !STRINGP(feature) )
565 feature = Fsymbol_name (feature);
566 if ( !STRINGP(genre) )
567 genre = Fsymbol_name (genre);
568 TO_EXTERNAL_FORMAT (LISP_STRING, genre,
569 C_STRING_ALLOCA, genre_name,
571 c_genre = concord_ds_get_genre (lds->ds, genre_name);
577 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
578 C_STRING_ALLOCA, feature_name,
580 c_index = concord_genre_get_index (c_genre, feature_name);
586 previous_print_readably = print_readably;
588 GCPRO5 (feature, value, genre, ds, value_string);
589 value_string = Fprin1_to_string (value, Qnil);
591 print_readably = previous_print_readably;
592 TO_EXTERNAL_FORMAT (LISP_STRING,
593 value_string, C_STRING_ALLOCA, strid,
595 status = concord_index_strid_get_obj_string (c_index, strid, &st_id);
600 GCPRO4 (genre, ds, obj, retval);
602 obj = read_from_c_string (CONCORD_String_data (&st_id),
603 CONCORD_String_size (&st_id) );
605 obj = Fcar (Fread_from_string (make_ext_string
606 ((char*)CONCORD_String_data (&st_id),
607 CONCORD_String_size (&st_id),
611 retval = Fconcord_make_object (genre, obj, ds);
618 DEFUN ("concord-object-get", Fconcord_object_get, 2, 2, 0, /*
619 Return the value of OBJECT's FEATURE.
623 struct gcpro gcpro1, gcpro2;
624 int previous_print_readably;
625 Lisp_Object obj_string;
627 CONCORD_Genre c_genre;
629 CONCORD_Feature c_feature;
631 CONCORD_String_Tank st_value;
633 CHECK_CONCORD_OBJECT (object);
634 if ( !STRINGP(feature) )
635 feature = Fsymbol_name (feature);
636 previous_print_readably = print_readably;
638 GCPRO2 (object, feature);
639 obj_string = Fprin1_to_string (XCONCORD_OBJECT_ID(object), Qnil);
641 print_readably = previous_print_readably;
642 TO_EXTERNAL_FORMAT (LISP_STRING, obj_string,
643 C_STRING_ALLOCA, c_obj, Qfile_name);
644 c_genre = XCONCORD_OBJECT_GENRE(object);
645 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
646 C_STRING_ALLOCA, feature_name,
648 c_feature = concord_genre_get_feature (c_genre, feature_name);
649 if (c_feature == NULL)
653 status = concord_obj_get_feature_value_string (c_obj, c_feature,
658 Fcar (Fread_from_string (make_ext_string
659 ((char*)CONCORD_String_data (&st_value),
660 CONCORD_String_size (&st_value),
668 concord_object_put (Lisp_Object object, Lisp_Object feature,
671 struct gcpro gcpro1, gcpro2, gcpro3;
672 int previous_print_readably;
673 Lisp_Object obj_string;
675 CONCORD_Genre c_genre;
677 CONCORD_Feature c_feature;
679 Lisp_Object value_string;
682 if ( !STRINGP(feature) )
683 feature = Fsymbol_name (feature);
684 previous_print_readably = print_readably;
686 GCPRO3 (object, feature, value);
687 obj_string = Fprin1_to_string (XCONCORD_OBJECT_ID(object), Qnil);
689 print_readably = previous_print_readably;
690 TO_EXTERNAL_FORMAT (LISP_STRING, obj_string,
691 C_STRING_ALLOCA, c_obj, Qfile_name);
692 c_genre = XCONCORD_OBJECT_GENRE(object);
693 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
694 C_STRING_ALLOCA, feature_name,
696 c_feature = concord_genre_get_feature (c_genre, feature_name);
697 if (c_feature == NULL)
701 previous_print_readably = print_readably;
703 GCPRO3 (object, feature, value);
704 value_string = Fprin1_to_string (value, Qnil);
706 print_readably = previous_print_readably;
707 TO_EXTERNAL_FORMAT (LISP_STRING, value_string,
708 C_STRING_ALLOCA, c_value,
710 status = concord_obj_put_feature_value_str (c_obj, c_feature,
711 (unsigned char*)c_value);
714 status = chise_feature_sync (c_feature);
717 if (XSTRING_DATA(feature)[0] == '=')
719 CONCORD_INDEX c_index
720 = concord_genre_get_index (c_genre, feature_name);
722 concord_index_strid_put_obj (c_index, c_value, c_obj);
723 concord_index_sync (c_index);
728 DEFUN ("concord-object-put", Fconcord_object_put, 3, 3, 0, /*
729 Store a VALUE of OBJECT's FEATURE.
731 (object, feature, value))
736 CHECK_CONCORD_OBJECT (object);
737 CHECK_SYMBOL (feature);
738 name = symbol_name (XSYMBOL (feature));
739 name_str = string_data (name);
740 if ( NILP (concord_object_put (object, feature, value)) )
742 if ( EQ (feature, Q_subsumptive) ||
743 EQ (feature, Q_subsumptive_from) ||
744 EQ (feature, Q_denotational) ||
745 EQ (feature, Q_denotational_from) ||
746 ( ( ((name_str[0] == '-') && (name_str[1] == '>')) ||
747 ((name_str[0] == '<') && (name_str[1] == '-')) )
748 && (memchr (name_str, '*', name->size) == NULL) ) )
750 Lisp_Object rest = value;
752 Lisp_Object rev_feature = Qnil;
755 GCPRO1 (rev_feature);
756 if (EQ (feature, Q_subsumptive))
757 rev_feature = Q_subsumptive_from;
758 else if (EQ (feature, Q_subsumptive_from))
759 rev_feature = Q_subsumptive;
760 else if (EQ (feature, Q_denotational))
761 rev_feature = Q_denotational_from;
762 else if (EQ (feature, Q_denotational_from))
763 rev_feature = Q_denotational;
766 Bytecount length = string_length (name);
767 Bufbyte *rev_name_str = alloca (length + 1);
769 memcpy (rev_name_str + 2, name_str + 2, length - 2);
770 if (name_str[0] == '<')
772 rev_name_str[0] = '-';
773 rev_name_str[1] = '>';
777 rev_name_str[0] = '<';
778 rev_name_str[1] = '-';
780 rev_name_str[length] = 0;
781 rev_feature = intern (rev_name_str);
788 if ( CONCORD_OBJECT_P (ret) && !EQ (ret, object) )
792 ffv = Fconcord_object_get (ret, rev_feature);
794 concord_object_put (ret, rev_feature, list1 (object));
795 else if (NILP (Fmemq (object, ffv)))
798 nconc2 (Fcopy_sequence (ffv), list1 (object)));
808 struct closure_for_object_spec
812 } *concord_object_spec_closure;
815 add_feature_to_spec_mapper (CONCORD_Genre genre, char* name)
817 /* This function can GC */
818 CONCORD_String_Tank st_value;
819 CONCORD_Feature c_feature;
822 c_feature = concord_genre_get_feature (genre, name);
823 if (c_feature == NULL)
827 concord_obj_get_feature_value_string
828 (concord_object_spec_closure->object_id, c_feature, &st_value);
831 concord_object_spec_closure->spec
832 = Fcons (Fcons (intern (name),
833 Fcar (Fread_from_string
835 ((char*)CONCORD_String_data (&st_value),
836 CONCORD_String_size (&st_value),
839 concord_object_spec_closure->spec);
844 DEFUN ("concord-object-spec", Fconcord_object_spec, 1, 1, 0, /*
845 Return the spec of OBJECT.
849 Lisp_Object obj_string;
851 CONCORD_Genre c_genre;
852 struct gcpro gcpro1, gcpro2;
853 int previous_print_readably;
855 CHECK_CONCORD_OBJECT (object);
856 previous_print_readably = print_readably;
859 obj_string = Fprin1_to_string (XCONCORD_OBJECT_ID(object), Qnil);
861 print_readably = previous_print_readably;
862 TO_EXTERNAL_FORMAT (LISP_STRING, obj_string,
863 C_STRING_ALLOCA, c_obj, Qfile_name);
864 c_genre = XCONCORD_OBJECT_GENRE(object);
865 concord_object_spec_closure
866 = alloca (sizeof (struct closure_for_object_spec));
867 concord_object_spec_closure->object_id = c_obj;
868 concord_object_spec_closure->spec = Qnil;
869 GCPRO2 (object, concord_object_spec_closure->spec);
870 concord_genre_foreach_feature_name (c_genre,
871 add_feature_to_spec_mapper);
873 return concord_object_spec_closure->spec;
876 DEFUN ("concord-define-object", Fconcord_define_object, 2, 3, 0, /*
877 Define an object of which spec is a set of features SPEC.
881 Lisp_Object id = Fcdr (Fassq (Q_id, spec));
886 Lisp_Object rest = spec;
889 obj = Fconcord_make_object (genre, id, ds);
893 Fconcord_object_put (obj, Fcar (cell), Fcdr (cell));
901 struct closure_for_each_object
903 Lisp_Object function;
907 } *for_each_object_closure;
910 func_for_each_object (CONCORD_String object_id,
911 CONCORD_Feature feature,
912 CONCORD_String value)
914 struct gcpro gcpro1, gcpro2;
915 Lisp_Object obj, val, ret;
918 obj = read_from_c_string (CONCORD_String_data (object_id),
919 CONCORD_String_size (object_id) );
921 obj = Fcar (Fread_from_string (make_ext_string
922 ((char*)CONCORD_String_data (object_id),
923 CONCORD_String_size (object_id),
928 obj = Fconcord_make_object (for_each_object_closure->genre,
930 for_each_object_closure->ds);
932 val = read_from_c_string (CONCORD_String_data (value),
933 CONCORD_String_size (value) );
935 val = Fcar (Fread_from_string (make_ext_string
936 ((char*)CONCORD_String_data (value),
937 CONCORD_String_size (value),
943 ret = call2 (for_each_object_closure->function, obj, val);
945 for_each_object_closure->ret = ret;
949 DEFUN ("concord-for-each-object-in-feature",
950 Fconcord_foreach_object_in_feature, 2, 4, 0, /*
951 Do FUNCTION over objects in FEATURE, calling it with two args,
952 each key and value in the FEATURE table.
953 Optional argument GENRE specifies the genre of the FEATURE.
954 When the FUNCTION returns non-nil, it breaks the repeat.
956 (function, feature, genre, ds))
958 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
959 Lisp_CONCORD_DS* lds;
961 CONCORD_Genre c_genre;
963 CONCORD_Feature c_feature;
966 ds = Fconcord_genre_ds (genre);
967 CHECK_CONCORD_DS (ds);
968 lds = XCONCORD_DS (ds);
971 if ( !STRINGP(feature) )
972 feature = Fsymbol_name (feature);
973 if ( !STRINGP(genre) )
974 genre = Fsymbol_name (genre);
975 TO_EXTERNAL_FORMAT (LISP_STRING, genre,
976 C_STRING_ALLOCA, genre_name,
978 c_genre = concord_ds_get_genre (lds->ds, genre_name);
982 CHECK_STRING (feature);
983 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
984 C_STRING_ALLOCA, feature_name,
986 c_feature = concord_genre_get_feature (c_genre, feature_name);
987 if (c_feature == NULL)
989 for_each_object_closure
990 = alloca (sizeof (struct closure_for_each_object));
991 for_each_object_closure->function = function;
992 for_each_object_closure->genre = genre;
993 for_each_object_closure->ds = ds;
994 for_each_object_closure->ret = Qnil;
995 GCPRO4 (for_each_object_closure->function,
996 for_each_object_closure->genre,
997 for_each_object_closure->ds,
998 for_each_object_closure->ret);
999 concord_feature_foreach_obj_string (c_feature, func_for_each_object);
1002 return for_each_object_closure->ret;
1007 concord_name_validate (Lisp_Object keyword, Lisp_Object value,
1008 Error_behavior errb)
1010 if (ERRB_EQ (errb, ERROR_ME))
1012 CHECK_SYMBOL (value);
1016 return SYMBOLP (value);
1020 concord_id_validate (Lisp_Object keyword, Lisp_Object value,
1021 Error_behavior errb)
1023 if (ERRB_EQ (errb, ERROR_ME))
1025 /* CHECK_SYMBOL (value); */
1026 if ( INTP (value) || CHARP (value) || SYMBOLP (value) )
1029 dead_wrong_type_argument (Qsymbolp, value);
1033 return INTP (value) || CHARP (value) || SYMBOLP (value);
1037 concord_object_validate (Lisp_Object data, Error_behavior errb)
1039 struct gcpro gcpro1, gcpro2, gcpro3;
1041 Lisp_Object valw = Qnil;
1042 Lisp_Object genre = Qnil;
1043 Lisp_Object oid = Qnil;
1045 data = Fcdr (data); /* skip over Qconcord_object */
1046 while (!NILP (data))
1048 Lisp_Object keyw = Fcar (data);
1053 if (EQ (keyw, Qgenre))
1055 else if (EQ (keyw, Q_id))
1063 maybe_error (Qconcord_object, errb, "No genre given");
1068 maybe_error (Qconcord_object, errb, "No object-id given");
1072 GCPRO3 (genre, oid, retval);
1073 retval = Fconcord_make_object (genre, oid, Qnil);
1077 maybe_signal_simple_error_2 ("No such Concord-object",
1078 oid, genre, Qconcord_object, errb);
1086 concord_object_instantiate (Lisp_Object data)
1088 struct gcpro gcpro1, gcpro2;
1091 GCPRO2 (data, retval);
1092 retval = Fconcord_make_object (Fplist_get (data, Qgenre, Qnil),
1093 Fplist_get (data, Q_id, Qnil),
1101 syms_of_concord (void)
1103 INIT_LRECORD_IMPLEMENTATION (concord_ds);
1104 INIT_LRECORD_IMPLEMENTATION (concord_object);
1106 defsymbol (&Qconcord, "concord");
1107 defsymbol (&Qconcord_dsp, "concord-dsp");
1108 defsymbol (&Qconcord_objectp, "concord-objectp");
1109 defsymbol (&Qconcord_object, "concord-object");
1110 defsymbol (&Qgenre, "genre");
1111 defsymbol (&Q_id, "=id");
1112 #ifdef HAVE_LIBCHISE
1113 defsymbol (&Qcharacter, "character");
1114 defsymbol (&Qfeature, "feature");
1117 DEFSUBR (Fconcord_open_ds);
1118 DEFSUBR (Fconcord_ds_p);
1119 DEFSUBR (Fconcord_close_ds);
1120 DEFSUBR (Fconcord_ds_directory);
1122 DEFSUBR (Fconcord_assign_genre);
1123 DEFSUBR (Fconcord_genre_directory);
1124 DEFSUBR (Fconcord_genre_ds);
1125 DEFSUBR (Fconcord_feature_list);
1127 DEFSUBR (Fconcord_make_object);
1128 DEFSUBR (Fconcord_object_p);
1129 DEFSUBR (Fconcord_object_id);
1130 DEFSUBR (Fconcord_object_genre);
1131 DEFSUBR (Fconcord_decode_object);
1132 DEFSUBR (Fconcord_object_get);
1133 DEFSUBR (Fconcord_object_put);
1134 DEFSUBR (Fconcord_define_object);
1135 DEFSUBR (Fconcord_object_spec);
1136 DEFSUBR (Fconcord_foreach_object_in_feature);
1140 structure_type_create_concord (void)
1142 struct structure_type *st;
1144 st = define_structure_type (Qconcord_object,
1145 concord_object_validate,
1146 concord_object_instantiate);
1148 define_structure_type_keyword (st, Qgenre, concord_name_validate);
1149 define_structure_type_keyword (st, Q_id, concord_id_validate);
1153 vars_of_concord (void)
1155 Fprovide (Qconcord);
1157 staticpro (&Vconcord_ds_hash_table);
1158 Vconcord_ds_hash_table
1159 = make_lisp_hash_table (8, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
1161 staticpro (&Vconcord_genre_hash_table);
1162 Vconcord_genre_hash_table
1163 = make_lisp_hash_table (16, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
1165 staticpro (&Vconcord_genre_object_hash_table);
1166 Vconcord_genre_object_hash_table
1167 = make_lisp_hash_table (16, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
1171 complex_vars_of_concord (void)
1173 #ifdef HAVE_LIBCHISE
1174 Lisp_Object dir = build_string(chise_system_db_dir);
1176 Fconcord_assign_genre (Qcharacter, dir);
1177 Fconcord_assign_genre (Qfeature, dir);