clipsruby 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/clipsruby/agenda.c +1373 -0
- data/ext/clipsruby/agenda.h +169 -0
- data/ext/clipsruby/analysis.c +1142 -0
- data/ext/clipsruby/analysis.h +61 -0
- data/ext/clipsruby/argacces.c +526 -0
- data/ext/clipsruby/argacces.h +77 -0
- data/ext/clipsruby/bload.c +884 -0
- data/ext/clipsruby/bload.h +94 -0
- data/ext/clipsruby/bmathfun.c +557 -0
- data/ext/clipsruby/bmathfun.h +66 -0
- data/ext/clipsruby/bsave.c +634 -0
- data/ext/clipsruby/bsave.h +130 -0
- data/ext/clipsruby/classcom.c +976 -0
- data/ext/clipsruby/classcom.h +115 -0
- data/ext/clipsruby/classexm.c +1376 -0
- data/ext/clipsruby/classexm.h +97 -0
- data/ext/clipsruby/classfun.c +1392 -0
- data/ext/clipsruby/classfun.h +164 -0
- data/ext/clipsruby/classinf.c +1245 -0
- data/ext/clipsruby/classinf.h +94 -0
- data/ext/clipsruby/classini.c +843 -0
- data/ext/clipsruby/classini.h +75 -0
- data/ext/clipsruby/classpsr.c +957 -0
- data/ext/clipsruby/classpsr.h +73 -0
- data/ext/clipsruby/clips.h +133 -0
- data/ext/clipsruby/clipsruby.c +619 -0
- data/ext/clipsruby/clsltpsr.c +931 -0
- data/ext/clipsruby/clsltpsr.h +72 -0
- data/ext/clipsruby/commline.c +1217 -0
- data/ext/clipsruby/commline.h +131 -0
- data/ext/clipsruby/conscomp.c +1593 -0
- data/ext/clipsruby/conscomp.h +150 -0
- data/ext/clipsruby/constant.h +264 -0
- data/ext/clipsruby/constrct.c +1090 -0
- data/ext/clipsruby/constrct.h +216 -0
- data/ext/clipsruby/constrnt.c +554 -0
- data/ext/clipsruby/constrnt.h +132 -0
- data/ext/clipsruby/crstrtgy.c +1088 -0
- data/ext/clipsruby/crstrtgy.h +85 -0
- data/ext/clipsruby/cstrcbin.c +185 -0
- data/ext/clipsruby/cstrcbin.h +61 -0
- data/ext/clipsruby/cstrccmp.h +43 -0
- data/ext/clipsruby/cstrccom.c +1791 -0
- data/ext/clipsruby/cstrccom.h +115 -0
- data/ext/clipsruby/cstrcpsr.c +835 -0
- data/ext/clipsruby/cstrcpsr.h +97 -0
- data/ext/clipsruby/cstrnbin.c +282 -0
- data/ext/clipsruby/cstrnbin.h +55 -0
- data/ext/clipsruby/cstrnchk.c +826 -0
- data/ext/clipsruby/cstrnchk.h +91 -0
- data/ext/clipsruby/cstrncmp.c +238 -0
- data/ext/clipsruby/cstrncmp.h +57 -0
- data/ext/clipsruby/cstrnops.c +1176 -0
- data/ext/clipsruby/cstrnops.h +47 -0
- data/ext/clipsruby/cstrnpsr.c +1394 -0
- data/ext/clipsruby/cstrnpsr.h +88 -0
- data/ext/clipsruby/cstrnutl.c +564 -0
- data/ext/clipsruby/cstrnutl.h +54 -0
- data/ext/clipsruby/default.c +454 -0
- data/ext/clipsruby/default.h +57 -0
- data/ext/clipsruby/defins.c +971 -0
- data/ext/clipsruby/defins.h +127 -0
- data/ext/clipsruby/developr.c +677 -0
- data/ext/clipsruby/developr.h +69 -0
- data/ext/clipsruby/dffctbin.c +477 -0
- data/ext/clipsruby/dffctbin.h +76 -0
- data/ext/clipsruby/dffctbsc.c +308 -0
- data/ext/clipsruby/dffctbsc.h +72 -0
- data/ext/clipsruby/dffctcmp.c +297 -0
- data/ext/clipsruby/dffctcmp.h +44 -0
- data/ext/clipsruby/dffctdef.c +364 -0
- data/ext/clipsruby/dffctdef.h +104 -0
- data/ext/clipsruby/dffctpsr.c +179 -0
- data/ext/clipsruby/dffctpsr.h +49 -0
- data/ext/clipsruby/dffnxbin.c +520 -0
- data/ext/clipsruby/dffnxbin.h +67 -0
- data/ext/clipsruby/dffnxcmp.c +378 -0
- data/ext/clipsruby/dffnxcmp.h +54 -0
- data/ext/clipsruby/dffnxexe.c +241 -0
- data/ext/clipsruby/dffnxexe.h +58 -0
- data/ext/clipsruby/dffnxfun.c +1192 -0
- data/ext/clipsruby/dffnxfun.h +155 -0
- data/ext/clipsruby/dffnxpsr.c +514 -0
- data/ext/clipsruby/dffnxpsr.h +57 -0
- data/ext/clipsruby/dfinsbin.c +509 -0
- data/ext/clipsruby/dfinsbin.h +66 -0
- data/ext/clipsruby/dfinscmp.c +345 -0
- data/ext/clipsruby/dfinscmp.h +48 -0
- data/ext/clipsruby/drive.c +1191 -0
- data/ext/clipsruby/drive.h +65 -0
- data/ext/clipsruby/emathfun.c +1213 -0
- data/ext/clipsruby/emathfun.h +99 -0
- data/ext/clipsruby/engine.c +1568 -0
- data/ext/clipsruby/engine.h +203 -0
- data/ext/clipsruby/entities.h +276 -0
- data/ext/clipsruby/envrnbld.c +514 -0
- data/ext/clipsruby/envrnbld.h +40 -0
- data/ext/clipsruby/envrnmnt.c +257 -0
- data/ext/clipsruby/envrnmnt.h +112 -0
- data/ext/clipsruby/evaluatn.c +1736 -0
- data/ext/clipsruby/evaluatn.h +211 -0
- data/ext/clipsruby/expressn.c +494 -0
- data/ext/clipsruby/expressn.h +154 -0
- data/ext/clipsruby/exprnbin.c +538 -0
- data/ext/clipsruby/exprnbin.h +60 -0
- data/ext/clipsruby/exprnops.c +564 -0
- data/ext/clipsruby/exprnops.h +67 -0
- data/ext/clipsruby/exprnpsr.c +1112 -0
- data/ext/clipsruby/exprnpsr.h +98 -0
- data/ext/clipsruby/extconf.rb +2 -0
- data/ext/clipsruby/extnfunc.c +1015 -0
- data/ext/clipsruby/extnfunc.h +157 -0
- data/ext/clipsruby/factbin.c +447 -0
- data/ext/clipsruby/factbin.h +56 -0
- data/ext/clipsruby/factbld.c +1035 -0
- data/ext/clipsruby/factbld.h +63 -0
- data/ext/clipsruby/factcmp.c +386 -0
- data/ext/clipsruby/factcmp.h +46 -0
- data/ext/clipsruby/factcom.c +759 -0
- data/ext/clipsruby/factcom.h +80 -0
- data/ext/clipsruby/factfile.c +1761 -0
- data/ext/clipsruby/factfile.h +54 -0
- data/ext/clipsruby/factfun.c +682 -0
- data/ext/clipsruby/factfun.h +77 -0
- data/ext/clipsruby/factgen.c +1305 -0
- data/ext/clipsruby/factgen.h +229 -0
- data/ext/clipsruby/facthsh.c +438 -0
- data/ext/clipsruby/facthsh.h +81 -0
- data/ext/clipsruby/factlhs.c +250 -0
- data/ext/clipsruby/factlhs.h +54 -0
- data/ext/clipsruby/factmch.c +905 -0
- data/ext/clipsruby/factmch.h +68 -0
- data/ext/clipsruby/factmngr.c +3373 -0
- data/ext/clipsruby/factmngr.h +325 -0
- data/ext/clipsruby/factprt.c +498 -0
- data/ext/clipsruby/factprt.h +60 -0
- data/ext/clipsruby/factqpsr.c +796 -0
- data/ext/clipsruby/factqpsr.h +61 -0
- data/ext/clipsruby/factqury.c +1267 -0
- data/ext/clipsruby/factqury.h +112 -0
- data/ext/clipsruby/factrete.c +978 -0
- data/ext/clipsruby/factrete.h +70 -0
- data/ext/clipsruby/factrhs.c +667 -0
- data/ext/clipsruby/factrhs.h +55 -0
- data/ext/clipsruby/filecom.c +353 -0
- data/ext/clipsruby/filecom.h +137 -0
- data/ext/clipsruby/filertr.c +481 -0
- data/ext/clipsruby/filertr.h +94 -0
- data/ext/clipsruby/fileutil.c +1020 -0
- data/ext/clipsruby/fileutil.h +50 -0
- data/ext/clipsruby/generate.c +1079 -0
- data/ext/clipsruby/generate.h +57 -0
- data/ext/clipsruby/genrcbin.c +902 -0
- data/ext/clipsruby/genrcbin.h +69 -0
- data/ext/clipsruby/genrccmp.c +640 -0
- data/ext/clipsruby/genrccmp.h +59 -0
- data/ext/clipsruby/genrccom.c +2017 -0
- data/ext/clipsruby/genrccom.h +119 -0
- data/ext/clipsruby/genrcexe.c +737 -0
- data/ext/clipsruby/genrcexe.h +73 -0
- data/ext/clipsruby/genrcfun.c +890 -0
- data/ext/clipsruby/genrcfun.h +185 -0
- data/ext/clipsruby/genrcpsr.c +1618 -0
- data/ext/clipsruby/genrcpsr.h +80 -0
- data/ext/clipsruby/globlbin.c +458 -0
- data/ext/clipsruby/globlbin.h +71 -0
- data/ext/clipsruby/globlbsc.c +361 -0
- data/ext/clipsruby/globlbsc.h +83 -0
- data/ext/clipsruby/globlcmp.c +330 -0
- data/ext/clipsruby/globlcmp.h +52 -0
- data/ext/clipsruby/globlcom.c +289 -0
- data/ext/clipsruby/globlcom.h +63 -0
- data/ext/clipsruby/globldef.c +1087 -0
- data/ext/clipsruby/globldef.h +151 -0
- data/ext/clipsruby/globlpsr.c +530 -0
- data/ext/clipsruby/globlpsr.h +59 -0
- data/ext/clipsruby/immthpsr.c +431 -0
- data/ext/clipsruby/immthpsr.h +55 -0
- data/ext/clipsruby/incrrset.c +530 -0
- data/ext/clipsruby/incrrset.h +73 -0
- data/ext/clipsruby/inherpsr.c +850 -0
- data/ext/clipsruby/inherpsr.h +52 -0
- data/ext/clipsruby/inscom.c +2076 -0
- data/ext/clipsruby/inscom.h +182 -0
- data/ext/clipsruby/insfile.c +1764 -0
- data/ext/clipsruby/insfile.h +96 -0
- data/ext/clipsruby/insfun.c +1451 -0
- data/ext/clipsruby/insfun.h +134 -0
- data/ext/clipsruby/insmngr.c +2550 -0
- data/ext/clipsruby/insmngr.h +125 -0
- data/ext/clipsruby/insmoddp.c +1041 -0
- data/ext/clipsruby/insmoddp.h +91 -0
- data/ext/clipsruby/insmult.c +804 -0
- data/ext/clipsruby/insmult.h +62 -0
- data/ext/clipsruby/inspsr.c +602 -0
- data/ext/clipsruby/inspsr.h +60 -0
- data/ext/clipsruby/insquery.c +1278 -0
- data/ext/clipsruby/insquery.h +115 -0
- data/ext/clipsruby/insqypsr.c +729 -0
- data/ext/clipsruby/insqypsr.h +63 -0
- data/ext/clipsruby/iofun.c +2045 -0
- data/ext/clipsruby/iofun.h +116 -0
- data/ext/clipsruby/lgcldpnd.c +644 -0
- data/ext/clipsruby/lgcldpnd.h +75 -0
- data/ext/clipsruby/main.c +112 -0
- data/ext/clipsruby/match.h +142 -0
- data/ext/clipsruby/memalloc.c +481 -0
- data/ext/clipsruby/memalloc.h +197 -0
- data/ext/clipsruby/miscfun.c +1801 -0
- data/ext/clipsruby/miscfun.h +132 -0
- data/ext/clipsruby/modulbin.c +607 -0
- data/ext/clipsruby/modulbin.h +84 -0
- data/ext/clipsruby/modulbsc.c +347 -0
- data/ext/clipsruby/modulbsc.h +67 -0
- data/ext/clipsruby/modulcmp.c +499 -0
- data/ext/clipsruby/modulcmp.h +54 -0
- data/ext/clipsruby/moduldef.c +817 -0
- data/ext/clipsruby/moduldef.h +271 -0
- data/ext/clipsruby/modulpsr.c +1150 -0
- data/ext/clipsruby/modulpsr.h +69 -0
- data/ext/clipsruby/modulutl.c +1036 -0
- data/ext/clipsruby/modulutl.h +84 -0
- data/ext/clipsruby/msgcom.c +1221 -0
- data/ext/clipsruby/msgcom.h +125 -0
- data/ext/clipsruby/msgfun.c +1076 -0
- data/ext/clipsruby/msgfun.h +118 -0
- data/ext/clipsruby/msgpass.c +1441 -0
- data/ext/clipsruby/msgpass.h +103 -0
- data/ext/clipsruby/msgpsr.c +698 -0
- data/ext/clipsruby/msgpsr.h +73 -0
- data/ext/clipsruby/multifld.c +1404 -0
- data/ext/clipsruby/multifld.h +130 -0
- data/ext/clipsruby/multifun.c +2182 -0
- data/ext/clipsruby/multifun.h +102 -0
- data/ext/clipsruby/network.h +142 -0
- data/ext/clipsruby/objbin.c +1522 -0
- data/ext/clipsruby/objbin.h +79 -0
- data/ext/clipsruby/objcmp.c +1507 -0
- data/ext/clipsruby/objcmp.h +71 -0
- data/ext/clipsruby/object.h +260 -0
- data/ext/clipsruby/objrtbin.c +701 -0
- data/ext/clipsruby/objrtbin.h +79 -0
- data/ext/clipsruby/objrtbld.c +2393 -0
- data/ext/clipsruby/objrtbld.h +66 -0
- data/ext/clipsruby/objrtcmp.c +734 -0
- data/ext/clipsruby/objrtcmp.h +66 -0
- data/ext/clipsruby/objrtfnx.c +1330 -0
- data/ext/clipsruby/objrtfnx.h +222 -0
- data/ext/clipsruby/objrtgen.c +736 -0
- data/ext/clipsruby/objrtgen.h +63 -0
- data/ext/clipsruby/objrtmch.c +1524 -0
- data/ext/clipsruby/objrtmch.h +160 -0
- data/ext/clipsruby/parsefun.c +415 -0
- data/ext/clipsruby/parsefun.h +67 -0
- data/ext/clipsruby/pattern.c +1265 -0
- data/ext/clipsruby/pattern.h +163 -0
- data/ext/clipsruby/pprint.c +328 -0
- data/ext/clipsruby/pprint.h +79 -0
- data/ext/clipsruby/prccode.c +1478 -0
- data/ext/clipsruby/prccode.h +145 -0
- data/ext/clipsruby/prcdrfun.c +640 -0
- data/ext/clipsruby/prcdrfun.h +95 -0
- data/ext/clipsruby/prcdrpsr.c +1068 -0
- data/ext/clipsruby/prcdrpsr.h +79 -0
- data/ext/clipsruby/prdctfun.c +869 -0
- data/ext/clipsruby/prdctfun.h +77 -0
- data/ext/clipsruby/prntutil.c +878 -0
- data/ext/clipsruby/prntutil.h +125 -0
- data/ext/clipsruby/proflfun.c +827 -0
- data/ext/clipsruby/proflfun.h +118 -0
- data/ext/clipsruby/reorder.c +2082 -0
- data/ext/clipsruby/reorder.h +172 -0
- data/ext/clipsruby/reteutil.c +1732 -0
- data/ext/clipsruby/reteutil.h +111 -0
- data/ext/clipsruby/retract.c +710 -0
- data/ext/clipsruby/retract.h +74 -0
- data/ext/clipsruby/router.c +737 -0
- data/ext/clipsruby/router.h +147 -0
- data/ext/clipsruby/rulebin.c +1136 -0
- data/ext/clipsruby/rulebin.h +153 -0
- data/ext/clipsruby/rulebld.c +1328 -0
- data/ext/clipsruby/rulebld.h +62 -0
- data/ext/clipsruby/rulebsc.c +517 -0
- data/ext/clipsruby/rulebsc.h +91 -0
- data/ext/clipsruby/rulecmp.c +733 -0
- data/ext/clipsruby/rulecmp.h +63 -0
- data/ext/clipsruby/rulecom.c +1583 -0
- data/ext/clipsruby/rulecom.h +116 -0
- data/ext/clipsruby/rulecstr.c +892 -0
- data/ext/clipsruby/rulecstr.h +53 -0
- data/ext/clipsruby/ruledef.c +559 -0
- data/ext/clipsruby/ruledef.h +179 -0
- data/ext/clipsruby/ruledlt.c +599 -0
- data/ext/clipsruby/ruledlt.h +58 -0
- data/ext/clipsruby/rulelhs.c +1216 -0
- data/ext/clipsruby/rulelhs.h +52 -0
- data/ext/clipsruby/rulepsr.c +1073 -0
- data/ext/clipsruby/rulepsr.h +61 -0
- data/ext/clipsruby/scanner.c +856 -0
- data/ext/clipsruby/scanner.h +112 -0
- data/ext/clipsruby/setup.h +488 -0
- data/ext/clipsruby/sortfun.c +433 -0
- data/ext/clipsruby/sortfun.h +55 -0
- data/ext/clipsruby/strngfun.c +1173 -0
- data/ext/clipsruby/strngfun.h +96 -0
- data/ext/clipsruby/strngrtr.c +523 -0
- data/ext/clipsruby/strngrtr.h +97 -0
- data/ext/clipsruby/symblbin.c +648 -0
- data/ext/clipsruby/symblbin.h +64 -0
- data/ext/clipsruby/symblcmp.c +893 -0
- data/ext/clipsruby/symblcmp.h +61 -0
- data/ext/clipsruby/symbol.c +1961 -0
- data/ext/clipsruby/symbol.h +243 -0
- data/ext/clipsruby/sysdep.c +894 -0
- data/ext/clipsruby/sysdep.h +164 -0
- data/ext/clipsruby/textpro.c +1388 -0
- data/ext/clipsruby/textpro.h +77 -0
- data/ext/clipsruby/tmpltbin.c +609 -0
- data/ext/clipsruby/tmpltbin.h +108 -0
- data/ext/clipsruby/tmpltbsc.c +327 -0
- data/ext/clipsruby/tmpltbsc.h +87 -0
- data/ext/clipsruby/tmpltcmp.c +450 -0
- data/ext/clipsruby/tmpltcmp.h +57 -0
- data/ext/clipsruby/tmpltdef.c +584 -0
- data/ext/clipsruby/tmpltdef.h +155 -0
- data/ext/clipsruby/tmpltfun.c +2477 -0
- data/ext/clipsruby/tmpltfun.h +122 -0
- data/ext/clipsruby/tmpltlhs.c +379 -0
- data/ext/clipsruby/tmpltlhs.h +50 -0
- data/ext/clipsruby/tmpltpsr.c +819 -0
- data/ext/clipsruby/tmpltpsr.h +59 -0
- data/ext/clipsruby/tmpltrhs.c +595 -0
- data/ext/clipsruby/tmpltrhs.h +55 -0
- data/ext/clipsruby/tmpltutl.c +637 -0
- data/ext/clipsruby/tmpltutl.h +82 -0
- data/ext/clipsruby/userdata.c +156 -0
- data/ext/clipsruby/userdata.h +72 -0
- data/ext/clipsruby/userfunctions.c +70 -0
- data/ext/clipsruby/usrsetup.h +7 -0
- data/ext/clipsruby/utility.c +1594 -0
- data/ext/clipsruby/utility.h +250 -0
- data/ext/clipsruby/watch.c +865 -0
- data/ext/clipsruby/watch.h +124 -0
- data/lib/clipsruby.rb +1 -0
- metadata +388 -0
@@ -0,0 +1,1076 @@
|
|
1
|
+
/*******************************************************/
|
2
|
+
/* "C" Language Integrated Production System */
|
3
|
+
/* */
|
4
|
+
/* CLIPS Version 6.40 06/22/18 */
|
5
|
+
/* */
|
6
|
+
/* OBJECT MESSAGE FUNCTIONS */
|
7
|
+
/*******************************************************/
|
8
|
+
|
9
|
+
/*************************************************************/
|
10
|
+
/* Purpose: */
|
11
|
+
/* */
|
12
|
+
/* Principal Programmer(s): */
|
13
|
+
/* Brian L. Dantes */
|
14
|
+
/* */
|
15
|
+
/* Contributing Programmer(s): */
|
16
|
+
/* */
|
17
|
+
/* Revision History: */
|
18
|
+
/* */
|
19
|
+
/* 6.23: Changed name of variable log to logName */
|
20
|
+
/* because of Unix compiler warnings of shadowed */
|
21
|
+
/* definitions. */
|
22
|
+
/* */
|
23
|
+
/* 6.24: Removed IMPERATIVE_MESSAGE_HANDLERS and */
|
24
|
+
/* AUXILIARY_MESSAGE_HANDLERS compilation flags. */
|
25
|
+
/* */
|
26
|
+
/* Renamed BOOLEAN macro type to intBool. */
|
27
|
+
/* */
|
28
|
+
/* 6.30: Support for long long integers. */
|
29
|
+
/* */
|
30
|
+
/* Changed integer type/precision. */
|
31
|
+
/* */
|
32
|
+
/* Added const qualifiers to remove C++ */
|
33
|
+
/* deprecation warnings. */
|
34
|
+
/* */
|
35
|
+
/* 6.40: Added Env prefix to GetEvaluationError and */
|
36
|
+
/* SetEvaluationError functions. */
|
37
|
+
/* */
|
38
|
+
/* Pragma once and other inclusion changes. */
|
39
|
+
/* */
|
40
|
+
/* Added support for booleans with <stdbool.h>. */
|
41
|
+
/* */
|
42
|
+
/* Removed use of void pointers for specific */
|
43
|
+
/* data structures. */
|
44
|
+
/* */
|
45
|
+
/* UDF redesign. */
|
46
|
+
/* */
|
47
|
+
/*************************************************************/
|
48
|
+
|
49
|
+
/* =========================================
|
50
|
+
*****************************************
|
51
|
+
EXTERNAL DEFINITIONS
|
52
|
+
=========================================
|
53
|
+
***************************************** */
|
54
|
+
#include "setup.h"
|
55
|
+
|
56
|
+
#if OBJECT_SYSTEM
|
57
|
+
|
58
|
+
#include "classcom.h"
|
59
|
+
#include "classfun.h"
|
60
|
+
#include "envrnmnt.h"
|
61
|
+
#include "extnfunc.h"
|
62
|
+
#include "inscom.h"
|
63
|
+
#include "insfun.h"
|
64
|
+
#include "memalloc.h"
|
65
|
+
#include "msgcom.h"
|
66
|
+
#include "prccode.h"
|
67
|
+
#include "prntutil.h"
|
68
|
+
#include "router.h"
|
69
|
+
|
70
|
+
#include "msgfun.h"
|
71
|
+
|
72
|
+
/***************************************/
|
73
|
+
/* LOCAL INTERNAL FUNCTION DEFINITIONS */
|
74
|
+
/***************************************/
|
75
|
+
|
76
|
+
#if DEBUGGING_FUNCTIONS
|
77
|
+
static HANDLER_LINK *DisplayPrimaryCore(Environment *,const char *,HANDLER_LINK *,int);
|
78
|
+
static void PrintPreviewHandler(Environment *,const char *,HANDLER_LINK *,int,const char *);
|
79
|
+
#endif
|
80
|
+
|
81
|
+
/* =========================================
|
82
|
+
*****************************************
|
83
|
+
EXTERNALLY VISIBLE FUNCTIONS
|
84
|
+
=========================================
|
85
|
+
***************************************** */
|
86
|
+
|
87
|
+
/********************************************************
|
88
|
+
NAME : UnboundHandlerErr
|
89
|
+
DESCRIPTION : Print out a synopis of the currently
|
90
|
+
executing handler for unbound variable
|
91
|
+
errors
|
92
|
+
INPUTS : None
|
93
|
+
RETURNS : Nothing useful
|
94
|
+
SIDE EFFECTS : Error synopsis printed to STDERR
|
95
|
+
NOTES : None
|
96
|
+
********************************************************/
|
97
|
+
void UnboundHandlerErr(
|
98
|
+
Environment *theEnv,
|
99
|
+
const char *logName)
|
100
|
+
{
|
101
|
+
WriteString(theEnv,logName,"message-handler ");
|
102
|
+
PrintHandler(theEnv,logName,MessageHandlerData(theEnv)->CurrentCore->hnd,true,true);
|
103
|
+
}
|
104
|
+
|
105
|
+
/*****************************************************************
|
106
|
+
NAME : PrintNoHandlerError
|
107
|
+
DESCRIPTION : Print "No primaries found" error message for send
|
108
|
+
INPUTS : The name of the message
|
109
|
+
RETURNS : Nothing useful
|
110
|
+
SIDE EFFECTS : None
|
111
|
+
NOTES : None
|
112
|
+
*****************************************************************/
|
113
|
+
void PrintNoHandlerError(
|
114
|
+
Environment *theEnv,
|
115
|
+
const char *msg)
|
116
|
+
{
|
117
|
+
PrintErrorID(theEnv,"MSGFUN",1,false);
|
118
|
+
WriteString(theEnv,STDERR,"No applicable primary message-handlers found for '");
|
119
|
+
WriteString(theEnv,STDERR,msg);
|
120
|
+
WriteString(theEnv,STDERR,"'.\n");
|
121
|
+
}
|
122
|
+
|
123
|
+
/***************************************************************
|
124
|
+
NAME : CheckHandlerArgCount
|
125
|
+
DESCRIPTION : Verifies that the current argument
|
126
|
+
list satisfies the current
|
127
|
+
handler's parameter count restriction
|
128
|
+
INPUTS : None
|
129
|
+
RETURNS : True if all OK, false otherwise
|
130
|
+
SIDE EFFECTS : EvaluationError set on errors
|
131
|
+
NOTES : Uses ProcParamArraySize and CurrentCore globals
|
132
|
+
***************************************************************/
|
133
|
+
bool CheckHandlerArgCount(
|
134
|
+
Environment *theEnv)
|
135
|
+
{
|
136
|
+
DefmessageHandler *hnd;
|
137
|
+
|
138
|
+
hnd = MessageHandlerData(theEnv)->CurrentCore->hnd;
|
139
|
+
if ((hnd->maxParams == PARAMETERS_UNBOUNDED) ?
|
140
|
+
(ProceduralPrimitiveData(theEnv)->ProcParamArraySize < hnd->minParams) : // TBD
|
141
|
+
(ProceduralPrimitiveData(theEnv)->ProcParamArraySize != hnd->minParams))
|
142
|
+
{
|
143
|
+
SetEvaluationError(theEnv,true);
|
144
|
+
PrintErrorID(theEnv,"MSGFUN",2,false);
|
145
|
+
WriteString(theEnv,STDERR,"Message-handler '");
|
146
|
+
WriteString(theEnv,STDERR,hnd->header.name->contents);
|
147
|
+
WriteString(theEnv,STDERR,"' ");
|
148
|
+
WriteString(theEnv,STDERR,MessageHandlerData(theEnv)->hndquals[hnd->type]);
|
149
|
+
WriteString(theEnv,STDERR," in class '");
|
150
|
+
WriteString(theEnv,STDERR,DefclassName(hnd->cls));
|
151
|
+
WriteString(theEnv,STDERR,"' expected ");
|
152
|
+
|
153
|
+
if (hnd->maxParams == PARAMETERS_UNBOUNDED)
|
154
|
+
WriteString(theEnv,STDERR,"at least ");
|
155
|
+
else
|
156
|
+
WriteString(theEnv,STDERR,"exactly ");
|
157
|
+
|
158
|
+
PrintUnsignedInteger(theEnv,STDERR,hnd->minParams-1);
|
159
|
+
if (hnd->minParams-1 == 1)
|
160
|
+
{ WriteString(theEnv,STDERR," argument.\n"); }
|
161
|
+
else
|
162
|
+
{ WriteString(theEnv,STDERR," arguments.\n"); }
|
163
|
+
|
164
|
+
return false;
|
165
|
+
}
|
166
|
+
return true;
|
167
|
+
}
|
168
|
+
|
169
|
+
/***************************************************
|
170
|
+
NAME : SlotAccessViolationError
|
171
|
+
DESCRIPTION : Prints out an error message when
|
172
|
+
attempt is made to set a read-only
|
173
|
+
or initialize-only slot improperly
|
174
|
+
INPUTS : 1) The slot name
|
175
|
+
2) A flag indicating if the source
|
176
|
+
is a class or an instance
|
177
|
+
3) A pointer to the source
|
178
|
+
instance/class
|
179
|
+
RETURNS : Nothing useful
|
180
|
+
SIDE EFFECTS : Error message printed
|
181
|
+
NOTES : None
|
182
|
+
***************************************************/
|
183
|
+
void SlotAccessViolationError(
|
184
|
+
Environment *theEnv,
|
185
|
+
const char *slotName,
|
186
|
+
Instance *theInstance,
|
187
|
+
Defclass *theDefclass)
|
188
|
+
{
|
189
|
+
PrintErrorID(theEnv,"MSGFUN",3,false);
|
190
|
+
WriteString(theEnv,STDERR,"Write access denied for slot '");
|
191
|
+
WriteString(theEnv,STDERR,slotName);
|
192
|
+
WriteString(theEnv,STDERR,"' in ");
|
193
|
+
if (theInstance != NULL)
|
194
|
+
{
|
195
|
+
WriteString(theEnv,STDERR,"instance ");
|
196
|
+
WriteString(theEnv,STDERR,"[");
|
197
|
+
WriteString(theEnv,STDERR,InstanceName(theInstance));
|
198
|
+
WriteString(theEnv,STDERR,"] of class ");
|
199
|
+
PrintClassName(theEnv,STDERR,theInstance->cls,true,false);
|
200
|
+
}
|
201
|
+
else
|
202
|
+
{
|
203
|
+
WriteString(theEnv,STDERR,"class ");
|
204
|
+
PrintClassName(theEnv,STDERR,theDefclass,true,false);
|
205
|
+
}
|
206
|
+
WriteString(theEnv,STDERR,".\n");
|
207
|
+
}
|
208
|
+
|
209
|
+
/***************************************************
|
210
|
+
NAME : SlotVisibilityViolationError
|
211
|
+
DESCRIPTION : Prints out an error message when
|
212
|
+
attempt is made to access a
|
213
|
+
private slot improperly
|
214
|
+
INPUTS : 1) The slot descriptor
|
215
|
+
2) A pointer to the source class
|
216
|
+
RETURNS : Nothing useful
|
217
|
+
SIDE EFFECTS : Error message printed
|
218
|
+
NOTES : None
|
219
|
+
***************************************************/
|
220
|
+
void SlotVisibilityViolationError(
|
221
|
+
Environment *theEnv,
|
222
|
+
SlotDescriptor *sd,
|
223
|
+
Defclass *theDefclass,
|
224
|
+
bool printCR)
|
225
|
+
{
|
226
|
+
PrintErrorID(theEnv,"MSGFUN",6,printCR);
|
227
|
+
WriteString(theEnv,STDERR,"Private slot '");
|
228
|
+
WriteString(theEnv,STDERR,sd->slotName->name->contents);
|
229
|
+
WriteString(theEnv,STDERR,"' of class ");
|
230
|
+
PrintClassName(theEnv,STDERR,sd->cls,true,false);
|
231
|
+
WriteString(theEnv,STDERR," cannot be accessed directly by handlers attached to class ");
|
232
|
+
PrintClassName(theEnv,STDERR,theDefclass,true,false);
|
233
|
+
WriteString(theEnv,STDERR,"\n");
|
234
|
+
}
|
235
|
+
|
236
|
+
#if ! RUN_TIME
|
237
|
+
|
238
|
+
/******************************************************************************
|
239
|
+
NAME : NewSystemHandler
|
240
|
+
DESCRIPTION : Adds a new system handler for a system class
|
241
|
+
|
242
|
+
The handler is assumed to be primary and of
|
243
|
+
the form:
|
244
|
+
|
245
|
+
(defmessage-handler <class> <handler> () (<func>))
|
246
|
+
|
247
|
+
INPUTS : 1) Name-string of the system class
|
248
|
+
2) Name-string of the system handler
|
249
|
+
3) Name-string of the internal H/L function to implement
|
250
|
+
this handler
|
251
|
+
4) The number of extra arguments (past the instance itself)
|
252
|
+
that the handler willl accept
|
253
|
+
RETURNS : Nothing useful
|
254
|
+
SIDE EFFECTS : Creates the new handler and inserts it in the system class's
|
255
|
+
handler array
|
256
|
+
On errors, generate a system error and exits.
|
257
|
+
NOTES : Does not check to see if handler already exists
|
258
|
+
*******************************************************************************/
|
259
|
+
void NewSystemHandler(
|
260
|
+
Environment *theEnv,
|
261
|
+
const char *cname,
|
262
|
+
const char *mname,
|
263
|
+
const char *fname,
|
264
|
+
unsigned short extraargs)
|
265
|
+
{
|
266
|
+
Defclass *cls;
|
267
|
+
DefmessageHandler *hnd;
|
268
|
+
|
269
|
+
cls = LookupDefclassInScope(theEnv,cname);
|
270
|
+
hnd = InsertHandlerHeader(theEnv,cls,CreateSymbol(theEnv,mname),MPRIMARY);
|
271
|
+
IncrementLexemeCount(hnd->header.name);
|
272
|
+
hnd->system = 1;
|
273
|
+
hnd->minParams = hnd->maxParams = extraargs + 1;
|
274
|
+
hnd->localVarCount = 0;
|
275
|
+
hnd->actions = get_struct(theEnv,expr);
|
276
|
+
hnd->actions->argList = NULL;
|
277
|
+
hnd->actions->type = FCALL;
|
278
|
+
hnd->actions->value = FindFunction(theEnv,fname);
|
279
|
+
hnd->actions->nextArg = NULL;
|
280
|
+
}
|
281
|
+
|
282
|
+
/***************************************************
|
283
|
+
NAME : InsertHandlerHeader
|
284
|
+
DESCRIPTION : Allocates a new handler header and
|
285
|
+
inserts it in the proper (sorted)
|
286
|
+
position in the class hnd array
|
287
|
+
INPUTS : 1) The class
|
288
|
+
2) The handler name
|
289
|
+
3) The handler type
|
290
|
+
RETURNS : The address of the new handler
|
291
|
+
header, NULL on errors
|
292
|
+
SIDE EFFECTS : Class handler array reallocated
|
293
|
+
and resorted
|
294
|
+
NOTES : Assumes handler does not exist
|
295
|
+
***************************************************/
|
296
|
+
DefmessageHandler *InsertHandlerHeader(
|
297
|
+
Environment *theEnv,
|
298
|
+
Defclass *cls,
|
299
|
+
CLIPSLexeme *mname,
|
300
|
+
unsigned mtype)
|
301
|
+
{
|
302
|
+
DefmessageHandler *nhnd,*hnd;
|
303
|
+
unsigned *narr,*arr;
|
304
|
+
long i;
|
305
|
+
long j,ni = -1;
|
306
|
+
|
307
|
+
hnd = cls->handlers;
|
308
|
+
arr = cls->handlerOrderMap;
|
309
|
+
nhnd = (DefmessageHandler *) gm2(theEnv,(sizeof(DefmessageHandler) * (cls->handlerCount+1)));
|
310
|
+
narr = (unsigned *) gm2(theEnv,(sizeof(unsigned) * (cls->handlerCount+1)));
|
311
|
+
GenCopyMemory(DefmessageHandler,cls->handlerCount,nhnd,hnd);
|
312
|
+
for (i = 0 , j = 0 ; i < cls->handlerCount ; i++ , j++)
|
313
|
+
{
|
314
|
+
if (ni == -1)
|
315
|
+
{
|
316
|
+
if ((hnd[arr[i]].header.name->bucket > mname->bucket) ? true :
|
317
|
+
(hnd[arr[i]].header.name == mname))
|
318
|
+
{
|
319
|
+
ni = i;
|
320
|
+
j++;
|
321
|
+
}
|
322
|
+
}
|
323
|
+
narr[j] = arr[i];
|
324
|
+
}
|
325
|
+
if (ni == -1)
|
326
|
+
ni = (int) cls->handlerCount;
|
327
|
+
narr[ni] = cls->handlerCount;
|
328
|
+
nhnd[cls->handlerCount].system = 0;
|
329
|
+
nhnd[cls->handlerCount].type = mtype;
|
330
|
+
nhnd[cls->handlerCount].busy = 0;
|
331
|
+
nhnd[cls->handlerCount].mark = 0;
|
332
|
+
#if DEBUGGING_FUNCTIONS
|
333
|
+
nhnd[cls->handlerCount].trace = MessageHandlerData(theEnv)->WatchHandlers;
|
334
|
+
#endif
|
335
|
+
nhnd[cls->handlerCount].header.name = mname;
|
336
|
+
nhnd[cls->handlerCount].header.whichModule = cls->header.whichModule;
|
337
|
+
nhnd[cls->handlerCount].header.next = NULL;
|
338
|
+
nhnd[cls->handlerCount].cls = cls;
|
339
|
+
nhnd[cls->handlerCount].minParams = 0;
|
340
|
+
nhnd[cls->handlerCount].maxParams = 0;
|
341
|
+
nhnd[cls->handlerCount].localVarCount = 0;
|
342
|
+
nhnd[cls->handlerCount].actions = NULL;
|
343
|
+
nhnd[cls->handlerCount].header.ppForm = NULL;
|
344
|
+
nhnd[cls->handlerCount].header.usrData = NULL;
|
345
|
+
nhnd[cls->handlerCount].header.constructType = DEFMESSAGE_HANDLER;
|
346
|
+
nhnd[cls->handlerCount].header.env = theEnv;
|
347
|
+
if (cls->handlerCount != 0)
|
348
|
+
{
|
349
|
+
rm(theEnv,hnd,(sizeof(DefmessageHandler) * cls->handlerCount));
|
350
|
+
rm(theEnv,arr,(sizeof(unsigned) * cls->handlerCount));
|
351
|
+
}
|
352
|
+
cls->handlers = nhnd;
|
353
|
+
cls->handlerOrderMap = narr;
|
354
|
+
cls->handlerCount++;
|
355
|
+
return(&nhnd[cls->handlerCount-1]);
|
356
|
+
}
|
357
|
+
|
358
|
+
#endif
|
359
|
+
|
360
|
+
#if (! BLOAD_ONLY) && (! RUN_TIME)
|
361
|
+
|
362
|
+
/*****************************************************
|
363
|
+
NAME : HandlersExecuting
|
364
|
+
DESCRIPTION : Determines if any message-handlers
|
365
|
+
for a class are currently executing
|
366
|
+
INPUTS : The class address
|
367
|
+
RETURNS : True if any handlers are executing,
|
368
|
+
false otherwise
|
369
|
+
SIDE EFFECTS : None
|
370
|
+
NOTES : None
|
371
|
+
*****************************************************/
|
372
|
+
bool HandlersExecuting(
|
373
|
+
Defclass *cls)
|
374
|
+
{
|
375
|
+
long i;
|
376
|
+
|
377
|
+
for (i = 0 ; i < cls->handlerCount ; i++)
|
378
|
+
if (cls->handlers[i].busy > 0)
|
379
|
+
return true;
|
380
|
+
return false;
|
381
|
+
}
|
382
|
+
|
383
|
+
/*********************************************************************
|
384
|
+
NAME : DeleteHandler
|
385
|
+
DESCRIPTION : Deletes one or more message-handlers
|
386
|
+
from a class definition
|
387
|
+
INPUTS : 1) The class address
|
388
|
+
2) The message-handler name
|
389
|
+
(if this is * and there is no handler
|
390
|
+
called *, then the delete operations
|
391
|
+
will be applied to all handlers matching the type
|
392
|
+
3) The message-handler type
|
393
|
+
(if this is -1, then the delete operations will be
|
394
|
+
applied to all handlers matching the name
|
395
|
+
4) A flag saying whether to print error messages when
|
396
|
+
handlers are not found meeting specs
|
397
|
+
RETURNS : 1 if successful, 0 otherwise
|
398
|
+
SIDE EFFECTS : Handlers deleted
|
399
|
+
NOTES : If any handlers for the class are
|
400
|
+
currently executing, this routine
|
401
|
+
will fail
|
402
|
+
**********************************************************************/
|
403
|
+
bool DeleteHandler(
|
404
|
+
Environment *theEnv,
|
405
|
+
Defclass *cls,
|
406
|
+
CLIPSLexeme *mname,
|
407
|
+
int mtype,
|
408
|
+
bool indicate_missing)
|
409
|
+
{
|
410
|
+
long i;
|
411
|
+
DefmessageHandler *hnd;
|
412
|
+
bool found,success = true;
|
413
|
+
|
414
|
+
if (cls->handlerCount == 0)
|
415
|
+
{
|
416
|
+
if (indicate_missing)
|
417
|
+
{
|
418
|
+
HandlerDeleteError(theEnv,DefclassName(cls));
|
419
|
+
return false;
|
420
|
+
}
|
421
|
+
return true;
|
422
|
+
}
|
423
|
+
if (HandlersExecuting(cls))
|
424
|
+
{
|
425
|
+
HandlerDeleteError(theEnv,DefclassName(cls));
|
426
|
+
return false;
|
427
|
+
}
|
428
|
+
if (mtype == -1)
|
429
|
+
{
|
430
|
+
found = false;
|
431
|
+
for (i = MAROUND ; i <= MAFTER ; i++)
|
432
|
+
{
|
433
|
+
hnd = FindHandlerByAddress(cls,mname,(unsigned) i);
|
434
|
+
if (hnd != NULL)
|
435
|
+
{
|
436
|
+
found = true;
|
437
|
+
if (hnd->system == 0)
|
438
|
+
hnd->mark = 1;
|
439
|
+
else
|
440
|
+
{
|
441
|
+
PrintErrorID(theEnv,"MSGPSR",3,false);
|
442
|
+
WriteString(theEnv,STDERR,"System message-handlers may not be modified.\n");
|
443
|
+
success = false;
|
444
|
+
}
|
445
|
+
}
|
446
|
+
}
|
447
|
+
if ((found == false) ? (strcmp(mname->contents,"*") == 0) : false)
|
448
|
+
{
|
449
|
+
for (i = 0 ; i < cls->handlerCount ; i++)
|
450
|
+
if (cls->handlers[i].system == 0)
|
451
|
+
cls->handlers[i].mark = 1;
|
452
|
+
}
|
453
|
+
}
|
454
|
+
else
|
455
|
+
{
|
456
|
+
hnd = FindHandlerByAddress(cls,mname,(unsigned) mtype);
|
457
|
+
if (hnd == NULL)
|
458
|
+
{
|
459
|
+
if (strcmp(mname->contents,"*") == 0)
|
460
|
+
{
|
461
|
+
for (i = 0 ; i < cls->handlerCount ; i++)
|
462
|
+
if ((cls->handlers[i].type == (unsigned) mtype) &&
|
463
|
+
(cls->handlers[i].system == 0))
|
464
|
+
cls->handlers[i].mark = 1;
|
465
|
+
}
|
466
|
+
else
|
467
|
+
{
|
468
|
+
if (indicate_missing)
|
469
|
+
HandlerDeleteError(theEnv,DefclassName(cls));
|
470
|
+
success = false;
|
471
|
+
}
|
472
|
+
}
|
473
|
+
else if (hnd->system == 0)
|
474
|
+
hnd->mark = 1;
|
475
|
+
else
|
476
|
+
{
|
477
|
+
if (indicate_missing)
|
478
|
+
{
|
479
|
+
PrintErrorID(theEnv,"MSGPSR",3,false);
|
480
|
+
WriteString(theEnv,STDERR,"System message-handlers may not be modified.\n");
|
481
|
+
}
|
482
|
+
success = false;
|
483
|
+
}
|
484
|
+
}
|
485
|
+
DeallocateMarkedHandlers(theEnv,cls);
|
486
|
+
return(success);
|
487
|
+
}
|
488
|
+
|
489
|
+
/***************************************************
|
490
|
+
NAME : DeallocateMarkedHandlers
|
491
|
+
DESCRIPTION : Removes any handlers from a class
|
492
|
+
that have been previously marked
|
493
|
+
for deletion.
|
494
|
+
INPUTS : The class
|
495
|
+
RETURNS : Nothing useful
|
496
|
+
SIDE EFFECTS : Marked handlers are deleted
|
497
|
+
NOTES : Assumes none of the handlers are
|
498
|
+
currently executing or have a
|
499
|
+
busy count != 0 for any reason
|
500
|
+
***************************************************/
|
501
|
+
void DeallocateMarkedHandlers(
|
502
|
+
Environment *theEnv,
|
503
|
+
Defclass *cls)
|
504
|
+
{
|
505
|
+
unsigned short count;
|
506
|
+
DefmessageHandler *hnd,*nhnd;
|
507
|
+
unsigned *arr,*narr;
|
508
|
+
long i,j;
|
509
|
+
|
510
|
+
for (i = 0 , count = 0 ; i < cls->handlerCount ; i++)
|
511
|
+
{
|
512
|
+
hnd = &cls->handlers[i];
|
513
|
+
if (hnd->mark == 1)
|
514
|
+
{
|
515
|
+
count++;
|
516
|
+
ReleaseLexeme(theEnv,hnd->header.name);
|
517
|
+
ExpressionDeinstall(theEnv,hnd->actions);
|
518
|
+
ReturnPackedExpression(theEnv,hnd->actions);
|
519
|
+
ClearUserDataList(theEnv,hnd->header.usrData);
|
520
|
+
if (hnd->header.ppForm != NULL)
|
521
|
+
rm(theEnv,(void *) hnd->header.ppForm,
|
522
|
+
(sizeof(char) * (strlen(hnd->header.ppForm)+1)));
|
523
|
+
}
|
524
|
+
else
|
525
|
+
/* ============================================
|
526
|
+
Use the busy field to count how many
|
527
|
+
message-handlers are removed before this one
|
528
|
+
============================================ */
|
529
|
+
hnd->busy = count;
|
530
|
+
}
|
531
|
+
if (count == 0)
|
532
|
+
return;
|
533
|
+
if (count == cls->handlerCount)
|
534
|
+
{
|
535
|
+
rm(theEnv,cls->handlers,(sizeof(DefmessageHandler) * cls->handlerCount));
|
536
|
+
rm(theEnv,cls->handlerOrderMap,(sizeof(unsigned) * cls->handlerCount));
|
537
|
+
cls->handlers = NULL;
|
538
|
+
cls->handlerOrderMap = NULL;
|
539
|
+
cls->handlerCount = 0;
|
540
|
+
}
|
541
|
+
else
|
542
|
+
{
|
543
|
+
count = (cls->handlerCount - count);
|
544
|
+
hnd = cls->handlers;
|
545
|
+
arr = cls->handlerOrderMap;
|
546
|
+
nhnd = (DefmessageHandler *) gm2(theEnv,(sizeof(DefmessageHandler) * count));
|
547
|
+
narr = (unsigned *) gm2(theEnv,(sizeof(unsigned) * count));
|
548
|
+
for (i = 0 , j = 0 ; j < count ; i++)
|
549
|
+
{
|
550
|
+
if (hnd[arr[i]].mark == 0)
|
551
|
+
{
|
552
|
+
/* ==============================================================
|
553
|
+
The offsets in the map need to be decremented by the number of
|
554
|
+
preceding nodes which were deleted. Use the value of the busy
|
555
|
+
field set in the first loop.
|
556
|
+
============================================================== */
|
557
|
+
narr[j] = arr[i] - hnd[arr[i]].busy;
|
558
|
+
j++;
|
559
|
+
}
|
560
|
+
}
|
561
|
+
for (i = 0 , j = 0 ; j < count ; i++)
|
562
|
+
{
|
563
|
+
if (hnd[i].mark == 0)
|
564
|
+
{
|
565
|
+
hnd[i].busy = 0;
|
566
|
+
GenCopyMemory(DefmessageHandler,1,&nhnd[j],&hnd[i]);
|
567
|
+
j++;
|
568
|
+
}
|
569
|
+
}
|
570
|
+
rm(theEnv,hnd,(sizeof(DefmessageHandler) * cls->handlerCount));
|
571
|
+
rm(theEnv,arr,(sizeof(unsigned) * cls->handlerCount));
|
572
|
+
cls->handlers = nhnd;
|
573
|
+
cls->handlerOrderMap = narr;
|
574
|
+
cls->handlerCount = count;
|
575
|
+
}
|
576
|
+
}
|
577
|
+
|
578
|
+
#endif
|
579
|
+
|
580
|
+
/*****************************************************
|
581
|
+
NAME : HandlerType
|
582
|
+
DESCRIPTION : Determines type of message-handler
|
583
|
+
INPUTS : 1) Calling function string
|
584
|
+
2) String representing type
|
585
|
+
RETURNS : MAROUND (0) for "around"
|
586
|
+
MBEFORE (1) for "before"
|
587
|
+
MPRIMARY (2) for "primary"
|
588
|
+
MAFTER (3) for "after"
|
589
|
+
MERROR (4) on errors
|
590
|
+
SIDE EFFECTS : None
|
591
|
+
NOTES : None
|
592
|
+
*****************************************************/
|
593
|
+
unsigned short HandlerType(
|
594
|
+
Environment *theEnv,
|
595
|
+
const char *where,
|
596
|
+
bool whereIsFunction,
|
597
|
+
const char *str)
|
598
|
+
{
|
599
|
+
unsigned short i;
|
600
|
+
|
601
|
+
for (i = MAROUND ; i <= MAFTER ; i++)
|
602
|
+
{
|
603
|
+
if (strcmp(str,MessageHandlerData(theEnv)->hndquals[i]) == 0)
|
604
|
+
{ return i; }
|
605
|
+
}
|
606
|
+
|
607
|
+
PrintErrorID(theEnv,"MSGFUN",7,false);
|
608
|
+
WriteString(theEnv,STDERR,"Unrecognized message-handler type in ");
|
609
|
+
if (whereIsFunction)
|
610
|
+
{
|
611
|
+
WriteString(theEnv,STDERR,"function '");
|
612
|
+
WriteString(theEnv,STDERR,where);
|
613
|
+
WriteString(theEnv,STDERR,"'.");
|
614
|
+
}
|
615
|
+
else
|
616
|
+
{ WriteString(theEnv,STDERR,where); }
|
617
|
+
|
618
|
+
WriteString(theEnv,STDERR,".\n");
|
619
|
+
|
620
|
+
return(MERROR);
|
621
|
+
}
|
622
|
+
|
623
|
+
/*****************************************************************
|
624
|
+
NAME : CheckCurrentMessage
|
625
|
+
DESCRIPTION : Makes sure that a message is available
|
626
|
+
and active for an internal message function
|
627
|
+
INPUTS : 1) The name of the function checking the message
|
628
|
+
2) A flag indicating whether the object must be
|
629
|
+
a class instance or not (it could be a
|
630
|
+
primitive type)
|
631
|
+
RETURNS : True if all OK, false otherwise
|
632
|
+
SIDE EFFECTS : EvaluationError set on errors
|
633
|
+
NOTES : None
|
634
|
+
*****************************************************************/
|
635
|
+
bool CheckCurrentMessage(
|
636
|
+
Environment *theEnv,
|
637
|
+
const char *func,
|
638
|
+
bool ins_reqd)
|
639
|
+
{
|
640
|
+
UDFValue *activeMsgArg;
|
641
|
+
|
642
|
+
if (!MessageHandlerData(theEnv)->CurrentCore || (MessageHandlerData(theEnv)->CurrentCore->hnd->actions != ProceduralPrimitiveData(theEnv)->CurrentProcActions))
|
643
|
+
{
|
644
|
+
PrintErrorID(theEnv,"MSGFUN",4,false);
|
645
|
+
WriteString(theEnv,STDERR,"The function '");
|
646
|
+
WriteString(theEnv,STDERR,func);
|
647
|
+
WriteString(theEnv,STDERR,"' may only be called from within message-handlers.\n");
|
648
|
+
SetEvaluationError(theEnv,true);
|
649
|
+
return false;
|
650
|
+
}
|
651
|
+
activeMsgArg = GetNthMessageArgument(theEnv,0);
|
652
|
+
if ((ins_reqd == true) ? (activeMsgArg->header->type != INSTANCE_ADDRESS_TYPE) : false)
|
653
|
+
{
|
654
|
+
PrintErrorID(theEnv,"MSGFUN",5,false);
|
655
|
+
WriteString(theEnv,STDERR,"The function '");
|
656
|
+
WriteString(theEnv,STDERR,func);
|
657
|
+
WriteString(theEnv,STDERR,"' operates only on instances.\n");
|
658
|
+
SetEvaluationError(theEnv,true);
|
659
|
+
return false;
|
660
|
+
}
|
661
|
+
if ((activeMsgArg->header->type == INSTANCE_ADDRESS_TYPE) ?
|
662
|
+
(activeMsgArg->instanceValue->garbage == 1) : false)
|
663
|
+
{
|
664
|
+
StaleInstanceAddress(theEnv,func,0);
|
665
|
+
SetEvaluationError(theEnv,true);
|
666
|
+
return false;
|
667
|
+
}
|
668
|
+
return true;
|
669
|
+
}
|
670
|
+
|
671
|
+
/***************************************************
|
672
|
+
NAME : PrintHandler
|
673
|
+
DESCRIPTION : Displays a handler synopsis
|
674
|
+
INPUTS : 1) Logical name of output
|
675
|
+
2) The handler
|
676
|
+
5) Flag indicating whether to
|
677
|
+
printout a terminating newline
|
678
|
+
RETURNS : Nothing useful
|
679
|
+
SIDE EFFECTS : None
|
680
|
+
NOTES : None
|
681
|
+
***************************************************/
|
682
|
+
void PrintHandler(
|
683
|
+
Environment *theEnv,
|
684
|
+
const char *logName,
|
685
|
+
DefmessageHandler *theHandler,
|
686
|
+
bool useQuotes,
|
687
|
+
bool crtn)
|
688
|
+
{
|
689
|
+
if (useQuotes) WriteString(theEnv,logName,"'");
|
690
|
+
WriteString(theEnv,logName,theHandler->header.name->contents);
|
691
|
+
if (useQuotes) WriteString(theEnv,logName,"'");
|
692
|
+
WriteString(theEnv,logName," ");
|
693
|
+
WriteString(theEnv,logName,MessageHandlerData(theEnv)->hndquals[theHandler->type]);
|
694
|
+
WriteString(theEnv,logName," in class ");
|
695
|
+
PrintClassName(theEnv,logName,theHandler->cls,useQuotes,crtn);
|
696
|
+
}
|
697
|
+
|
698
|
+
/***********************************************************
|
699
|
+
NAME : FindHandlerByAddress
|
700
|
+
DESCRIPTION : Uses a binary search on a class's
|
701
|
+
handler header array
|
702
|
+
INPUTS : 1) The class address
|
703
|
+
2) The handler symbolic name
|
704
|
+
3) The handler type (MPRIMARY,etc.)
|
705
|
+
RETURNS : The address of the found handler,
|
706
|
+
NULL if not found
|
707
|
+
SIDE EFFECTS : None
|
708
|
+
NOTES : Assumes array is in ascending order
|
709
|
+
1st key: symbolic name of handler
|
710
|
+
2nd key: type of handler
|
711
|
+
***********************************************************/
|
712
|
+
DefmessageHandler *FindHandlerByAddress(
|
713
|
+
Defclass *cls,
|
714
|
+
CLIPSLexeme *name,
|
715
|
+
unsigned type)
|
716
|
+
{
|
717
|
+
int b;
|
718
|
+
long i;
|
719
|
+
DefmessageHandler *hnd;
|
720
|
+
unsigned *arr;
|
721
|
+
|
722
|
+
if ((b = FindHandlerNameGroup(cls,name)) == -1)
|
723
|
+
return NULL;
|
724
|
+
arr = cls->handlerOrderMap;
|
725
|
+
hnd = cls->handlers;
|
726
|
+
for (i = (unsigned) b ; i < cls->handlerCount ; i++)
|
727
|
+
{
|
728
|
+
if (hnd[arr[i]].header.name != name)
|
729
|
+
return NULL;
|
730
|
+
if (hnd[arr[i]].type == type)
|
731
|
+
return(&hnd[arr[i]]);
|
732
|
+
}
|
733
|
+
return NULL;
|
734
|
+
}
|
735
|
+
|
736
|
+
/***********************************************************
|
737
|
+
NAME : FindHandlerByIndex
|
738
|
+
DESCRIPTION : Uses a binary search on a class's
|
739
|
+
handler header array
|
740
|
+
INPUTS : 1) The class address
|
741
|
+
2) The handler symbolic name
|
742
|
+
3) The handler type (MPRIMARY,etc.)
|
743
|
+
RETURNS : The index of the found handler,
|
744
|
+
-1 if not found
|
745
|
+
SIDE EFFECTS : None
|
746
|
+
NOTES : Assumes array is in ascending order
|
747
|
+
1st key: symbolic name of handler
|
748
|
+
2nd key: type of handler
|
749
|
+
***********************************************************/
|
750
|
+
int FindHandlerByIndex(
|
751
|
+
Defclass *cls,
|
752
|
+
CLIPSLexeme *name,
|
753
|
+
unsigned type)
|
754
|
+
{
|
755
|
+
int b;
|
756
|
+
long i;
|
757
|
+
DefmessageHandler *hnd;
|
758
|
+
unsigned *arr;
|
759
|
+
|
760
|
+
if ((b = FindHandlerNameGroup(cls,name)) == -1)
|
761
|
+
return -1;
|
762
|
+
arr = cls->handlerOrderMap;
|
763
|
+
hnd = cls->handlers;
|
764
|
+
for (i = (unsigned) b ; i < cls->handlerCount ; i++)
|
765
|
+
{
|
766
|
+
if (hnd[arr[i]].header.name != name)
|
767
|
+
return -1;
|
768
|
+
if (hnd[arr[i]].type == type)
|
769
|
+
return (int) arr[i];
|
770
|
+
}
|
771
|
+
return -1;
|
772
|
+
}
|
773
|
+
|
774
|
+
/*****************************************************
|
775
|
+
NAME : FindHandlerNameGroup
|
776
|
+
DESCRIPTION : Uses a binary search on a class's
|
777
|
+
handler header array
|
778
|
+
INPUTS : 1) The class address
|
779
|
+
2) The handler symbolic name
|
780
|
+
RETURNS : The index of the found handler group
|
781
|
+
-1 if not found
|
782
|
+
SIDE EFFECTS : None
|
783
|
+
NOTES : Assumes array is in ascending order
|
784
|
+
1st key: handler name symbol bucket
|
785
|
+
*****************************************************/
|
786
|
+
int FindHandlerNameGroup(
|
787
|
+
Defclass *cls,
|
788
|
+
CLIPSLexeme *name)
|
789
|
+
{
|
790
|
+
int b,e,i,j;
|
791
|
+
DefmessageHandler *hnd;
|
792
|
+
unsigned *arr;
|
793
|
+
int start;
|
794
|
+
|
795
|
+
if (cls->handlerCount == 0)
|
796
|
+
return(-1);
|
797
|
+
hnd = cls->handlers;
|
798
|
+
arr = cls->handlerOrderMap;
|
799
|
+
b = 0;
|
800
|
+
e = (int) (cls->handlerCount-1);
|
801
|
+
start = -1;
|
802
|
+
do
|
803
|
+
{
|
804
|
+
i = (b+e)/2;
|
805
|
+
if (name->bucket == hnd[arr[i]].header.name->bucket)
|
806
|
+
{
|
807
|
+
for (j = i ; j >= b ; j--)
|
808
|
+
{
|
809
|
+
if (hnd[arr[j]].header.name == name)
|
810
|
+
start = j;
|
811
|
+
if (hnd[arr[j]].header.name->bucket != name->bucket)
|
812
|
+
break;
|
813
|
+
}
|
814
|
+
if (start != -1)
|
815
|
+
return(start);
|
816
|
+
for (j = i+1 ; j <= e ; j++)
|
817
|
+
{
|
818
|
+
if (hnd[arr[j]].header.name == name)
|
819
|
+
return(j);
|
820
|
+
if (hnd[arr[j]].header.name->bucket != name->bucket)
|
821
|
+
return(-1);
|
822
|
+
}
|
823
|
+
return(-1);
|
824
|
+
}
|
825
|
+
else if (name->bucket < hnd[arr[i]].header.name->bucket)
|
826
|
+
e = i-1;
|
827
|
+
else
|
828
|
+
b = i+1;
|
829
|
+
}
|
830
|
+
while (b <= e);
|
831
|
+
return(-1);
|
832
|
+
}
|
833
|
+
|
834
|
+
/***************************************************
|
835
|
+
NAME : HandlerDeleteError
|
836
|
+
DESCRIPTION : Prints out an error message when
|
837
|
+
handlers cannot be deleted
|
838
|
+
INPUTS : Name-string of the class
|
839
|
+
RETURNS : Nothing useful
|
840
|
+
SIDE EFFECTS : None
|
841
|
+
NOTES : None
|
842
|
+
***************************************************/
|
843
|
+
void HandlerDeleteError(
|
844
|
+
Environment *theEnv,
|
845
|
+
const char *cname)
|
846
|
+
{
|
847
|
+
PrintErrorID(theEnv,"MSGFUN",8,false);
|
848
|
+
WriteString(theEnv,STDERR,"Unable to delete message-handler(s) from class '");
|
849
|
+
WriteString(theEnv,STDERR,cname);
|
850
|
+
WriteString(theEnv,STDERR,"'.\n");
|
851
|
+
}
|
852
|
+
|
853
|
+
#if DEBUGGING_FUNCTIONS
|
854
|
+
|
855
|
+
/********************************************************************
|
856
|
+
NAME : DisplayCore
|
857
|
+
DESCRIPTION : Gives a schematic "printout" of the
|
858
|
+
core framework for a message showing
|
859
|
+
arounds, primaries, shadows etc.
|
860
|
+
This routine uses recursion to print indentation
|
861
|
+
to indicate shadowing and where handlers begin
|
862
|
+
and end execution wrt one another.
|
863
|
+
INPUTS : 1) Logical name of output
|
864
|
+
2) The remaining core
|
865
|
+
3) The number of handlers this (partial) core
|
866
|
+
shadows
|
867
|
+
RETURNS : Nothing useful
|
868
|
+
SIDE EFFECTS : None
|
869
|
+
NOTES : Expects that the core was created in PREVIEW mode,
|
870
|
+
i.e. implicit handlers are SlotDescriptor addresses
|
871
|
+
(in PERFORM mode they are INSTANCE_SLOT addresses)
|
872
|
+
Assumes (partial) core is not empty
|
873
|
+
********************************************************************/
|
874
|
+
void DisplayCore(
|
875
|
+
Environment *theEnv,
|
876
|
+
const char *logicalName,
|
877
|
+
HANDLER_LINK *core,
|
878
|
+
int sdepth)
|
879
|
+
{
|
880
|
+
if (core->hnd->type == MAROUND)
|
881
|
+
{
|
882
|
+
PrintPreviewHandler(theEnv,logicalName,core,sdepth,BEGIN_TRACE);
|
883
|
+
if (core->nxt != NULL)
|
884
|
+
DisplayCore(theEnv,logicalName,core->nxt,sdepth+1);
|
885
|
+
PrintPreviewHandler(theEnv,logicalName,core,sdepth,END_TRACE);
|
886
|
+
}
|
887
|
+
else
|
888
|
+
{
|
889
|
+
while ((core != NULL) ? (core->hnd->type == MBEFORE) : false)
|
890
|
+
{
|
891
|
+
PrintPreviewHandler(theEnv,logicalName,core,sdepth,BEGIN_TRACE);
|
892
|
+
PrintPreviewHandler(theEnv,logicalName,core,sdepth,END_TRACE);
|
893
|
+
core = core->nxt;
|
894
|
+
}
|
895
|
+
if ((core != NULL) ? (core->hnd->type == MPRIMARY) : false)
|
896
|
+
|
897
|
+
core = DisplayPrimaryCore(theEnv,logicalName,core,sdepth);
|
898
|
+
|
899
|
+
while ((core != NULL) ? (core->hnd->type == MAFTER) : false)
|
900
|
+
{
|
901
|
+
PrintPreviewHandler(theEnv,logicalName,core,sdepth,BEGIN_TRACE);
|
902
|
+
PrintPreviewHandler(theEnv,logicalName,core,sdepth,END_TRACE);
|
903
|
+
core = core->nxt;
|
904
|
+
}
|
905
|
+
|
906
|
+
}
|
907
|
+
}
|
908
|
+
|
909
|
+
/*******************************************************************
|
910
|
+
NAME : FindPreviewApplicableHandlers
|
911
|
+
DESCRIPTION : See FindApplicableHandlers
|
912
|
+
However, this function only examines classes rather
|
913
|
+
than instances for implicit slot-accessors
|
914
|
+
INPUTS : 1) The class address
|
915
|
+
2) The message name symbol
|
916
|
+
RETURNS : The links of applicable handlers, NULL on errors
|
917
|
+
SIDE EFFECTS : Links are allocated for the list
|
918
|
+
NOTES : None
|
919
|
+
******************************************************************/
|
920
|
+
HANDLER_LINK *FindPreviewApplicableHandlers(
|
921
|
+
Environment *theEnv,
|
922
|
+
Defclass *cls,
|
923
|
+
CLIPSLexeme *mname)
|
924
|
+
{
|
925
|
+
unsigned int i;
|
926
|
+
HANDLER_LINK *tops[4],*bots[4];
|
927
|
+
|
928
|
+
for (i = MAROUND ; i <= MAFTER ; i++)
|
929
|
+
tops[i] = bots[i] = NULL;
|
930
|
+
|
931
|
+
for (i = 0 ; i < cls->allSuperclasses.classCount ; i++)
|
932
|
+
FindApplicableOfName(theEnv,cls->allSuperclasses.classArray[i],tops,bots,mname);
|
933
|
+
|
934
|
+
return JoinHandlerLinks(theEnv,tops,bots,mname);
|
935
|
+
}
|
936
|
+
|
937
|
+
/***********************************************************
|
938
|
+
NAME : WatchMessage
|
939
|
+
DESCRIPTION : Prints a condensed description of a
|
940
|
+
message and its arguments
|
941
|
+
INPUTS : 1) The output logical name
|
942
|
+
2) BEGIN_TRACE or END_TRACE string
|
943
|
+
RETURNS : Nothing useful
|
944
|
+
SIDE EFFECTS : None
|
945
|
+
NOTES : Uses the global variables ProcParamArray
|
946
|
+
and CurrentMessageName
|
947
|
+
***********************************************************/
|
948
|
+
void WatchMessage(
|
949
|
+
Environment *theEnv,
|
950
|
+
const char *logName,
|
951
|
+
const char *tstring)
|
952
|
+
{
|
953
|
+
if (ConstructData(theEnv)->ClearReadyInProgress ||
|
954
|
+
ConstructData(theEnv)->ClearInProgress)
|
955
|
+
{ return; }
|
956
|
+
|
957
|
+
WriteString(theEnv,logName,"MSG ");
|
958
|
+
WriteString(theEnv,logName,tstring);
|
959
|
+
WriteString(theEnv,logName," ");
|
960
|
+
WriteString(theEnv,logName,MessageHandlerData(theEnv)->CurrentMessageName->contents);
|
961
|
+
WriteString(theEnv,logName," ED:");
|
962
|
+
WriteInteger(theEnv,logName,EvaluationData(theEnv)->CurrentEvaluationDepth);
|
963
|
+
PrintProcParamArray(theEnv,logName);
|
964
|
+
}
|
965
|
+
|
966
|
+
/***********************************************************
|
967
|
+
NAME : WatchHandler
|
968
|
+
DESCRIPTION : Prints a condensed description of a
|
969
|
+
message-handler and its arguments
|
970
|
+
INPUTS : 1) The output logical name
|
971
|
+
2) The handler address
|
972
|
+
3) BEGIN_TRACE or END_TRACE string
|
973
|
+
RETURNS : Nothing useful
|
974
|
+
SIDE EFFECTS : None
|
975
|
+
NOTES : Uses the global variables ProcParamArray
|
976
|
+
and CurrentMessageName
|
977
|
+
***********************************************************/
|
978
|
+
void WatchHandler(
|
979
|
+
Environment *theEnv,
|
980
|
+
const char *logName,
|
981
|
+
HANDLER_LINK *hndl,
|
982
|
+
const char *tstring)
|
983
|
+
{
|
984
|
+
DefmessageHandler *hnd;
|
985
|
+
|
986
|
+
if (ConstructData(theEnv)->ClearReadyInProgress ||
|
987
|
+
ConstructData(theEnv)->ClearInProgress)
|
988
|
+
{ return; }
|
989
|
+
|
990
|
+
WriteString(theEnv,logName,"HND ");
|
991
|
+
WriteString(theEnv,logName,tstring);
|
992
|
+
WriteString(theEnv,logName," ");
|
993
|
+
hnd = hndl->hnd;
|
994
|
+
PrintHandler(theEnv,logName,hnd,false,true);
|
995
|
+
WriteString(theEnv,logName," ED:");
|
996
|
+
WriteInteger(theEnv,logName,EvaluationData(theEnv)->CurrentEvaluationDepth);
|
997
|
+
PrintProcParamArray(theEnv,logName);
|
998
|
+
}
|
999
|
+
|
1000
|
+
#endif /* DEBUGGING_FUNCTIONS */
|
1001
|
+
|
1002
|
+
/* =========================================
|
1003
|
+
*****************************************
|
1004
|
+
INTERNALLY VISIBLE FUNCTIONS
|
1005
|
+
=========================================
|
1006
|
+
***************************************** */
|
1007
|
+
|
1008
|
+
#if DEBUGGING_FUNCTIONS
|
1009
|
+
|
1010
|
+
/********************************************************************
|
1011
|
+
NAME : DisplayPrimaryCore
|
1012
|
+
DESCRIPTION : Gives a schematic "printout" of the primary
|
1013
|
+
message showing other shadowed primaries
|
1014
|
+
This routine uses recursion to print indentation
|
1015
|
+
to indicate shadowing and where handlers begin
|
1016
|
+
and end execution wrt one another.
|
1017
|
+
INPUTS : 1) The logical name of the output
|
1018
|
+
2) The remaining core
|
1019
|
+
3) The number of handlers this (partial) core
|
1020
|
+
shadows
|
1021
|
+
RETURNS : The address of the handler following the primary
|
1022
|
+
group of handlers in the core
|
1023
|
+
SIDE EFFECTS : None
|
1024
|
+
NOTES : Expects that the core was created in PREVIEW mode,
|
1025
|
+
i.e. implicit handlers are SlotDescriptor addresses
|
1026
|
+
(in PERFORM mode they are INSTANCE_SLOT addresses)
|
1027
|
+
Assumes (partial) core is not empty
|
1028
|
+
********************************************************************/
|
1029
|
+
static HANDLER_LINK *DisplayPrimaryCore(
|
1030
|
+
Environment *theEnv,
|
1031
|
+
const char *logicalName,
|
1032
|
+
HANDLER_LINK *core,
|
1033
|
+
int pdepth)
|
1034
|
+
{
|
1035
|
+
HANDLER_LINK *rtn;
|
1036
|
+
|
1037
|
+
PrintPreviewHandler(theEnv,logicalName,core,pdepth,BEGIN_TRACE);
|
1038
|
+
if ((core->nxt != NULL) ? (core->nxt->hnd->type == MPRIMARY) : false)
|
1039
|
+
rtn = DisplayPrimaryCore(theEnv,logicalName,core->nxt,pdepth+1);
|
1040
|
+
else
|
1041
|
+
rtn = core->nxt;
|
1042
|
+
PrintPreviewHandler(theEnv,logicalName,core,pdepth,END_TRACE);
|
1043
|
+
return(rtn);
|
1044
|
+
}
|
1045
|
+
|
1046
|
+
/***************************************************
|
1047
|
+
NAME : PrintPreviewHandler
|
1048
|
+
DESCRIPTION : Displays a message preview
|
1049
|
+
INPUTS : 1) The logical name of the output
|
1050
|
+
2) Handler-link
|
1051
|
+
3) Number of handlers shadowed
|
1052
|
+
4) The trace-string
|
1053
|
+
RETURNS : Nothing useful
|
1054
|
+
SIDE EFFECTS : None
|
1055
|
+
NOTES : None
|
1056
|
+
***************************************************/
|
1057
|
+
static void PrintPreviewHandler(
|
1058
|
+
Environment *theEnv,
|
1059
|
+
const char *logicalName,
|
1060
|
+
HANDLER_LINK *cptr,
|
1061
|
+
int sdepth,
|
1062
|
+
const char *tstr)
|
1063
|
+
{
|
1064
|
+
int i;
|
1065
|
+
|
1066
|
+
for (i = 0 ; i < sdepth ; i++)
|
1067
|
+
WriteString(theEnv,logicalName,"| ");
|
1068
|
+
WriteString(theEnv,logicalName,tstr);
|
1069
|
+
WriteString(theEnv,logicalName," ");
|
1070
|
+
PrintHandler(theEnv,logicalName,cptr->hnd,false,true);
|
1071
|
+
}
|
1072
|
+
|
1073
|
+
#endif
|
1074
|
+
|
1075
|
+
#endif
|
1076
|
+
|