2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
25 * $XConsortium: obj_utils.c /main/4 1996/10/02 15:44:56 drk $
27 * @(#)obj_utils.c 3.137 01 Feb 1995
29 * RESTRICTED CONFIDENTIAL INFORMATION:
31 * The information in this document is subject to special restrictions in a
32 * confidential disclosure agreement between HP, IBM, Sun, USL, SCO and
33 * Univel. Do not distribute this document outside HP, IBM, Sun, USL, SCO,
34 * or Univel without Sun's specific written approval. This document and all
35 * copies and derivative works thereof must be returned or destroyed at Sun's
38 * Copyright 1993 Sun Microsystems, Inc. All rights reserved.
44 * utils.c - general utilities
49 #include <sys/param.h>
50 #include <sys/times.h>
54 #include "objP.h" /* put objP.h first! */
55 #include <ab_private/trav.h>
56 #include <ab_private/util.h>
57 #include <ab/util_types.h>
58 #include <ab_private/istr.h>
59 #include "obj_utils.h"
60 #include "obj_names_listP.h"
62 #define AB_TYPE_MODULE AB_TYPE_MODULE /* REMIND: can be taken out later */
67 char *abo_empty_string = "";
68 char *abo_null_string = "(nil)";
70 static struct sigaction org_sig_segv_handler;
72 static struct sigaction org_sig_bus_handler;
74 static sigjmp_buf sigjmp_env;
76 static volatile BOOL sig_fault_handler_installed = FALSE;
77 static volatile BOOL mem_fault_occurred = FALSE;
78 static int sig_fault_handler_install(void);
79 static int sig_fault_handler_uninstall(void);
80 static void sig_fault_handler();
81 static BOOL objP_is_accessible(ABObj obj);
82 static int build_obj_array(
83 ABObj **objArrayInOut,
84 int *objArraySizeInOut,
87 static int verify_the_silly_index(
94 /*************************************************************************
96 ** General (non-object) utilities **
98 *************************************************************************/
101 ab_get_proper_subobj_type(AB_OBJECT_TYPE type)
103 AB_OBJECT_TYPE subtype = AB_TYPE_UNKNOWN;
107 case AB_TYPE_PROJECT:
108 subtype = AB_TYPE_MODULE;
114 subtype = AB_TYPE_ITEM;
123 * Returns the item type this object should contain. If the object is an
124 * item, it returns the type of the item.
127 ab_get_proper_item_type(AB_OBJECT_TYPE type)
129 AB_ITEM_TYPE item_type = AB_ITEM_FOR_UNDEF;
134 item_type = AB_ITEM_FOR_MENU;
138 item_type = AB_ITEM_FOR_CHOICE;
142 item_type = AB_ITEM_FOR_LIST;
151 ab_string_list_count(STRING * list)
156 while (list[i] != NULL)
166 ab_file_type_from_path(STRING path)
168 AB_FILE_TYPE file_type = AB_FILE_UNDEF;
169 int pathlen = strlen(path);
173 char *ext = &(path[pathlen - 2]);
174 if (strcmp(ext, ".P") == 0)
176 file_type = AB_FILE_GIL_PROJECT;
178 else if (strcmp(ext, ".G") == 0)
180 file_type = AB_FILE_GIL_INTERFACE;
189 * Only ensures that the identifier has no white space in it.
192 ab_ident_is_ok(STRING ident)
199 for (cp = ident; *cp != NULL; ++cp)
211 ab_c_ident_is_ok(STRING ident)
221 for (i = 0, len = strlen(ident); i < len; ++i)
225 /* The first character of a variable name must be a letter.
226 * The underscore character is considered a letter in C.
230 if (!(isalpha(ch)) && (ch != '_'))
235 if (!((isalnum(ch) || (ch == '_'))))
244 /*************************************************************************
246 ** Object utilities **
248 *************************************************************************/
251 obj_get_file(ABObj obj)
253 if (obj->type == AB_TYPE_FILE)
255 return obj_get_name(obj); /* stored as name */
257 while ((obj != NULL) && (obj->type != AB_TYPE_MODULE)
258 && (obj->type != AB_TYPE_PROJECT))
264 if (obj->type == AB_TYPE_MODULE)
266 return istr_string(obj->info.module.file);
268 else if (obj->type == AB_TYPE_PROJECT)
270 return istr_string(obj->info.project.file);
277 * Gets the project the object belongs to
280 obj_get_project(ABObj obj)
282 while ((obj != NULL) && (obj->type != AB_TYPE_PROJECT))
290 * Gets the module the object belongs to
293 obj_get_module(ABObj obj)
295 while ((obj != NULL) && (obj->type != AB_TYPE_MODULE))
303 * Gets the window the object belongs to
306 obj_get_window(ABObj obj)
308 while ((obj != NULL) && !obj_is_window(obj))
316 obj_get_num_items(ABObj obj)
318 return trav_count(obj, AB_TRAV_ITEMS_FOR_OBJ);
322 * Counts the given object! (i.e., always returns at least 1).
325 obj_get_num_siblings(ABObj obj)
329 for (trav_open(&trav, obj, AB_TRAV_SIBLINGS);
330 (obj = trav_next(&trav)) != NULL;)
338 * Makes sure the object has at least the specified number of children.
340 * Any new children created are appended to the child list, and they are of the
341 * type returned from abo_proper_item_type.
344 obj_ensure_num_children(ABObj obj, int requested_num_children)
346 AB_OBJECT_TYPE child_type = ab_get_proper_subobj_type(obj->type);
347 AB_ITEM_TYPE child_item_type = ab_get_proper_item_type(obj->type);
348 int num_children = obj_get_num_children(obj);
351 while (num_children < requested_num_children)
353 child = obj_create(child_type, NULL);
358 if (obj_is_item(child))
360 child->info.item.type = child_item_type;
362 obj_append_child(obj, child);
370 obj_find_child_by_label(ABObj root, STRING label)
374 for (child = root->first_child;
375 child != NULL; child = child->next_sibling)
377 if (istr_equalstr(child->label, label))
387 obj_find_child_by_type(ABObj obj, AB_OBJECT_TYPE childType)
390 for (child = obj->first_child;
391 (child != NULL); child = child->next_sibling)
393 if (child->type == childType)
404 obj_find_by_name(ABObj root, STRING name)
406 StringList names = objP_get_names_scope_for_children(root);
407 ISTRING istr_name = istr_dup_existing(name);
411 if ((name == NULL) || (istr_name == NULL))
418 obj = (ABObj)strlist_get_istr_data(names, istr_name);
422 for (trav_open(&trav, root, AB_TRAV_ALL);
423 (obj = trav_next(&trav)) != NULL;)
425 if (!(obj_is_project(obj) || obj_is_module(obj)))
427 if (istr_equal(obj->name, istr_name))
433 istr_destroy(istr_name);
438 obj_find_by_name_and_type(ABObj root, STRING name, AB_OBJECT_TYPE type)
447 for (trav_open(&trav, root, AB_TRAV_ALL);
448 (obj = trav_next(&trav)) != NULL;)
450 if ((obj->type == type)
451 && (istr_equalstr(obj->name, name)))
462 obj_find_by_type(ABObj root, AB_OBJECT_TYPE type)
467 for (trav_open(&trav, root, AB_TRAV_UI | AB_TRAV_MOD_PARENTS_FIRST);
468 (obj = trav_next(&trav)) != NULL;)
470 if (obj->type == type)
482 obj_find_child_by_name(ABObj obj, STRING name)
489 for (child = obj->first_child;
490 child != NULL; child = child->next_sibling)
492 if (istr_equalstr(child->name, name))
502 obj_find_menu_by_name(ABObj root, STRING name)
504 return obj_find_by_name_and_type(root, name, AB_TYPE_MENU);
509 obj_find_module_by_name(ABObj root, STRING name)
514 for (trav_open(&trav, root, AB_TRAV_MODULES);
515 (module = trav_next(&trav)) != NULL;)
517 if (util_streq(obj_get_name(module), name))
529 obj_scoped_find_or_create_undef(ABObj parent,
530 STRING scopedName, AB_OBJECT_TYPE objType)
532 ABObj obj = obj_scoped_find_by_name(parent, scopedName);
536 STRING moduleName = obj_scoped_name_get_module_name(
538 STRING objName = obj_scoped_name_get_obj_name(
540 ABObj project = NULL;
543 if (moduleName == NULL)
545 /* simple name - create as child of the "parent" object */
546 obj = obj_create(objType, parent);
550 /* complex name - find module to create under */
551 project = obj_get_project(parent);
554 module = obj_find_module_by_name(project, moduleName);
557 /* damn! module don't exist!! */
558 module = obj_create(AB_TYPE_MODULE, project);
559 obj_set_is_defined(module, FALSE);
560 obj_set_name(module, moduleName);
565 /* actually create the object under the correct module */
566 obj = obj_create(objType, module);
571 * We've (hopefully) created a new object (or more correctly, a
572 * reference to an undefined object). Set the attributes that we know
577 obj_set_is_defined(obj, FALSE);
578 obj_set_name(obj, objName);
586 /*************************************************************************
588 ** Functions private to libgobj **
590 **************************************************************************/
593 abo_error(STRING message)
595 util_printf_err("%s\n", message);
603 for (i = 0; i < spaces; ++i)
611 * Returns TRUE if the object is the target of a project connection (i.e. one
612 * that is written into the project .c file, and not into a module. Formerly
613 * known as cross-module connections).
616 obj_is_project_action_target(ABObj obj)
618 ABObj project = NULL;
619 BOOL is_project_target = FALSE;
623 project = obj_get_project(obj);
624 for (trav_open(&trav, project, AB_TRAV_ACTIONS_FOR_OBJ);
625 (action = trav_next(&trav)) != NULL;)
627 if (action->info.action.to == obj)
629 is_project_target = TRUE;
634 return is_project_target;
639 * Return a valid C name given a string (normally, a label)
642 ab_make_valid_c_ident(STRING label)
644 static char name[MAXPATHLEN];
647 register char *oldPtr = label;
648 register char *newPtr = name;
650 if (isdigit(*oldPtr))
654 * If the label starts with a number, prepend 'dtb'
659 lastchar = *(newPtr-1);
662 while ((*oldPtr) != '\0')
664 if (isalnum(*oldPtr))
666 lastchar = *newPtr++ = *oldPtr++;
668 else if (isprint(*oldPtr) && (lastchar != '_'))
670 /* turn illegal printable chars into _ (e.g. / .) */
671 lastchar = *newPtr++ = '_';
677 * Skip the illegal character.
684 * Strip off trailing underscore (there will be no more than one).
690 *newPtr = 0; /* terminate the string */
696 * The entire label is composed of illegal characters, in that case,
697 * return a generated name.
699 sprintf(name, "dtb_name_%d", ith++);
707 * Given a unix file name, strip off the path and the suffix.
710 ab_ident_from_file_name(STRING filename)
712 static char buf[MAXPATHLEN];
715 if (filename != NULL)
717 if (p = (char *) strrchr(filename, '/'))
720 strcpy(buf, filename);
722 if (p = (char *) strrchr(buf, '.'))
730 * Assumes: name, label not NULL.
733 ab_ident_from_name_and_label(STRING name, STRING label)
735 static char new_name[256];
736 sprintf(new_name, "%s_%s", name, label);
737 return ab_make_valid_c_ident(new_name);
742 * Gets the module and object name from a complex name (i.e., a name of the
743 * form module.name or module::name
746 obj_scoped_name_split(
748 STRING module_name_buf,
749 int module_name_buf_size,
751 int obj_name_buf_size
754 int return_value = 0;
755 char *dot_ptr = NULL;
756 char *module_name_ptr = NULL;
757 char *obj_name_ptr = complex_name;
758 char *module_name_end_ptr = NULL;
759 int moduleNameEndChar = -1;
761 if ((dot_ptr = strchr(complex_name, '.')) != NULL)
763 module_name_ptr = complex_name;
764 obj_name_ptr = dot_ptr + 1;
766 else if ((dot_ptr = strstr(complex_name, "::")) != NULL)
768 module_name_ptr = complex_name;
769 obj_name_ptr = dot_ptr + 2;
773 * Remove white space on either side of the separator
777 /* put a 0 at the end of the module name */
778 for (module_name_end_ptr = dot_ptr - 1;
779 ((module_name_end_ptr > complex_name)
780 && isspace(*module_name_end_ptr));)
782 --module_name_end_ptr;
784 if (module_name_end_ptr < dot_ptr)
786 ++module_name_end_ptr; /* point one *after* last char in
789 moduleNameEndChar = *module_name_end_ptr;
790 *module_name_end_ptr = 0;
792 while (((*obj_name_ptr) != NULL) && (isspace(*obj_name_ptr)))
798 * We now now the substrings' locations. grab them
800 if (module_name_buf != NULL)
802 if (module_name_ptr == NULL)
804 /* no module name! */
805 *module_name_buf = 0;
809 strncpy(module_name_buf, complex_name, module_name_buf_size);
810 module_name_buf[module_name_buf_size - 1] = 0;
813 if (obj_name_buf != NULL)
815 strncpy(obj_name_buf, obj_name_ptr, obj_name_buf_size);
816 obj_name_buf[obj_name_buf_size - 1] = 0;
820 /* replace the 0 we inserted with the char that was there */
821 if (module_name_end_ptr != NULL)
823 *module_name_end_ptr = moduleNameEndChar;
830 * Gets the module name from the given object name, if there is one (i.e, the
831 * name is of the for module::name or module.name).
834 obj_scoped_name_get_module_name(STRING complexName)
836 static char module_name[256] = "";
838 rc = obj_scoped_name_split(complexName, module_name, 256, NULL, 0);
839 if ((rc < 0) || (*module_name == 0))
848 * Gets the simple object name from the complex name (a name of the form
849 * module::name or module.name).
852 obj_scoped_name_get_obj_name(STRING complexName)
854 static char simple_name[256] = "";
856 rc = obj_scoped_name_split(complexName, NULL, 0, simple_name, 256);
857 if ((rc < 0) || (*simple_name == 0))
865 /*************************************************************************
867 ** Debugging functions **
869 **************************************************************************/
872 obj_tree_print_indented(ABObj obj,
873 int spaces, int verbosity);
874 static int indent(int spaces);
880 int verbosity = util_get_verbosity();
881 return obj_print_indented(obj, spaces, verbosity);
885 obj_print_indented(ABObj obj, int spaces, int verbosity)
887 #define print_flag(flag, flag_str) \
888 (obj_has_flag(obj, flag)? \
889 util_dprintf(0, " %s", flag_str) \
898 util_dprintf(0, "NULL Object\n");
901 if (obj_is_action(obj))
903 switch (obj->info.action.func_type)
905 case AB_FUNC_USER_DEF:
906 sprintf(namebuf, "func:%s",
907 istr_string_safe(obj->info.action.func_value.func_name));
910 case AB_FUNC_BUILTIN: /* builtin */
911 sprintf(namebuf, "builtin:%s",
912 util_builtin_action_to_string(
913 obj->info.action.func_value.builtin));
919 sprintf(namebuf, "name:'%s'", istr_string_safe(obj->name));
922 if ((obj != NULL) && (obj_has_impl_flags(obj, ObjFlagDestroyed)))
924 util_dprintf(1, "**DESTROYED** ");
926 if ((obj != NULL) && (!obj_is_defined(obj)))
928 util_dprintf(0, "**UNDEF** ");
930 util_dprintf(0, "0x%08lx: %s type:%s\n",
932 util_object_type_to_string(obj->type));
936 util_dprintf(1, "file: '%s'\n", util_strsafe(obj_get_file(obj)));
937 if (obj->flags != NoFlags)
940 util_dprintf(0, "flags:");
941 print_flag(NoCodeGenFlag, "NoCodeGen");
942 print_flag(XmConfiguredFlag, "XmConfiged");
943 print_flag(XmCfgForCodeFlag, "CfgForCode");
944 print_flag(XmCfgForBuildFlag, "CfgForBuild");
945 print_flag(InstantiatedFlag, "Instantiated");
946 print_flag(BuildActionsFlag, "BuildActions");
947 print_flag(MappedFlag, "Mapped");
948 print_flag(AttrChangedFlag, "AttrChanged");
949 print_flag(SaveNeededFlag, "SaveNeeded");
950 print_flag(BeingDestroyedFlag, "BeingDestroyed");
951 util_dprintf(0, "\n");
953 if (obj_is_action(obj))
955 ABObj thisModule = NULL;
956 ABObj thatModule = NULL;
957 ABObj thatObj = NULL;
958 AB_WHEN when = AB_WHEN_UNDEF;
962 thisModule = obj_get_module(obj);
968 thatObj = obj->info.action.to;
971 thatModule = obj_get_module(thatObj);
974 util_dprintf(0, "to: ");
975 if ((thatModule != NULL) && (thatModule != thisModule))
977 util_dprintf(0, "%s.", obj_get_safe_name(thatModule, namebuf, 256));
979 util_dprintf(0, "(%#08lx)%s\n",
980 thatObj, obj_get_safe_name(thatObj, namebuf, 256));
985 thatObj = obj->info.action.from;
988 thatModule = obj_get_module(thatObj);
991 util_dprintf(0, "from: ");
992 if ((thatModule != NULL) && (thatModule != thisModule))
994 util_dprintf(0, "%s.", obj_get_safe_name(thatModule, namebuf, 256));
996 util_dprintf(0, "(%#08lx)%s\n",
997 thatObj, obj_get_safe_name(thatObj, namebuf, 256));
999 when = obj_get_when(obj);
1002 "when: %s\n", util_strsafe(util_when_to_string(when)));
1007 util_dprintf(0, "class:%s\n",
1008 istr_string_safe(obj->class_name));
1010 util_dprintf(0, "[parent: %s]\n",
1011 obj_get_safe_name(obj->parent, namebuf, 256));
1012 if (obj->ref_to != NULL)
1015 util_dprintf(0, "[ref_to: %s]\n",
1016 obj_get_safe_name(obj->ref_to, namebuf, 256));
1018 if (obj->part_of != NULL)
1021 util_dprintf(0, "[part_of: %s]\n",
1022 obj_get_safe_name(obj->part_of, namebuf, 256));
1025 util_dprintf(0, "x: %d\n", obj->x);
1027 util_dprintf(0, "y: %d\n", obj->y);
1029 util_dprintf(0, "width: %d\n", obj->width);
1031 util_dprintf(0, "height: %d\n", obj->height);
1033 util_dprintf(0, "label: '%s'\n",
1034 istr_string_safe(obj->label));
1035 } /* if is_action */
1039 } /* obj_print_indented */
1043 obj_tree_print(ABObj obj)
1046 util_dprintf(0, "***** Object tree *****\n");
1047 iRet = obj_tree_print_indented(obj, 0, util_get_verbosity());
1048 iRet = obj_tree_verify(obj);
1051 util_dprintf(0, "\n***\n*** TREE IS CORRUPT!\n***");
1054 util_dprintf(0, "******* Tree End ******\n");
1060 obj_tree_print_indented(ABObj obj, int spaces, int verbosity)
1067 util_dprintf(0, "NULL Tree\n");
1070 obj_print_indented(obj, spaces, verbosity);
1073 util_dprintf(0, "\n");
1075 for (trav_open(&trav, obj, AB_TRAV_CHILDREN);
1076 (child = trav_next(&trav)) != NULL;)
1078 obj_tree_print_indented(child, spaces + 4, verbosity);
1087 * Perform regular checks of object integrity.
1088 * Tries not to overuse CPU, so this may or may not actually verify anything.
1090 * Note that the debug_last_verify_time field doesn't exist in non-debugging
1094 objP_update_verify(ABObj obj)
1099 int return_value = 0;
1100 static ABObj lastObj = NULL;
1101 static int lastObjCount = 0;
1105 * time() can be rather slow, so let multiple references to the
1106 * same object slide...
1109 && ( (debug_level() >= 5)
1110 || (( (obj != lastObj) || (++lastObjCount > 10))
1111 && (curTime > (obj->debug_last_verify_time+1))) )
1114 return_value = obj_verify(obj);
1118 return return_value;
1124 * This function does not call any functions outside of this file.
1125 * This is because many functions call this one, and we don't want
1128 * This function can be EXTREMELY SLOW! Calling it, for instance,
1129 * one million times inside a loop would not be the right thing to do.
1132 obj_verify(ABObj obj)
1134 #define safe_data_access(_expr) \
1135 mem_fault_occurred = FALSE; \
1136 if (sigsetjmp(sigjmp_env, TRUE) == 0) \
1140 data_access_ok = (!mem_fault_occurred);
1142 #define field_err(_fieldName) \
1143 (return_value = -1, \
1145 "ERROR: Obj %s, bad value in field: %s\n", \
1146 obj_name, (_fieldName)))
1148 #define check_str(obj, _field) \
1149 ( ((int)(last_field = #_field)), \
1150 (istr_verify(obj->_field) >= 0)? \
1153 (field_err(#_field)))
1155 volatile BOOL objIsAccessible = FALSE;
1156 volatile int return_value = 0;
1157 volatile char obj_name[1024] = "";
1158 volatile STRING obj_str_ptr_name = NULL;
1159 volatile ABObj parent = NULL;
1160 volatile ABObj next_sibling = NULL;
1161 volatile ABObj prev_sibling = NULL;
1162 volatile BOOL ok = FALSE;
1163 volatile BOOL data_access_ok = TRUE;
1164 volatile STRING last_field = NULL;
1165 volatile ABObj tmpObj = NULL;
1166 volatile StringList namesList = NULL;
1168 sig_fault_handler_install();
1177 * See if this object even exists
1179 if (!objP_is_accessible(obj))
1181 objIsAccessible = FALSE;
1184 "ERROR - bad object ptr in obj_verify(): %#lx\n", obj);
1187 objIsAccessible = TRUE; /* don't forget to set this!! */
1190 * Get the name of the object
1192 mem_fault_occurred = FALSE;
1193 if (sigsetjmp(sigjmp_env, TRUE) == 0)
1195 obj_str_ptr_name = NULL;
1196 ok = (istr_verify(obj->name) >= 0);
1199 obj_str_ptr_name = istr_string(obj->name);
1200 sprintf((STRING)obj_name, "(ABObj %#lx", obj);
1201 if (obj_str_ptr_name != NULL)
1203 strcat((STRING)obj_name, " = ");
1204 strcat((STRING)obj_name, obj_str_ptr_name);
1206 strcat((STRING)obj_name, ")");
1215 sprintf((STRING)obj_name, "(ABObj %#lx)", obj);
1219 if (obj->impl_flags == ObjFlagAlreadyFreedValue)
1221 util_dprintf(0, "\n\n");
1222 util_dprintf(0, "\nDANGER WILL ROBINSON! COSMIC STORM APPROACHES!!!\n");
1223 util_dprintf(0, "\n");
1225 util_dprintf(0, " (Actually, it's just a reference to a previously destroyed object)\n");
1226 util_dprintf(0, " (Object is %s)\n", obj_name);
1227 util_dputs(0, "\n\n");
1234 next_sibling = obj->next_sibling;
1235 if ((next_sibling != NULL) && (!objP_is_accessible(next_sibling)))
1237 next_sibling = NULL;
1238 field_err("next_sibling");
1240 if (next_sibling != NULL)
1242 safe_data_access(ok = (next_sibling->prev_sibling == obj));
1243 if ((!data_access_ok) || (!ok))
1246 field_err("next_sibling");
1253 prev_sibling = obj->prev_sibling;
1254 if ((prev_sibling != NULL) && (!objP_is_accessible(prev_sibling)))
1256 prev_sibling = NULL;
1257 field_err("prev_sibling");
1259 if (prev_sibling != NULL)
1261 safe_data_access(ok = (prev_sibling->next_sibling == obj));
1262 if ((!data_access_ok) || (!ok))
1265 field_err("next_sibling");
1272 parent = obj->parent;
1273 if ((parent != NULL) && (!objP_is_accessible(parent)))
1276 field_err("parent");
1280 volatile ABObj child;
1281 volatile BOOL found = FALSE;
1284 safe_data_access(child = parent->first_child);
1285 if (!data_access_ok)
1287 field_err("parent");
1291 while ((!found) && (child != NULL))
1297 safe_data_access(child = child->next_sibling);
1298 if (!data_access_ok)
1300 field_err("parent");
1308 field_err("parent");
1317 * Still should check: first_child, part_of
1321 * Check all the ISTRING fields
1324 /* we shouldn't mem fault here, but we're going to prepare, */
1326 mem_fault_occurred = FALSE;
1327 if (sigsetjmp(sigjmp_env, TRUE) != 0)
1330 if (last_field != NULL)
1332 field_err(last_field);
1336 check_str(obj,user_data);
1337 check_str(obj,help_volume);
1338 check_str(obj,help_location);
1339 check_str(obj,help_text);
1340 check_str(obj,bg_color);
1341 check_str(obj,fg_color);
1342 check_str(obj,label);
1343 check_str(obj,menu_name);
1344 check_str(obj,class_name);
1347 * Check type-specific info
1351 case AB_TYPE_ACTION:
1352 switch (obj->info.action.func_type)
1354 case AB_FUNC_CODE_FRAG:
1355 check_str(obj,info.action.func_value.code_frag);
1358 case AB_FUNC_USER_DEF:
1359 check_str(obj,info.action.func_value.func_name);
1362 switch (obj->info.action.arg_type)
1365 check_str(obj,info.action.arg_value.sval);
1368 check_str(obj,info.action.func_name_suffix);
1371 case AB_TYPE_FILE_CHOOSER:
1372 check_str(obj,info.file_chooser.filter_pattern);
1373 check_str(obj,info.file_chooser.ok_label);
1374 check_str(obj,info.file_chooser.directory);
1377 case AB_TYPE_MESSAGE:
1378 check_str(obj,info.message.msg_string);
1379 check_str(obj,info.message.action1_label);
1380 check_str(obj,info.message.action2_label);
1383 case AB_TYPE_DIALOG:
1384 case AB_TYPE_BASE_WINDOW:
1386 check_str(obj,info.window.icon);
1387 check_str(obj,info.window.icon_label);
1391 case AB_TYPE_TEXT_FIELD:
1392 case AB_TYPE_TEXT_PANE:
1394 check_str(obj,info.text.initial_value_string);
1397 } /* switch obj->type */
1398 if (obj->type == AB_TYPE_MODULE)
1400 check_str(obj,info.module.file);
1401 check_str(obj,info.module.stubs_file);
1402 check_str(obj,info.module.ui_file);
1404 if (obj->type == AB_TYPE_ITEM)
1406 check_str(obj,info.item.accelerator);
1408 if (obj->type == AB_TYPE_PROJECT)
1410 check_str(obj,info.project.file);
1411 check_str(obj,info.project.stubs_file);
1413 if (obj->type == AB_TYPE_TERM_PANE)
1415 check_str(obj,info.term.process_string);
1420 * Check names index (we know the strings are valid, now)
1421 * project name doesn't go in an index
1423 if ((obj->type != AB_TYPE_PROJECT) && (obj->name != NULL))
1426 for (parent = obj->parent; parent != NULL; parent = parent->parent)
1428 if ( (parent->type == AB_TYPE_MODULE)
1429 || (parent->type == AB_TYPE_PROJECT) )
1436 switch (parent->type)
1438 case AB_TYPE_MODULE:
1439 namesList = parent->info.module.obj_names_list;
1441 case AB_TYPE_PROJECT:
1442 namesList = parent->info.project.obj_names_list;
1446 if (namesList == NULL)
1449 "No names index found containing %s\n", obj_name);
1456 * A destroyed object must *not* be in the index,
1457 * but any other object *must* be in the index.
1459 tmpObj = (ABObj)strlist_get_istr_data(namesList, obj->name);
1460 if (obj_has_impl_flags(obj, ObjFlagDestroyed))
1465 "Destroyed object is in names index: %s\n",
1475 util_dprintf(1, "Object does not exist in index: %s\n",
1482 } /* parent != NULL */
1483 } /* obj->name != NULL */
1487 if (objIsAccessible)
1489 obj->debug_last_verify_time = time(NULL); /*only exists in debug build*/
1492 sig_fault_handler_uninstall();
1493 return return_value;
1496 #undef safe_data_access
1501 * Returns whether or not we can actually examine this object without
1502 * causing a memory fault
1504 * Assumes: memory fault handler is installed
1505 * Modifies: sigjmp_env global var
1508 objP_is_accessible(ABObj obj)
1510 volatile BOOL isIt = TRUE;
1511 volatile unsigned char *volatile objData = (unsigned char *)obj;
1513 volatile unsigned char oneByte = 0;
1515 mem_fault_occurred = FALSE;
1516 if (sigsetjmp(sigjmp_env, TRUE) != 0)
1522 for (i = 0 ; i < sizeof(*obj); ++i)
1524 oneByte = objData[i];
1533 sig_fault_handler_install(void)
1535 struct sigaction new_action;
1537 mem_fault_occurred = FALSE;
1538 if (sig_fault_handler_installed)
1543 if (sigaction(SIGSEGV, NULL, &org_sig_segv_handler) < 0)
1547 new_action = org_sig_segv_handler;
1548 new_action.sa_handler = sig_fault_handler;
1549 sigemptyset(&(new_action.sa_mask));
1550 new_action.sa_flags = 0;
1551 if (sigaction(SIGSEGV, &new_action, NULL) < 0)
1556 sig_fault_handler_installed = TRUE;
1559 if (sigaction(SIGBUS, NULL, &org_sig_bus_handler) < 0)
1563 new_action = org_sig_bus_handler;
1564 new_action.sa_handler = sig_fault_handler;
1565 sigemptyset(&(new_action.sa_mask));
1566 new_action.sa_flags = 0;
1567 if (sigaction(SIGBUS, &new_action, NULL) < 0)
1578 sig_fault_handler_uninstall(void)
1580 mem_fault_occurred = FALSE;
1581 if (!sig_fault_handler_installed)
1586 if (sigaction(SIGSEGV, &org_sig_segv_handler, NULL) < 0)
1590 sig_fault_handler_installed = FALSE;
1593 if (sigaction(SIGBUS, &org_sig_bus_handler, NULL) < 0)
1606 if (mem_fault_occurred)
1608 /* We should have cleared this to prepare for a mem fault */
1609 /* If not, then something has gone haywire */
1610 static STRING msg = NULL;
1611 msg = "MEMORY ACCESS VIOLATION OCCURED. ABORTING.\n";
1612 write(2, msg, strlen(msg));
1615 mem_fault_occurred = TRUE;
1616 siglongjmp(sigjmp_env, 1);
1621 obj_tree_verify(ABObj root)
1623 int return_value = 0;
1624 int rc = 0; /* return code */
1625 ABObj *objArray = NULL;
1626 int objArraySize = 0;
1627 ABObj module = NULL;
1628 AB_TRAVERSAL moduleTrav;
1633 /* empty tree is valid (I guess) */
1637 rc = build_obj_array(&objArray, &objArraySize, root);
1644 for (i = 0; i < objArraySize; ++i)
1646 rc = obj_verify(objArray[i]);
1655 * Check the project names list
1657 if (obj_is_project(root))
1659 rc = verify_the_silly_index(root, objArray, objArraySize);
1668 * check the modules' name lists
1670 for (trav_open(&moduleTrav, root, AB_TRAV_MODULES);
1671 (module = trav_next(&moduleTrav)) != NULL; )
1673 rc = verify_the_silly_index(module, objArray, objArraySize);
1680 trav_close(&moduleTrav);
1683 util_free(objArray);
1684 return return_value;
1689 verify_the_silly_index(
1695 int return_value = 0;
1696 StringList names = NULL;
1700 ABObj namedObj = NULL;
1701 ABObj namesObj = NULL;
1702 ISTRING curName = NULL;
1703 ABObj curObj = NULL;
1704 ABObj curScopeObj = NULL;
1705 StringList curNames = NULL;
1706 BOOL namedObjFound = FALSE;
1707 char nameBuf1[1024];
1708 char nameBuf2[1024];
1709 char nameBuf3[1024];
1715 names = objP_get_names_list(nameScopeObj);
1720 numNames = strlist_get_num_strs(names);
1722 for (nameCount = 0; nameCount < numNames; ++nameCount)
1724 namedObjFound = FALSE;
1725 curName = strlist_get_istr(names, nameCount, (void **)&namedObj);
1727 (!namedObjFound) && (objCount < objArraySize); ++objCount)
1730 * See if we've found the object
1732 curObj = objArray[objCount];
1733 if ((curObj != namedObj) || obj_is_project(curObj))
1735 /* projects don't go in list, anywhere */
1740 * We've found the object that goes with this name. Check
1741 * to see if it is in the right scope.
1744 curScopeObj = objP_get_names_scope_obj(curObj);
1745 if (curScopeObj != NULL)
1747 curNames = objP_get_names_list(curScopeObj);
1749 if (curNames == NULL)
1752 "No names list found for object %s in module %s!\n",
1753 obj_get_safe_name(curObj, nameBuf1, 1024),
1754 obj_get_safe_name(obj_get_module(curObj), nameBuf2, 1024));
1755 return_value = ERR_INTERNAL;
1758 else if (curNames != names)
1761 "Object %s should be in scope for %s, but is in scope for %s\n",
1762 obj_get_safe_name(curObj, nameBuf1, 1024),
1763 obj_get_safe_name(curScopeObj, nameBuf2, 1024),
1764 obj_get_safe_name(nameScopeObj, nameBuf3, 1024));
1765 return_value = ERR_INTERNAL;
1768 else if (!istr_equal(curName, curObj->name))
1771 "Object %s has incorrect reference in index!\n",
1772 obj_get_safe_name(curObj, nameBuf1, 1024));
1776 namedObjFound = TRUE;
1778 } /* for objCount */
1784 "Name is in index '%s', but no such object exists!\n",
1785 istr_string_safe(curName));
1787 return_value = ERR_INTERNAL;
1790 } /* for nameCount */
1793 return return_value;
1798 build_obj_array(ABObj **objArrayPtr, int *objArraySizePtr, ABObj root)
1800 #define objArray (*objArrayPtr)
1801 #define objArraySize (*objArraySizePtr)
1802 int rc = 0; /* return code */
1803 ABObj *newObjArray = NULL;
1807 * If this object is already in the list, we've detected some sort
1814 for (i = 0; i < objArraySize; ++i)
1816 if (objArray[i] == root)
1819 "INTERNAL ERROR: some sort of cycle detected involving %s\n",
1820 obj_get_safe_name(root, name, 1024));
1827 * Add root obj to list
1830 newObjArray = (ABObj*)realloc(objArray, objArraySize*sizeof(ABObj*));
1831 if (newObjArray == NULL)
1833 util_dprintf(1, "Out of memory in build_obj_array\n");
1834 return ERR_NO_MEMORY;
1836 objArray = newObjArray;
1837 objArray[objArraySize-1] = root;
1840 * Add the children to the list
1842 for (child = root->first_child; child != NULL; child = child->next_sibling)
1844 if ((rc = build_obj_array(&objArray, &objArraySize, child)) < 0)
1857 obj_get_parent_of_type(ABObj obj, AB_OBJECT_TYPE type)
1859 ABObj ancestor = obj->parent;
1860 while ((ancestor != NULL) && (obj_get_type(ancestor) != type))
1862 ancestor = ancestor->parent;