summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/src/m_obj.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/m_obj.c')
-rw-r--r--apps/plugins/pdbox/PDa/src/m_obj.c697
1 files changed, 0 insertions, 697 deletions
diff --git a/apps/plugins/pdbox/PDa/src/m_obj.c b/apps/plugins/pdbox/PDa/src/m_obj.c
index d53da5722e..785fd240bf 100644
--- a/apps/plugins/pdbox/PDa/src/m_obj.c
+++ b/apps/plugins/pdbox/PDa/src/m_obj.c
@@ -695,700 +695,3 @@ int outlet_getsignalindex(t_outlet *x)
695 return (n); 695 return (n);
696} 696}
697 697
698/* Copyright (c) 1997-1999 Miller Puckette.
699* For information on usage and redistribution, and for a DISCLAIMER OF ALL
700* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
701
702/* this file handles Max-style patchable objects, i.e., objects which
703can interconnect via inlets and outlets; also, the (terse) generic
704behavior for "gobjs" appears at the end of this file. */
705
706#include "m_pd.h"
707#include "m_imp.h"
708
709union inletunion
710{
711 t_symbol *iu_symto;
712 t_gpointer *iu_pointerslot;
713 t_float *iu_floatslot;
714 t_symbol **iu_symslot;
715 t_sample iu_floatsignalvalue;
716};
717
718struct _inlet
719{
720 t_pd i_pd;
721 struct _inlet *i_next;
722 t_object *i_owner;
723 t_pd *i_dest;
724 t_symbol *i_symfrom;
725 union inletunion i_un;
726};
727
728#define i_symto i_un.iu_symto
729#define i_pointerslot i_un.iu_pointerslot
730#define i_floatslot i_un.iu_floatslot
731#define i_symslot i_un.iu_symslot
732
733static t_class *inlet_class, *pointerinlet_class, *floatinlet_class,
734 *symbolinlet_class;
735
736#define ISINLET(pd) ((*(pd) == inlet_class) || \
737 (*(pd) == pointerinlet_class) || \
738 (*(pd) == floatinlet_class) || \
739 (*(pd) == symbolinlet_class))
740
741/* --------------------- generic inlets ala max ------------------ */
742
743t_inlet *inlet_new(t_object *owner, t_pd *dest, t_symbol *s1, t_symbol *s2)
744{
745 t_inlet *x = (t_inlet *)pd_new(inlet_class), *y, *y2;
746 x->i_owner = owner;
747 x->i_dest = dest;
748 if (s1 == &s_signal)
749 x->i_un.iu_floatsignalvalue = 0;
750 else x->i_symto = s2;
751 x->i_symfrom = s1;
752 x->i_next = 0;
753 if (y = owner->ob_inlet)
754 {
755 while (y2 = y->i_next) y = y2;
756 y->i_next = x;
757 }
758 else owner->ob_inlet = x;
759 return (x);
760}
761
762static void inlet_wrong(t_inlet *x, t_symbol *s)
763{
764 pd_error(x->i_owner, "inlet: expected '%s' but got '%s'",
765 x->i_symfrom->s_name, s->s_name);
766}
767
768 /* LATER figure out how to make these efficient: */
769static void inlet_bang(t_inlet *x)
770{
771 if (x->i_symfrom == &s_bang)
772 pd_vmess(x->i_dest, x->i_symto, "");
773 else if (!x->i_symfrom) pd_bang(x->i_dest);
774 else inlet_wrong(x, &s_bang);
775}
776
777static void inlet_pointer(t_inlet *x, t_gpointer *gp)
778{
779 if (x->i_symfrom == &s_pointer)
780 pd_vmess(x->i_dest, x->i_symto, "p", gp);
781 else if (!x->i_symfrom) pd_pointer(x->i_dest, gp);
782 else inlet_wrong(x, &s_pointer);
783}
784
785static void inlet_float(t_inlet *x, t_float f)
786{
787 if (x->i_symfrom == &s_float)
788 pd_vmess(x->i_dest, x->i_symto, "f", (t_floatarg)f);
789 else if (x->i_symfrom == &s_signal)
790 x->i_un.iu_floatsignalvalue = ftofix(f);
791 else if (!x->i_symfrom)
792 pd_float(x->i_dest, f);
793 else inlet_wrong(x, &s_float);
794}
795
796static void inlet_symbol(t_inlet *x, t_symbol *s)
797{
798 if (x->i_symfrom == &s_symbol)
799 pd_vmess(x->i_dest, x->i_symto, "s", s);
800 else if (!x->i_symfrom) pd_symbol(x->i_dest, s);
801 else inlet_wrong(x, &s_symbol);
802}
803
804static void inlet_list(t_inlet *x, t_symbol *s, int argc, t_atom *argv)
805{
806 t_atom at;
807 if (x->i_symfrom == &s_list || x->i_symfrom == &s_float
808 || x->i_symfrom == &s_symbol || x->i_symfrom == &s_pointer)
809 typedmess(x->i_dest, x->i_symto, argc, argv);
810 else if (!x->i_symfrom) pd_list(x->i_dest, s, argc, argv);
811 else inlet_wrong(x, &s_list);
812}
813
814static void inlet_anything(t_inlet *x, t_symbol *s, int argc, t_atom *argv)
815{
816 if (x->i_symfrom == s)
817 typedmess(x->i_dest, x->i_symto, argc, argv);
818 else if (!x->i_symfrom)
819 typedmess(x->i_dest, s, argc, argv);
820 else inlet_wrong(x, s);
821}
822
823void inlet_free(t_inlet *x)
824{
825 t_object *y = x->i_owner;
826 t_inlet *x2;
827 if (y->ob_inlet == x) y->ob_inlet = x->i_next;
828 else for (x2 = y->ob_inlet; x2; x2 = x2->i_next)
829 if (x2->i_next == x)
830 {
831 x2->i_next = x->i_next;
832 break;
833 }
834 t_freebytes(x, sizeof(*x));
835}
836
837/* ----- pointerinlets, floatinlets, syminlets: optimized inlets ------- */
838
839static void pointerinlet_pointer(t_inlet *x, t_gpointer *gp)
840{
841 gpointer_unset(x->i_pointerslot);
842 *(x->i_pointerslot) = *gp;
843 if (gp->gp_stub) gp->gp_stub->gs_refcount++;
844}
845
846t_inlet *pointerinlet_new(t_object *owner, t_gpointer *gp)
847{
848 t_inlet *x = (t_inlet *)pd_new(pointerinlet_class), *y, *y2;
849 x->i_owner = owner;
850 x->i_dest = 0;
851 x->i_symfrom = &s_pointer;
852 x->i_pointerslot = gp;
853 x->i_next = 0;
854 if (y = owner->ob_inlet)
855 {
856 while (y2 = y->i_next) y = y2;
857 y->i_next = x;
858 }
859 else owner->ob_inlet = x;
860 return (x);
861}
862
863static void floatinlet_float(t_inlet *x, t_float f)
864{
865 *(x->i_floatslot) = f;
866}
867
868t_inlet *floatinlet_new(t_object *owner, t_float *fp)
869{
870 t_inlet *x = (t_inlet *)pd_new(floatinlet_class), *y, *y2;
871 x->i_owner = owner;
872 x->i_dest = 0;
873 x->i_symfrom = &s_float;
874 x->i_floatslot = fp;
875 x->i_next = 0;
876 if (y = owner->ob_inlet)
877 {
878 while (y2 = y->i_next) y = y2;
879 y->i_next = x;
880 }
881 else owner->ob_inlet = x;
882 return (x);
883}
884
885static void symbolinlet_symbol(t_inlet *x, t_symbol *s)
886{
887 *(x->i_symslot) = s;
888}
889
890t_inlet *symbolinlet_new(t_object *owner, t_symbol **sp)
891{
892 t_inlet *x = (t_inlet *)pd_new(symbolinlet_class), *y, *y2;
893 x->i_owner = owner;
894 x->i_dest = 0;
895 x->i_symfrom = &s_symbol;
896 x->i_symslot = sp;
897 x->i_next = 0;
898 if (y = owner->ob_inlet)
899 {
900 while (y2 = y->i_next) y = y2;
901 y->i_next = x;
902 }
903 else owner->ob_inlet = x;
904 return (x);
905}
906
907/* ---------------------- routine to handle lists ---------------------- */
908
909 /* objects interpret lists by feeding them to the individual inlets.
910 Before you call this check that the object doesn't have a more
911 specific way to handle lists. */
912void obj_list(t_object *x, t_symbol *s, int argc, t_atom *argv)
913{
914 t_atom *ap;
915 int count;
916 t_inlet *ip = ((t_object *)x)->ob_inlet;
917 if (!argc) return;
918 for (count = argc-1, ap = argv+1; ip && count--; ap++, ip = ip->i_next)
919 {
920 if (ap->a_type == A_POINTER) pd_pointer(&ip->i_pd, ap->a_w.w_gpointer);
921 else if (ap->a_type == A_FLOAT) pd_float(&ip->i_pd, ap->a_w.w_float);
922 else pd_symbol(&ip->i_pd, ap->a_w.w_symbol);
923 }
924 if (argv->a_type == A_POINTER) pd_pointer(&x->ob_pd, argv->a_w.w_gpointer);
925 else if (argv->a_type == A_FLOAT) pd_float(&x->ob_pd, argv->a_w.w_float);
926 else pd_symbol(&x->ob_pd, argv->a_w.w_symbol);
927}
928
929void obj_init(void)
930{
931 inlet_class = class_new(gensym("inlet"), 0, 0,
932 sizeof(t_inlet), CLASS_PD, 0);
933 class_addbang(inlet_class, inlet_bang);
934 class_addpointer(inlet_class, inlet_pointer);
935 class_addfloat(inlet_class, inlet_float);
936 class_addsymbol(inlet_class, inlet_symbol);
937 class_addlist(inlet_class, inlet_list);
938 class_addanything(inlet_class, inlet_anything);
939
940 pointerinlet_class = class_new(gensym("inlet"), 0, 0,
941 sizeof(t_inlet), CLASS_PD, 0);
942 class_addpointer(pointerinlet_class, pointerinlet_pointer);
943
944 floatinlet_class = class_new(gensym("inlet"), 0, 0,
945 sizeof(t_inlet), CLASS_PD, 0);
946 class_addfloat(floatinlet_class, (t_method)floatinlet_float);
947
948 symbolinlet_class = class_new(gensym("inlet"), 0, 0,
949 sizeof(t_inlet), CLASS_PD, 0);
950 class_addsymbol(symbolinlet_class, symbolinlet_symbol);
951
952}
953
954/* --------------------------- outlets ------------------------------ */
955
956static char *stacklimit, *topstack;
957#define STACKSIZE 1000000
958static int outlet_eventno;
959
960 /* set a stack limit (on each incoming event that can set off messages)
961 for the outlet functions to check to prevent stack overflow from message
962 recursion */
963void outlet_setstacklim(void)
964{
965 char c;
966 topstack = &c;
967 stacklimit = (&c) - STACKSIZE;
968 outlet_eventno++;
969}
970
971 /* get a number unique to the (clock, MIDI, GUI, etc.) event we're on */
972int sched_geteventno( void)
973{
974 return (outlet_eventno);
975}
976
977struct _outconnect
978{
979 struct _outconnect *oc_next;
980 t_pd *oc_to;
981};
982
983struct _outlet
984{
985 t_object *o_owner;
986 struct _outlet *o_next;
987 t_outconnect *o_connections;
988 t_symbol *o_sym;
989};
990
991t_outlet *outlet_new(t_object *owner, t_symbol *s)
992{
993 t_outlet *x = (t_outlet *)getbytes(sizeof(*x)), *y, *y2;
994 x->o_owner = owner;
995 x->o_next = 0;
996 if (y = owner->ob_outlet)
997 {
998 while (y2 = y->o_next) y = y2;
999 y->o_next = x;
1000 }
1001 else owner->ob_outlet = x;
1002 x->o_connections = 0;
1003 x->o_sym = s;
1004 return (x);
1005}
1006
1007static void outlet_stackerror(t_outlet *x)
1008{
1009 pd_error(x->o_owner, "stack overflow");
1010 stacklimit = topstack;
1011}
1012
1013void outlet_bang(t_outlet *x)
1014{
1015 t_outconnect *oc;
1016 char c;
1017 if (&c < stacklimit)
1018 outlet_stackerror(x);
1019 else for (oc = x->o_connections; oc; oc = oc->oc_next)
1020 pd_bang(oc->oc_to);
1021}
1022
1023void outlet_pointer(t_outlet *x, t_gpointer *gp)
1024{
1025 t_outconnect *oc;
1026 t_gpointer gpointer;
1027 char c;
1028 if (&c < stacklimit)
1029 outlet_stackerror(x);
1030 else
1031 {
1032#if 0
1033 gpointer_copy(gp, &gpointer);
1034 for (oc = x->o_connections; oc; oc = oc->oc_next)
1035 pd_pointer(oc->oc_to, &gpointer);
1036 gpointer_unset(&gpointer);
1037#else
1038 gpointer = *gp;
1039 for (oc = x->o_connections; oc; oc = oc->oc_next)
1040 pd_pointer(oc->oc_to, &gpointer);
1041#endif
1042 }
1043}
1044
1045void outlet_float(t_outlet *x, t_float f)
1046{
1047 t_outconnect *oc;
1048 char c;
1049 if (&c < stacklimit)
1050 outlet_stackerror(x);
1051 else for (oc = x->o_connections; oc; oc = oc->oc_next)
1052 pd_float(oc->oc_to, f);
1053}
1054
1055void outlet_symbol(t_outlet *x, t_symbol *s)
1056{
1057 t_outconnect *oc;
1058 char c;
1059 if (&c < stacklimit)
1060 outlet_stackerror(x);
1061 else for (oc = x->o_connections; oc; oc = oc->oc_next)
1062 pd_symbol(oc->oc_to, s);
1063}
1064
1065void outlet_list(t_outlet *x, t_symbol *s, int argc, t_atom *argv)
1066{
1067 t_outconnect *oc;
1068 char c;
1069 if (&c < stacklimit)
1070 outlet_stackerror(x);
1071 else for (oc = x->o_connections; oc; oc = oc->oc_next)
1072 pd_list(oc->oc_to, s, argc, argv);
1073}
1074
1075void outlet_anything(t_outlet *x, t_symbol *s, int argc, t_atom *argv)
1076{
1077 t_outconnect *oc;
1078 char c;
1079 if (&c < stacklimit)
1080 outlet_stackerror(x);
1081 else for (oc = x->o_connections; oc; oc = oc->oc_next)
1082 typedmess(oc->oc_to, s, argc, argv);
1083}
1084
1085 /* get the outlet's declared symbol */
1086t_symbol *outlet_getsymbol(t_outlet *x)
1087{
1088 return (x->o_sym);
1089}
1090
1091void outlet_free(t_outlet *x)
1092{
1093 t_object *y = x->o_owner;
1094 t_outlet *x2;
1095 if (y->ob_outlet == x) y->ob_outlet = x->o_next;
1096 else for (x2 = y->ob_outlet; x2; x2 = x2->o_next)
1097 if (x2->o_next == x)
1098 {
1099 x2->o_next = x->o_next;
1100 break;
1101 }
1102 t_freebytes(x, sizeof(*x));
1103}
1104
1105t_outconnect *obj_connect(t_object *source, int outno,
1106 t_object *sink, int inno)
1107{
1108 t_inlet *i;
1109 t_outlet *o;
1110 t_pd *to;
1111 t_outconnect *oc, *oc2;
1112
1113 for (o = source->ob_outlet; o && outno; o = o->o_next, outno--) ;
1114 if (!o) return (0);
1115
1116 if (sink->ob_pd->c_firstin)
1117 {
1118 if (!inno)
1119 {
1120 to = &sink->ob_pd;
1121 goto doit;
1122 }
1123 else inno--;
1124 }
1125 for (i = sink->ob_inlet; i && inno; i = i->i_next, inno--) ;
1126 if (!i) return (0);
1127 to = &i->i_pd;
1128doit:
1129 oc = (t_outconnect *)t_getbytes(sizeof(*oc));
1130 oc->oc_next = 0;
1131 oc->oc_to = to;
1132 /* append it to the end of the list */
1133 /* LATER we might cache the last "oc" to make this faster. */
1134 if ((oc2 = o->o_connections))
1135 {
1136 while (oc2->oc_next) oc2 = oc2->oc_next;
1137 oc2->oc_next = oc;
1138 }
1139 else o->o_connections = oc;
1140 if (o->o_sym == &s_signal) canvas_update_dsp();
1141
1142 return (oc);
1143}
1144
1145void obj_disconnect(t_object *source, int outno, t_object *sink, int inno)
1146{
1147 t_inlet *i;
1148 t_outlet *o;
1149 t_pd *to;
1150 t_outconnect *oc, *oc2;
1151
1152 for (o = source->ob_outlet; o && outno; o = o->o_next, outno--)
1153 if (!o) return;
1154 if (sink->ob_pd->c_firstin)
1155 {
1156 if (!inno)
1157 {
1158 to = &sink->ob_pd;
1159 goto doit;
1160 }
1161 else inno--;
1162 }
1163 for (i = sink->ob_inlet; i && inno; i = i->i_next, inno--) ;
1164 if (!i) return;
1165 to = &i->i_pd;
1166doit:
1167 if (!(oc = o->o_connections)) return;
1168 if (oc->oc_to == to)
1169 {
1170 o->o_connections = oc->oc_next;
1171 freebytes(oc, sizeof(*oc));
1172 goto done;
1173 }
1174 while (oc2 = oc->oc_next)
1175 {
1176 if (oc2->oc_to == to)
1177 {
1178 oc->oc_next = oc2->oc_next;
1179 freebytes(oc2, sizeof(*oc2));
1180 goto done;
1181 }
1182 oc = oc2;
1183 }
1184done:
1185 if (o->o_sym == &s_signal) canvas_update_dsp();
1186}
1187
1188/* ------ traversal routines for code that can't see our structures ------ */
1189
1190int obj_noutlets(t_object *x)
1191{
1192 int n;
1193 t_outlet *o;
1194 for (o = x->ob_outlet, n = 0; o; o = o->o_next) n++;
1195 return (n);
1196}
1197
1198int obj_ninlets(t_object *x)
1199{
1200 int n;
1201 t_inlet *i;
1202 for (i = x->ob_inlet, n = 0; i; i = i->i_next) n++;
1203 if (x->ob_pd->c_firstin) n++;
1204 return (n);
1205}
1206
1207t_outconnect *obj_starttraverseoutlet(t_object *x, t_outlet **op, int nout)
1208{
1209 t_outlet *o = x->ob_outlet;
1210 while (nout-- && o) o = o->o_next;
1211 *op = o;
1212 if (o) return (o->o_connections);
1213 else return (0);
1214}
1215
1216t_outconnect *obj_nexttraverseoutlet(t_outconnect *lastconnect,
1217 t_object **destp, t_inlet **inletp, int *whichp)
1218{
1219 t_pd *y;
1220 y = lastconnect->oc_to;
1221 if (ISINLET(y))
1222 {
1223 int n;
1224 t_inlet *i = (t_inlet *)y, *i2;
1225 t_object *dest = i->i_owner;
1226 for (n = dest->ob_pd->c_firstin, i2 = dest->ob_inlet;
1227 i2 && i2 != i; i2 = i2->i_next) n++;
1228 *whichp = n;
1229 *destp = dest;
1230 *inletp = i;
1231 }
1232 else
1233 {
1234 *whichp = 0;
1235 *inletp = 0;
1236 *destp = ((t_object *)y);
1237 }
1238 return (lastconnect->oc_next);
1239}
1240
1241 /* this one checks that a pd is indeed a patchable object, and returns
1242 it, correctly typed, or zero if the check failed. */
1243t_object *pd_checkobject(t_pd *x)
1244{
1245 if ((*x)->c_patchable) return ((t_object *)x);
1246 else return (0);
1247}
1248
1249 /* move an inlet or outlet to the head of the list */
1250void obj_moveinletfirst(t_object *x, t_inlet *i)
1251{
1252 t_inlet *i2;
1253 if (x->ob_inlet == i) return;
1254 else for (i2 = x->ob_inlet; i2; i2 = i2->i_next)
1255 if (i2->i_next == i)
1256 {
1257 i2->i_next = i->i_next;
1258 i->i_next = x->ob_inlet;
1259 x->ob_inlet = i;
1260 return;
1261 }
1262}
1263
1264void obj_moveoutletfirst(t_object *x, t_outlet *o)
1265{
1266 t_outlet *o2;
1267 if (x->ob_outlet == o) return;
1268 else for (o2 = x->ob_outlet; o2; o2 = o2->o_next)
1269 if (o2->o_next == o)
1270 {
1271 o2->o_next = o->o_next;
1272 o->o_next = x->ob_outlet;
1273 x->ob_outlet = o;
1274 return;
1275 }
1276}
1277
1278 /* routines for DSP sorting, which are used in d_ugen.c and g_canvas.c */
1279 /* LATER try to consolidate all the slightly different routines. */
1280
1281int obj_nsiginlets(t_object *x)
1282{
1283 int n;
1284 t_inlet *i;
1285 for (i = x->ob_inlet, n = 0; i; i = i->i_next)
1286 if (i->i_symfrom == &s_signal) n++;
1287 if (x->ob_pd->c_firstin && x->ob_pd->c_floatsignalin) n++;
1288 return (n);
1289}
1290
1291 /* get the index, among signal inlets, of the mth inlet overall */
1292int obj_siginletindex(t_object *x, int m)
1293{
1294 int n = 0;
1295 t_inlet *i;
1296 if (x->ob_pd->c_firstin && x->ob_pd->c_floatsignalin)
1297 {
1298 if (!m--) return (0);
1299 n++;
1300 }
1301 for (i = x->ob_inlet; i; i = i->i_next, m--)
1302 if (i->i_symfrom == &s_signal)
1303 {
1304 if (m == 0) return (n);
1305 n++;
1306 }
1307 return (-1);
1308}
1309
1310int obj_issignalinlet(t_object *x, int m)
1311{
1312 t_inlet *i;
1313 if (x->ob_pd->c_firstin)
1314 {
1315 if (!m)
1316 return (x->ob_pd->c_firstin && x->ob_pd->c_floatsignalin);
1317 else m--;
1318 }
1319 for (i = x->ob_inlet; i && m; i = i->i_next, m--)
1320 ;
1321 return (i && (i->i_symfrom == &s_signal));
1322}
1323
1324int obj_nsigoutlets(t_object *x)
1325{
1326 int n;
1327 t_outlet *o;
1328 for (o = x->ob_outlet, n = 0; o; o = o->o_next)
1329 if (o->o_sym == &s_signal) n++;
1330 return (n);
1331}
1332
1333int obj_sigoutletindex(t_object *x, int m)
1334{
1335 int n;
1336 t_outlet *o2;
1337 for (o2 = x->ob_outlet, n = 0; o2; o2 = o2->o_next, m--)
1338 if (o2->o_sym == &s_signal)
1339 {
1340 if (m == 0) return (n);
1341 n++;
1342 }
1343 return (-1);
1344}
1345
1346int obj_issignaloutlet(t_object *x, int m)
1347{
1348 int n;
1349 t_outlet *o2;
1350 for (o2 = x->ob_outlet, n = 0; o2 && m--; o2 = o2->o_next);
1351 return (o2 && (o2->o_sym == &s_signal));
1352}
1353
1354t_sample *obj_findsignalscalar(t_object *x, int m)
1355{
1356 int n = 0;
1357 t_inlet *i;
1358 if (x->ob_pd->c_firstin && x->ob_pd->c_floatsignalin)
1359 {
1360 if (!m--)
1361 return (x->ob_pd->c_floatsignalin > 0 ?
1362 (t_sample *)(((char *)x) + x->ob_pd->c_floatsignalin) : 0);
1363 n++;
1364 }
1365 for (i = x->ob_inlet; i; i = i->i_next, m--)
1366 if (i->i_symfrom == &s_signal)
1367 {
1368 if (m == 0)
1369 return (&i->i_un.iu_floatsignalvalue);
1370 n++;
1371 }
1372 return (0);
1373}
1374
1375/* and these are only used in g_io.c... */
1376
1377int inlet_getsignalindex(t_inlet *x)
1378{
1379 int n = 0;
1380 t_inlet *i;
1381 for (i = x->i_owner->ob_inlet, n = 0; i && i != x; i = i->i_next)
1382 if (i->i_symfrom == &s_signal) n++;
1383 return (n);
1384}
1385
1386int outlet_getsignalindex(t_outlet *x)
1387{
1388 int n = 0;
1389 t_outlet *o;
1390 for (o = x->o_owner->ob_outlet, n = 0; o && o != x; o = o->o_next)
1391 if (o->o_sym == &s_signal) n++;
1392 return (n);
1393}
1394