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 ( UNBOUNDP (retval) )
268 retval = Vchise_system_db_directory;
269 if ( STRINGP (retval) )
271 retval = Fconcord_open_ds (retval, Qnil, Qnil, Qnil);
272 if ( !NILP (retval) )
273 Fputhash (genre, retval, Vconcord_genre_hash_table);
276 else if ( CONCORD_DS_P (retval) )
282 struct closure_to_list_feature
284 Lisp_Object feature_list;
285 } *concord_feature_list_closure;
288 add_feature_to_list_mapper (CONCORD_Genre genre, char* name)
290 /* This function can GC */
291 concord_feature_list_closure->feature_list
292 = Fcons (intern (name), concord_feature_list_closure->feature_list);
296 DEFUN ("concord-feature-list", Fconcord_feature_list, 1, 2, 0, /*
297 Return the list of all existing features in GENRE.
301 Lisp_CONCORD_DS* lds;
303 CONCORD_Genre c_genre;
306 CHECK_SYMBOL (genre);
308 ds = Fconcord_genre_ds (genre);
309 CHECK_CONCORD_DS (ds);
310 lds = XCONCORD_DS (ds);
313 genre = Fsymbol_name (genre);
314 TO_EXTERNAL_FORMAT (LISP_STRING, genre,
315 C_STRING_ALLOCA, genre_name,
317 c_genre = concord_ds_get_genre (lds->ds, genre_name);
320 concord_feature_list_closure
321 = alloca (sizeof (struct closure_to_list_feature));
322 concord_feature_list_closure->feature_list = Qnil;
323 GCPRO1 (concord_feature_list_closure->feature_list);
324 concord_genre_foreach_feature_name (c_genre,
325 add_feature_to_list_mapper);
327 return concord_feature_list_closure->feature_list;
331 typedef struct Lisp_CONCORD_Object Lisp_CONCORD_Object;
332 DECLARE_LRECORD (concord_object, Lisp_CONCORD_Object);
334 Lisp_Object Qconcord_objectp;
336 struct Lisp_CONCORD_Object
338 struct lcrecord_header header;
343 #define XCONCORD_OBJECT(x) XRECORD (x, concord_object, Lisp_CONCORD_Object)
344 #define XSET_CONCORD_OBJECT(x, p) XSETRECORD (x, p, concord_object)
345 #define CONCORD_OBJECT_P(x) RECORDP (x, concord_object)
346 #define CHECK_CONCORD_OBJECT(x) CHECK_RECORD (x, concord_object)
347 #define CONCHECK_CONCORD_OBJECT(x) CONCHECK_RECORD (x, concord_object)
348 #define CONCORD_OBJECT_GENRE(x) ((x)->genre)
349 #define CONCORD_OBJECT_ID(x) ((x)->id)
350 #define XCONCORD_OBJECT_ID(x) CONCORD_OBJECT_ID (XCONCORD_OBJECT(x))
351 #define XCONCORD_OBJECT_GENRE(x) CONCORD_OBJECT_GENRE (XCONCORD_OBJECT(x))
353 static Lisp_CONCORD_Object*
354 allocate_concord_object (void)
356 Lisp_CONCORD_Object* lcobj
357 = alloc_lcrecord_type (Lisp_CONCORD_Object, &lrecord_concord_object);
360 lcobj->id = Qunbound;
365 mark_concord_object (Lisp_Object object)
367 mark_object (XCONCORD_OBJECT_ID(object));
372 print_concord_object (Lisp_Object obj,
373 Lisp_Object printcharfun, int escapeflag)
375 Lisp_CONCORD_Object* lcobj = XCONCORD_OBJECT (obj);
376 struct gcpro gcpro1, gcpro2;
380 write_c_string ("#s(concord-object", printcharfun);
381 write_c_string (" genre ", printcharfun);
382 write_c_string (concord_genre_get_name (lcobj->genre), printcharfun);
383 write_c_string (" =id ", printcharfun);
384 GCPRO2 (obj, printcharfun);
385 print_internal (lcobj->id, printcharfun, escapeflag);
387 write_c_string (")", printcharfun);
391 write_c_string ("#<concord-object \"", printcharfun);
392 write_c_string (concord_ds_location
393 (concord_genre_get_data_source (lcobj->genre)),
395 write_c_string (":", printcharfun);
396 write_c_string (concord_genre_get_name (lcobj->genre), printcharfun);
397 write_c_string (";", printcharfun);
398 GCPRO2 (obj, printcharfun);
399 print_internal (lcobj->id, printcharfun, escapeflag);
401 write_c_string ("\">", printcharfun);
406 finalize_concord_object (void *header, int for_disksave)
408 Lisp_CONCORD_Object* lcobj = (Lisp_CONCORD_Object *) header;
413 XSET_CONCORD_OBJECT (object, lcobj);
416 ("Can't dump an emacs containing concord_object objects", object);
420 static const struct lrecord_description concord_object_description[] = {
421 { XD_LISP_OBJECT, offsetof (Lisp_CONCORD_Object, id) },
425 DEFINE_LRECORD_IMPLEMENTATION ("concord_object", concord_object,
426 mark_concord_object, print_concord_object,
427 finalize_concord_object, 0, 0,
428 concord_object_description,
429 Lisp_CONCORD_Object);
432 concord_genre_cache_get_object (Lisp_Object genre, Lisp_Object id)
434 Lisp_Object obj_hash;
436 obj_hash = Fgethash (genre, Vconcord_genre_object_hash_table, Qunbound);
437 if (UNBOUNDP (obj_hash))
439 return Fgethash (id, obj_hash, Qunbound);
443 concord_genre_cache_put_object (Lisp_Object genre, Lisp_Object id,
446 Lisp_Object obj_hash;
448 obj_hash = Fgethash (genre, Vconcord_genre_object_hash_table, Qunbound);
449 if (UNBOUNDP (obj_hash))
452 = make_lisp_hash_table (256, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
453 Fputhash (genre, obj_hash, Vconcord_genre_object_hash_table);
455 return Fputhash (id, object, obj_hash);
458 DEFUN ("concord-make-object", Fconcord_make_object, 1, 3, 0, /*
459 Make and return a Concord-object from ID and GENRE.
460 Optional argument DS specifies the data-source of the GENRE.
464 Lisp_CONCORD_DS* lds;
465 Lisp_Object genre_string;
466 char* genre_name_str;
467 CONCORD_Genre c_genre;
468 Lisp_CONCORD_Object* lcobj;
473 retval = concord_genre_cache_get_object (genre, id);
474 if (!UNBOUNDP (retval))
480 ds = Fconcord_genre_ds (genre);
481 CHECK_CONCORD_DS (ds);
482 lds = XCONCORD_DS (ds);
485 if ( STRINGP(genre) )
486 genre_string = genre;
488 genre_string = Fsymbol_name (genre);
489 TO_EXTERNAL_FORMAT (LISP_STRING, genre_string,
490 C_STRING_ALLOCA, genre_name_str,
492 c_genre = concord_ds_get_genre (lds->ds, genre_name_str);
495 lcobj = allocate_concord_object ();
496 lcobj->genre = c_genre;
498 XSET_CONCORD_OBJECT (retval, lcobj);
501 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
503 GCPRO4 (retval, id, genre, ds);
504 concord_genre_cache_put_object (genre, id, retval);
506 if (!EQ (Fconcord_object_get (retval, Q_id), id))
507 Fconcord_object_put (retval, Q_id, id);
514 DEFUN ("concord-object-p", Fconcord_object_p, 1, 1, 0, /*
515 Return t if OBJECT is a concord-object.
519 return CONCORD_OBJECT_P (object) ? Qt : Qnil;
522 DEFUN ("concord-object-id", Fconcord_object_id, 1, 1, 0, /*
523 Return an id of Concord-object OBJECT.
527 CHECK_CONCORD_OBJECT (object);
528 return XCONCORD_OBJECT_ID (object);
531 DEFUN ("concord-object-genre", Fconcord_object_genre, 1, 1, 0, /*
532 Return genre of Concord-object OBJECT.
536 CHECK_CONCORD_OBJECT (object);
537 return intern (concord_genre_get_name (XCONCORD_OBJECT_GENRE (object)));
540 DEFUN ("concord-decode-object", Fconcord_decode_object, 2, 4, 0, /*
541 Make and return a Concord-object from FEATURE and VALUE.
542 Optional argument GENRE specifies the GENRE of the object.
543 Optional argument DS specifies the data-source of the GENRE.
545 (feature, value, genre, ds))
547 Lisp_CONCORD_DS* lds;
549 CONCORD_Genre c_genre;
551 CONCORD_INDEX c_index;
552 Lisp_Object value_string;
554 CONCORD_String_Tank st_id;
557 int previous_print_readably;
558 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
561 ds = Fconcord_genre_ds (genre);
562 CHECK_CONCORD_DS (ds);
563 lds = XCONCORD_DS (ds);
566 if ( !STRINGP(feature) )
567 feature = Fsymbol_name (feature);
568 if ( !STRINGP(genre) )
569 genre = Fsymbol_name (genre);
570 TO_EXTERNAL_FORMAT (LISP_STRING, genre,
571 C_STRING_ALLOCA, genre_name,
573 c_genre = concord_ds_get_genre (lds->ds, genre_name);
579 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
580 C_STRING_ALLOCA, feature_name,
582 c_index = concord_genre_get_index (c_genre, feature_name);
588 previous_print_readably = print_readably;
590 GCPRO5 (feature, value, genre, ds, value_string);
591 value_string = Fprin1_to_string (value, Qnil);
593 print_readably = previous_print_readably;
594 TO_EXTERNAL_FORMAT (LISP_STRING,
595 value_string, C_STRING_ALLOCA, strid,
597 status = concord_index_strid_get_obj_string (c_index, strid, &st_id);
602 GCPRO4 (genre, ds, obj, retval);
604 obj = read_from_c_string (CONCORD_String_data (&st_id),
605 CONCORD_String_size (&st_id) );
607 obj = Fcar (Fread_from_string (make_ext_string
608 ((char*)CONCORD_String_data (&st_id),
609 CONCORD_String_size (&st_id),
613 retval = Fconcord_make_object (genre, obj, ds);
620 DEFUN ("concord-object-get", Fconcord_object_get, 2, 2, 0, /*
621 Return the value of OBJECT's FEATURE.
625 struct gcpro gcpro1, gcpro2;
626 int previous_print_readably;
627 Lisp_Object obj_string;
629 CONCORD_Genre c_genre;
631 CONCORD_Feature c_feature;
633 CONCORD_String_Tank st_value;
635 CHECK_CONCORD_OBJECT (object);
636 if ( !STRINGP(feature) )
637 feature = Fsymbol_name (feature);
638 previous_print_readably = print_readably;
640 GCPRO2 (object, feature);
641 obj_string = Fprin1_to_string (XCONCORD_OBJECT_ID(object), Qnil);
643 print_readably = previous_print_readably;
644 TO_EXTERNAL_FORMAT (LISP_STRING, obj_string,
645 C_STRING_ALLOCA, c_obj, Qfile_name);
646 c_genre = XCONCORD_OBJECT_GENRE(object);
647 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
648 C_STRING_ALLOCA, feature_name,
650 c_feature = concord_genre_get_feature (c_genre, feature_name);
651 if (c_feature == NULL)
655 status = concord_obj_get_feature_value_string (c_obj, c_feature,
660 Fcar (Fread_from_string (make_ext_string
661 ((char*)CONCORD_String_data (&st_value),
662 CONCORD_String_size (&st_value),
670 concord_object_put (Lisp_Object object, Lisp_Object feature,
673 struct gcpro gcpro1, gcpro2, gcpro3;
674 int previous_print_readably;
675 Lisp_Object obj_string;
677 CONCORD_Genre c_genre;
679 CONCORD_Feature c_feature;
681 Lisp_Object value_string;
684 if ( !STRINGP(feature) )
685 feature = Fsymbol_name (feature);
686 previous_print_readably = print_readably;
688 GCPRO3 (object, feature, value);
689 obj_string = Fprin1_to_string (XCONCORD_OBJECT_ID(object), Qnil);
691 print_readably = previous_print_readably;
692 TO_EXTERNAL_FORMAT (LISP_STRING, obj_string,
693 C_STRING_ALLOCA, c_obj, Qfile_name);
694 c_genre = XCONCORD_OBJECT_GENRE(object);
695 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
696 C_STRING_ALLOCA, feature_name,
698 c_feature = concord_genre_get_feature (c_genre, feature_name);
699 if (c_feature == NULL)
703 previous_print_readably = print_readably;
705 GCPRO3 (object, feature, value);
706 value_string = Fprin1_to_string (value, Qnil);
708 print_readably = previous_print_readably;
709 TO_EXTERNAL_FORMAT (LISP_STRING, value_string,
710 C_STRING_ALLOCA, c_value,
712 status = concord_obj_put_feature_value_str (c_obj, c_feature,
713 (unsigned char*)c_value);
716 status = chise_feature_sync (c_feature);
719 if (XSTRING_DATA(feature)[0] == '=')
721 CONCORD_INDEX c_index
722 = concord_genre_get_index (c_genre, feature_name);
724 concord_index_strid_put_obj (c_index, c_value, c_obj);
725 concord_index_sync (c_index);
730 DEFUN ("concord-object-put", Fconcord_object_put, 3, 3, 0, /*
731 Store a VALUE of OBJECT's FEATURE.
733 (object, feature, value))
738 CHECK_CONCORD_OBJECT (object);
739 CHECK_SYMBOL (feature);
740 name = symbol_name (XSYMBOL (feature));
741 name_str = string_data (name);
742 if ( NILP (concord_object_put (object, feature, value)) )
744 if ( EQ (feature, Q_subsumptive) ||
745 EQ (feature, Q_subsumptive_from) ||
746 EQ (feature, Q_denotational) ||
747 EQ (feature, Q_denotational_from) ||
748 ( ( ((name_str[0] == '-') && (name_str[1] == '>')) ||
749 ((name_str[0] == '<') && (name_str[1] == '-')) )
750 && (memchr (name_str, '*', name->size) == NULL) ) )
752 Lisp_Object rest = value;
754 Lisp_Object rev_feature = Qnil;
757 GCPRO1 (rev_feature);
758 if (EQ (feature, Q_subsumptive))
759 rev_feature = Q_subsumptive_from;
760 else if (EQ (feature, Q_subsumptive_from))
761 rev_feature = Q_subsumptive;
762 else if (EQ (feature, Q_denotational))
763 rev_feature = Q_denotational_from;
764 else if (EQ (feature, Q_denotational_from))
765 rev_feature = Q_denotational;
768 Bytecount length = string_length (name);
769 Bufbyte *rev_name_str = alloca (length + 1);
771 memcpy (rev_name_str + 2, name_str + 2, length - 2);
772 if (name_str[0] == '<')
774 rev_name_str[0] = '-';
775 rev_name_str[1] = '>';
779 rev_name_str[0] = '<';
780 rev_name_str[1] = '-';
782 rev_name_str[length] = 0;
783 rev_feature = intern (rev_name_str);
790 if ( CONCORD_OBJECT_P (ret) && !EQ (ret, object) )
794 ffv = Fconcord_object_get (ret, rev_feature);
796 concord_object_put (ret, rev_feature, list1 (object));
797 else if (NILP (Fmemq (object, ffv)))
800 nconc2 (Fcopy_sequence (ffv), list1 (object)));
810 struct closure_for_object_spec
814 } *concord_object_spec_closure;
817 add_feature_to_spec_mapper (CONCORD_Genre genre, char* name)
819 /* This function can GC */
820 CONCORD_String_Tank st_value;
821 CONCORD_Feature c_feature;
824 c_feature = concord_genre_get_feature (genre, name);
825 if (c_feature == NULL)
829 concord_obj_get_feature_value_string
830 (concord_object_spec_closure->object_id, c_feature, &st_value);
833 concord_object_spec_closure->spec
834 = Fcons (Fcons (intern (name),
835 Fcar (Fread_from_string
837 ((char*)CONCORD_String_data (&st_value),
838 CONCORD_String_size (&st_value),
841 concord_object_spec_closure->spec);
846 DEFUN ("concord-object-spec", Fconcord_object_spec, 1, 1, 0, /*
847 Return the spec of OBJECT.
851 Lisp_Object obj_string;
853 CONCORD_Genre c_genre;
854 struct gcpro gcpro1, gcpro2;
855 int previous_print_readably;
857 CHECK_CONCORD_OBJECT (object);
858 previous_print_readably = print_readably;
861 obj_string = Fprin1_to_string (XCONCORD_OBJECT_ID(object), Qnil);
863 print_readably = previous_print_readably;
864 TO_EXTERNAL_FORMAT (LISP_STRING, obj_string,
865 C_STRING_ALLOCA, c_obj, Qfile_name);
866 c_genre = XCONCORD_OBJECT_GENRE(object);
867 concord_object_spec_closure
868 = alloca (sizeof (struct closure_for_object_spec));
869 concord_object_spec_closure->object_id = c_obj;
870 concord_object_spec_closure->spec = Qnil;
871 GCPRO2 (object, concord_object_spec_closure->spec);
872 concord_genre_foreach_feature_name (c_genre,
873 add_feature_to_spec_mapper);
875 return concord_object_spec_closure->spec;
878 DEFUN ("concord-define-object", Fconcord_define_object, 2, 3, 0, /*
879 Define an object of which spec is a set of features SPEC.
883 Lisp_Object id = Fcdr (Fassq (Q_id, spec));
888 Lisp_Object rest = spec;
891 obj = Fconcord_make_object (genre, id, ds);
895 Fconcord_object_put (obj, Fcar (cell), Fcdr (cell));
903 struct closure_for_each_object
905 Lisp_Object function;
909 } *for_each_object_closure;
912 func_for_each_object (CONCORD_String object_id,
913 CONCORD_Feature feature,
914 CONCORD_String value)
916 struct gcpro gcpro1, gcpro2;
917 Lisp_Object obj, val, ret;
920 obj = read_from_c_string (CONCORD_String_data (object_id),
921 CONCORD_String_size (object_id) );
923 obj = Fcar (Fread_from_string (make_ext_string
924 ((char*)CONCORD_String_data (object_id),
925 CONCORD_String_size (object_id),
930 obj = Fconcord_make_object (for_each_object_closure->genre,
932 for_each_object_closure->ds);
934 val = read_from_c_string (CONCORD_String_data (value),
935 CONCORD_String_size (value) );
937 val = Fcar (Fread_from_string (make_ext_string
938 ((char*)CONCORD_String_data (value),
939 CONCORD_String_size (value),
945 ret = call2 (for_each_object_closure->function, obj, val);
947 for_each_object_closure->ret = ret;
951 DEFUN ("concord-for-each-object-in-feature",
952 Fconcord_foreach_object_in_feature, 2, 4, 0, /*
953 Do FUNCTION over objects in FEATURE, calling it with two args,
954 each key and value in the FEATURE table.
955 Optional argument GENRE specifies the genre of the FEATURE.
956 When the FUNCTION returns non-nil, it breaks the repeat.
958 (function, feature, genre, ds))
960 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
961 Lisp_CONCORD_DS* lds;
963 CONCORD_Genre c_genre;
965 CONCORD_Feature c_feature;
968 ds = Fconcord_genre_ds (genre);
969 CHECK_CONCORD_DS (ds);
970 lds = XCONCORD_DS (ds);
973 if ( !STRINGP(feature) )
974 feature = Fsymbol_name (feature);
975 if ( !STRINGP(genre) )
976 genre = Fsymbol_name (genre);
977 TO_EXTERNAL_FORMAT (LISP_STRING, genre,
978 C_STRING_ALLOCA, genre_name,
980 c_genre = concord_ds_get_genre (lds->ds, genre_name);
984 CHECK_STRING (feature);
985 TO_EXTERNAL_FORMAT (LISP_STRING, feature,
986 C_STRING_ALLOCA, feature_name,
988 c_feature = concord_genre_get_feature (c_genre, feature_name);
989 if (c_feature == NULL)
991 for_each_object_closure
992 = alloca (sizeof (struct closure_for_each_object));
993 for_each_object_closure->function = function;
994 for_each_object_closure->genre = genre;
995 for_each_object_closure->ds = ds;
996 for_each_object_closure->ret = Qnil;
997 GCPRO4 (for_each_object_closure->function,
998 for_each_object_closure->genre,
999 for_each_object_closure->ds,
1000 for_each_object_closure->ret);
1001 concord_feature_foreach_obj_string (c_feature, func_for_each_object);
1004 return for_each_object_closure->ret;
1009 concord_name_validate (Lisp_Object keyword, Lisp_Object value,
1010 Error_behavior errb)
1012 if (ERRB_EQ (errb, ERROR_ME))
1014 CHECK_SYMBOL (value);
1018 return SYMBOLP (value);
1022 concord_id_validate (Lisp_Object keyword, Lisp_Object value,
1023 Error_behavior errb)
1025 if (ERRB_EQ (errb, ERROR_ME))
1027 /* CHECK_SYMBOL (value); */
1028 if ( INTP (value) || CHARP (value) || SYMBOLP (value) )
1031 dead_wrong_type_argument (Qsymbolp, value);
1035 return INTP (value) || CHARP (value) || SYMBOLP (value);
1039 concord_object_validate (Lisp_Object data, Error_behavior errb)
1041 struct gcpro gcpro1, gcpro2, gcpro3;
1043 Lisp_Object valw = Qnil;
1044 Lisp_Object genre = Qnil;
1045 Lisp_Object oid = Qnil;
1047 data = Fcdr (data); /* skip over Qconcord_object */
1048 while (!NILP (data))
1050 Lisp_Object keyw = Fcar (data);
1055 if (EQ (keyw, Qgenre))
1057 else if (EQ (keyw, Q_id))
1065 maybe_error (Qconcord_object, errb, "No genre given");
1070 maybe_error (Qconcord_object, errb, "No object-id given");
1074 GCPRO3 (genre, oid, retval);
1075 retval = Fconcord_make_object (genre, oid, Qnil);
1079 maybe_signal_simple_error_2 ("No such Concord-object",
1080 oid, genre, Qconcord_object, errb);
1088 concord_object_instantiate (Lisp_Object data)
1090 struct gcpro gcpro1, gcpro2;
1093 GCPRO2 (data, retval);
1094 retval = Fconcord_make_object (Fplist_get (data, Qgenre, Qnil),
1095 Fplist_get (data, Q_id, Qnil),
1103 syms_of_concord (void)
1105 INIT_LRECORD_IMPLEMENTATION (concord_ds);
1106 INIT_LRECORD_IMPLEMENTATION (concord_object);
1108 defsymbol (&Qconcord, "concord");
1109 defsymbol (&Qconcord_dsp, "concord-dsp");
1110 defsymbol (&Qconcord_objectp, "concord-objectp");
1111 defsymbol (&Qconcord_object, "concord-object");
1112 defsymbol (&Qgenre, "genre");
1113 defsymbol (&Q_id, "=id");
1114 #ifdef HAVE_LIBCHISE
1115 defsymbol (&Qcharacter, "character");
1116 defsymbol (&Qfeature, "feature");
1119 DEFSUBR (Fconcord_open_ds);
1120 DEFSUBR (Fconcord_ds_p);
1121 DEFSUBR (Fconcord_close_ds);
1122 DEFSUBR (Fconcord_ds_directory);
1124 DEFSUBR (Fconcord_assign_genre);
1125 DEFSUBR (Fconcord_genre_directory);
1126 DEFSUBR (Fconcord_genre_ds);
1127 DEFSUBR (Fconcord_feature_list);
1129 DEFSUBR (Fconcord_make_object);
1130 DEFSUBR (Fconcord_object_p);
1131 DEFSUBR (Fconcord_object_id);
1132 DEFSUBR (Fconcord_object_genre);
1133 DEFSUBR (Fconcord_decode_object);
1134 DEFSUBR (Fconcord_object_get);
1135 DEFSUBR (Fconcord_object_put);
1136 DEFSUBR (Fconcord_define_object);
1137 DEFSUBR (Fconcord_object_spec);
1138 DEFSUBR (Fconcord_foreach_object_in_feature);
1142 structure_type_create_concord (void)
1144 struct structure_type *st;
1146 st = define_structure_type (Qconcord_object,
1147 concord_object_validate,
1148 concord_object_instantiate);
1150 define_structure_type_keyword (st, Qgenre, concord_name_validate);
1151 define_structure_type_keyword (st, Q_id, concord_id_validate);
1155 vars_of_concord (void)
1157 Fprovide (Qconcord);
1159 staticpro (&Vconcord_ds_hash_table);
1160 Vconcord_ds_hash_table
1161 = make_lisp_hash_table (8, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
1163 staticpro (&Vconcord_genre_hash_table);
1164 Vconcord_genre_hash_table
1165 = make_lisp_hash_table (16, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
1167 staticpro (&Vconcord_genre_object_hash_table);
1168 Vconcord_genre_object_hash_table
1169 = make_lisp_hash_table (16, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
1173 complex_vars_of_concord (void)
1175 #ifdef HAVE_LIBCHISE
1176 Fconcord_assign_genre (Qcharacter, Vchise_system_db_directory);
1177 Fconcord_assign_genre (Qfeature, Vchise_system_db_directory);