Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtappbuilder / src / libABil / gil_loadact.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
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)
10  * any later version.
11  *
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
16  * details.
17  *
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
22  */
23
24 /*
25  * $XConsortium: gil_loadact.c /main/3 1995/11/06 18:27:51 rswiston $
26  * 
27  * @(#)gil_loadact.c    1.20 13 Feb 1994        cde_app_builder/src/libABil
28  * 
29  * RESTRICTED CONFIDENTIAL INFORMATION:
30  * 
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
36  * request.
37  * 
38  * Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
39  * 
40  */
41
42
43 /*
44  * loadact.c - load action and handler attributes
45  */
46
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <string.h>
50 #include <sys/param.h>
51 #include <assert.h>
52 #include <ab_private/obj.h>
53 #include <ab_private/abio.h>
54 #include <ab_private/trav.h>
55 #include <ab_private/util.h>
56 #include <ab_private/istr.h>
57 #include "../libABobj/obj_utils.h"
58 #include "gil.h"
59 #include "gilP.h"
60 #include "load.h"
61 #include "loadP.h"
62 #include "gil_loadattP.h"
63
64 static int      get_action(
65                         FILE * inFile, 
66                         ABObj obj, 
67                         ABObj module,
68                         ABObj action
69                 );
70 static int      get_action_attribute(
71                         FILE * inFile, 
72                         ABObj obj, 
73                         ABObj module,
74                         ABObj action,
75                         AB_GIL_ATTRIBUTE attr
76                 );
77 static int      get_when(
78                         FILE * inFile,
79                         ABObj obj, 
80                         ABObj action
81                 );
82 static int      get_from(
83                         FILE * inFile, 
84                         ABObj obj, 
85                         ABObj module, 
86                         ABObj action
87                 );
88 static int      get_to(
89                         FILE * inFile, 
90                         ABObj obj, 
91                         ABObj module, 
92                         ABObj action
93                 );
94 static int          get_operation(FILE * inFile, ABObj action);
95 static int          get_function_type(FILE * inFile, ABObj action);
96 static int          get_arg_type(FILE * inFile, ABObj action);
97 static int      add_user_handler(ABObj obj, ABObj module,
98                         ISTRING handler, AB_WHEN when);
99 static int      install_action(
100                         ABObj obj, 
101                         ABObj module, 
102                         ABObj action
103                 );
104 static ABObj    find_or_create_target(
105                         ABObj   obj, 
106                         ABObj   module,
107                         ISTRING interface_name,
108                         ISTRING parent_name,
109                         ISTRING obj_name,
110                         ISTRING item_label
111                 );
112
113 /*************************************************************************
114 **                                                                      **
115 **              Specific handlers                                       **
116 **                                                                      **
117 **************************************************************************/
118
119 /*
120  * */
121 int
122 gilP_load_att_done_handler(FILE * inFile, ABObj obj, ABObj module)
123 {
124     int                 return_value = 0;
125     int                 rc = 0; /* r turn code */
126     ISTRING             handler = NULL;
127     ABObj               action = NULL;
128
129     if ((rc = gilP_load_handler(inFile, &handler)) < 0)
130     {
131         return rc;
132     }
133
134     /*
135      * I don't know what this a DONE when signifies. It doesn't exist in BIL
136      * add_user_handler(obj, module, handler, AB_WHEN_DONE);
137      */
138     abil_print_load_err(ERR_NOT_IMPL);
139
140     istr_destroy(handler);
141     return return_value;
142 }
143
144 int
145 gilP_load_att_event_handler(FILE * inFile, ABObj obj, ABObj module)
146 {
147     int                 return_value = 0;
148     int                 rc = 0; /* r turn code */
149     ISTRING             event_handler = NULL;
150
151     if ((rc = gilP_load_handler(inFile, &event_handler)) < 0)
152     {
153         istr_destroy(event_handler);
154         return rc;
155     }
156
157     /*
158      * Doesn't exist in BIL add_user_handler(obj, module, event_handler,
159      * AB_WHEN_ANY_EVENT);
160      */
161     abil_print_load_err(ERR_NOT_IMPL);
162     istr_destroy(event_handler);
163     return return_value;
164 }
165
166 /*
167  * */
168 int
169 gilP_load_att_menu_handler(FILE * inFile, ABObj obj, ABObj module)
170 {
171     int                 return_value = 0;
172     int                 rc = 0; /* r turn code */
173     ISTRING             handler = NULL;
174
175     if ((rc = gilP_load_handler(inFile, &handler)) < 0)
176     {
177         return rc;
178     }
179     add_user_handler(obj, module, handler, AB_WHEN_ACTIVATED);
180     istr_destroy(handler);
181     return return_value;
182 }
183
184 /*
185  * */
186 int
187 gilP_load_att_menu_item_handlers(FILE * inFile, ABObj obj, ABObj module)
188 {
189     int                 return_value = 0;
190     int                 rc = 0; /* r turn code */
191     ISTRING_ARRAY       handlers;
192     AB_TRAVERSAL        trav;
193     ABObj               item = NULL;
194     int                 i = 0;
195
196     istr_array_init(&handlers);
197     if ((rc = gilP_load_handlers(inFile, &handlers)) < 0)
198     {
199         return rc;
200     }
201     obj_ensure_num_children(obj, handlers.count);
202     for (trav_open(&trav, obj, AB_TRAV_ITEMS_FOR_OBJ), i = 0;
203          (item = trav_next(&trav)) != NULL; ++i)
204     {
205         add_user_handler(item, module,
206                          handlers.strings[i], AB_WHEN_ACTIVATED);
207         handlers.strings[i] = NULL;
208     }
209     trav_close(&trav);
210     istr_array_uninit(&handlers);
211     return return_value;
212 }
213
214 /*
215  * */
216 int
217 gilP_load_att_notify_handler(FILE * inFile, ABObj obj, ABObj module)
218 {
219     int                 return_value = 0;
220     int                 rc = 0; /* r turn code */
221     ISTRING             handler = NULL;
222
223     if ((rc = gilP_load_handler(inFile, &handler)) < 0)
224     {
225         return rc;
226     }
227     add_user_handler(obj, module, handler, AB_WHEN_ACTIVATED);
228
229     istr_destroy(handler);
230     return return_value;
231 }
232
233 /*
234  * */
235 int
236 gilP_load_att_repaint_proc(FILE * inFile, ABObj obj, ABObj module)
237 {
238     int                 return_value = 0;
239     int                 rc = 0; /* r turn code */
240     ISTRING             repaint = NULL;
241
242     if ((rc = gilP_load_handler(inFile, &repaint)) < 0)
243     {
244         return rc;
245     }
246     add_user_handler(obj, module, repaint, AB_WHEN_REPAINT_NEEDED);
247
248     istr_destroy(repaint);
249     return return_value;
250 }
251
252
253 /*************************************************************************
254 **                                                                      **
255 **                                                                      **
256 **              General actions                                         **
257 **                                                                      **
258 **                                                                      **
259 **************************************************************************/
260
261
262 /*
263  * Load the actions attributes
264  */
265 int
266 gilP_load_att_actions(FILE * inFile, ABObj obj, ABObj module)
267 {
268     int                 return_value = 0;
269     int                 rc = 0; /* r turn code */
270     ABObj               action = NULL;
271
272     if (!abio_get_list_begin(inFile))
273         return (abil_print_load_err(ERR_WANT_LIST), -1);
274
275     while (!abio_get_list_end(inFile))
276     {
277         action = obj_create(AB_TYPE_ACTION, NULL);
278
279         if ((rc = get_action(inFile, obj, module, action)) < 0)
280         {
281             obj_destroy(action);
282             return rc;
283         }
284         else
285         {
286             if (obj_get_when(action) == AB_WHEN_UNDEF)
287             {
288                 /* unsupported :when value - ignore it and continue */
289                 obj_destroy(action);
290             }
291             else
292             {
293                 install_action(obj, module, action);
294             }
295         }
296     }
297     return return_value;
298 }
299
300
301 /*
302  * Load an action.
303  */
304 static int
305 get_action(
306                         FILE * inFile, 
307                         ABObj obj, 
308                         ABObj module, 
309                         ABObj action
310 )
311 {
312     int                 return_value = 0;
313     int                 rc = 0; /* r turn code */
314     ISTRING             keyword;
315     AB_GIL_ATTRIBUTE    action_attr;
316
317     if (!abio_get_list_begin(inFile))
318         return (abil_print_load_err(ERR_WANT_LIST), -1);
319
320     while (!abio_get_list_end(inFile))
321     {
322         if (abio_get_eof(inFile))
323         {
324             abil_print_load_err(ERR_EOF);
325             return -1;
326         }
327
328         if (!abio_get_keyword(inFile, &keyword))
329         {
330             abil_print_load_err(ERR_WANT_KEYWORD);
331             return -1;
332         }
333
334         action_attr = gilP_string_to_att(istr_string(keyword));
335         if ((rc = get_action_attribute(inFile, obj, module,
336                                        action, action_attr))
337             < 0)
338         {
339             return_value = rc;
340             break;
341         }
342         abil_loadmsg_set_action_att(NULL);
343     }
344     abil_loadmsg_set_action_att(NULL);
345
346     return return_value;
347 }
348
349
350 /*
351  * Load one action attribute.
352  */
353 static int
354 get_action_attribute(
355                         FILE * inFile, 
356                         ABObj obj,
357                         ABObj module,
358                         ABObj action,
359                         AB_GIL_ATTRIBUTE attr
360 )
361 {
362     int                 return_value = 0;
363     int                 rc = 0; /* r turn code */
364
365     if (abio_get_eof(inFile))
366     {
367         return (abil_print_load_err(ERR_EOF), -1);
368     }
369
370     switch (attr)
371     {
372     case AB_GIL_FROM:
373         rc = get_from(inFile, obj, module, action);
374         break;
375     case AB_GIL_ACTION:
376         rc = get_operation(inFile, action);
377         break;
378     case AB_GIL_TO:
379         rc = get_to(inFile, obj, module, action);
380         break;
381     case AB_GIL_WHEN:
382         rc = get_when(inFile, obj, action);
383         break;
384     case AB_GIL_FUNCTION_TYPE:
385         rc = get_function_type(inFile, action);
386         break;
387     case AB_GIL_ARG_TYPE:
388         rc = get_arg_type(inFile, action);
389         break;
390     default:
391         abil_print_load_err(ERR_UNKNOWN);
392     }
393
394     return return_value;
395 }
396
397 /*
398  * Get the source object.
399  */
400 static int
401 get_from(FILE * inFile, ABObj obj, ABObj module, ABObj action)
402 {
403     int                 return_value = 0;
404     int                 rc = 0; /* r turn code */
405     ISTRING             interface_name = NULL;
406     ISTRING             parent_name = NULL;
407     ISTRING             name = NULL;
408     ISTRING             item_name = NULL;
409     ABObj               from = NULL;
410
411     if (   (abio_gil_get_full_name(inFile, 
412                 &interface_name, &parent_name, &name, &item_name) < 0)
413         || (name == NULL) )
414     {
415         abil_print_load_err(ERR_WANT_FULL_NAME);
416         return_value = -1;
417         goto abort;
418     }
419
420     from = find_or_create_target(obj, module,
421                         interface_name, parent_name, name, item_name);
422
423     if (from == NULL)
424     {
425         rc = abil_print_load_err(ERR_UNKNOWN_OBJECT);
426         goto abort;
427     }
428
429     obj_set_from(action, from);
430
431 abort:
432     istr_destroy(parent_name);
433     istr_destroy(name);
434     istr_destroy(item_name);
435     return return_value;
436 }
437
438
439 /*
440  * Get the destination object.
441  */
442 static int
443 get_to(FILE * inFile, ABObj obj, ABObj module, ABObj action)
444 {
445     int                 return_value = 0;
446     int                 rc = 0; /* r turn code */
447     ISTRING             interface_name = NULL;
448     ISTRING             parent_name = NULL;
449     ISTRING             name = NULL;
450     ISTRING             item_name = NULL;
451     ABObj               to = NULL;
452
453     if (   (abio_gil_get_full_name(inFile,
454                   &interface_name, &parent_name, &name, &item_name) < 0)
455         || (name == NULL) )
456     {
457         abil_print_load_err(ERR_WANT_FULL_NAME);
458         return_value = -1;
459         goto abort;
460     }
461
462     to = find_or_create_target(obj, module, 
463                         interface_name, parent_name, name, item_name);
464
465     if (to == NULL)
466     {
467         rc = abil_print_load_err(ERR_UNKNOWN_OBJECT);
468         goto abort;
469     }
470
471     action->info.action.to = to;
472
473 abort:
474     istr_destroy(parent_name);
475     istr_destroy(name);
476     istr_destroy(item_name);
477     return return_value;
478 }
479
480
481 /*
482  * Get the operation.
483  */
484 static int
485 get_operation(FILE * inFile, ABObj action)
486 {
487     int                 return_value = 0;
488     int                 rc = 0; /* r turn code */
489     ISTRING             string = NULL;
490     ISTRING             name = NULL;
491     int                 intval;
492
493     if (!abio_get_list_begin(inFile))
494     {
495         return (abil_print_load_err(ERR_WANT_LIST), -1);
496     }
497
498     switch (obj_get_func_type(action))
499     {
500     case AB_FUNC_CODE_FRAG:     /* code fragment */
501         if (!abio_get_string(inFile, &string))
502         {
503             rc = abil_print_load_err(ERR_WANT_STRING);
504             goto abort;
505         }
506         obj_set_func_code(action, istr_string(string));
507         break;
508
509     case AB_FUNC_USER_DEF:      /* function name (user defined) */
510         if (!abio_gil_get_name(inFile, &name))
511         {
512             rc = abil_print_load_err(ERR_WANT_NAME);
513             goto abort;
514         }
515         obj_set_func_name(action, istr_string(name));
516         break;
517
518     case AB_FUNC_BUILTIN:       /* predefined function */
519         if (!abio_gil_get_name(inFile, &name))
520         {
521             return (abil_print_load_err(ERR_WANT_NAME), -1);
522         }
523         obj_set_func_builtin(action,
524                           gilP_string_to_builtin_action(istr_string(name)));
525
526         if (obj_get_func_builtin(action) != AB_STDACT_UNDEF)
527         {
528             if (abio_get_list_end(inFile))
529                 return return_value;
530
531             switch (obj_get_arg_type(action))
532             {
533             case AB_ARG_STRING:
534                 if (!abio_get_string(inFile, &string))
535                     return (abil_print_load_err(ERR_WANT_STRING), -1);
536                 obj_set_arg_string(action, istr_string(string));
537                 break;
538             case AB_ARG_INT:
539                 if (!abio_get_integer(inFile, &intval))
540                     return (abil_print_load_err(ERR_WANT_INTEGER), -1);
541                 obj_set_arg_int(action, intval);
542                 break;
543             case AB_ARG_FLOAT:
544                 rc = abil_print_load_err(ERR_UNKNOWN);
545                 break;
546             default:
547                 rc = abil_print_load_err(ERR_WANT_ARG);
548                 break;
549             }
550         }
551
552         break;
553
554     default:
555         break;
556     }
557
558     if (rc < 0)
559     {
560         return_value = rc;
561     }
562     else
563     {
564         if (!abio_get_list_end(inFile))
565         {
566             return (abil_print_load_err(ERR_WANT_LIST), -1);
567         }
568     }
569
570 abort:
571     istr_destroy(string);
572     istr_destroy(name);
573     return return_value;
574 }
575
576 /*
577  * Get the when part of a connection.
578  */
579 static int
580 get_when(FILE * inFile, ABObj obj, ABObj action)
581 {
582     int                 return_value = 0;
583     ISTRING             string = NULL;
584     AB_WHEN             when = AB_WHEN_UNDEF;
585     int                 numWhens = 0;
586
587     if (!abio_get_list_begin(inFile))
588         return (abil_print_load_err(ERR_WANT_LIST), -1);
589
590     while (!abio_get_list_end(inFile))
591     {
592         if (!abio_gil_get_name(inFile, &string))
593             return (abil_print_load_err(ERR_WANT_NAME), -1);
594
595         when = gilP_string_to_when(istr_string(string));
596         if (when == AB_WHEN_UNDEF)
597         {
598             if (util_be_verbose())
599             {
600                 util_printf("WARNING: ignoring unsupported when: %s\n",
601                     istr_string(string));
602             }
603         }
604         else
605         {
606             obj_set_when(action, when);
607             istr_destroy(string);
608             ++numWhens;
609             if (numWhens > 1)
610             {
611                 util_printf_err(
612                     "WARNING: multiple :when values not supported. "
613                     "Using first value\n");
614             }
615         }
616     }
617     return return_value;
618 }
619
620 /*
621  * Get the function_type for an action holder
622  */
623 static int
624 get_function_type(FILE * inFile, ABObj action)
625 {
626     int                 return_value = 0;
627     ISTRING             type_name = NULL;
628
629     if (!abio_gil_get_name(inFile, &type_name))
630     {
631         return (abil_print_load_err(ERR_WANT_KEYWORD), -1);
632     }
633
634     if (istr_equalstr(type_name, "ExecuteCode"))
635     {
636         obj_set_func_type(action, AB_FUNC_CODE_FRAG);
637     }
638     else if (istr_equalstr(type_name, ":user_defined"))
639     {
640         /* yes, :user_defined in GIL means a builtin action */
641         obj_set_func_type(action, AB_FUNC_BUILTIN);
642     }
643     else if (istr_equalstr(type_name, "CallFunction"))
644     {
645         obj_set_func_type(action, AB_FUNC_USER_DEF);
646     }
647     else
648     {
649         return (abil_print_load_err(ERR_WANT_KEYWORD), -1);
650     }
651
652     istr_destroy(type_name);
653     return return_value;
654 }
655
656
657 /*
658  * Get the arg_type of an action_holder
659  */
660 static int
661 get_arg_type(FILE * inFile, ABObj action)
662 {
663     int                 return_value = 0;
664     ISTRING             type_name = NULL;
665
666     obj_set_arg_type(action, AB_ARG_VOID_PTR);
667
668     if (!abio_get_list_begin(inFile))
669         return (abil_print_load_err(ERR_WANT_LIST), -1);
670
671     if (abio_get_list_end(inFile))
672     {
673         return return_value;
674     }
675
676     while (!abio_get_list_end(inFile))
677     {
678         if (!abio_gil_get_name(inFile, &type_name))
679             return (abil_print_load_err(ERR_WANT_NAME), -1);
680
681         obj_set_arg_type(action, 
682                 gilP_string_to_arg_type(istr_string(type_name)));
683     }
684
685     return return_value;
686 }
687
688
689 static int
690 add_user_handler(ABObj obj, ABObj module,
691                  ISTRING handler, AB_WHEN when)
692 {
693     int                 retval = 0;
694     ABObj               project = NULL;
695     ABObj               action = NULL;
696
697     if (handler == NULL)
698     {
699         return 0;
700     }
701     project = obj_get_project(module);
702
703     /*
704      * With "callbacks," the to field is irrelevant.  The target is generally
705      * whatever widget calls the callback, so we set the "to" field to NULL,
706      * so that this action may be used by multiple widgets.  I.e., if the
707      * function type, name and to fields match, an action will be shared.
708      */
709     action = obj_create(AB_TYPE_ACTION, NULL);
710     obj_set_func_type(action, AB_FUNC_USER_DEF);
711     obj_set_func_name(action, istr_string(handler));
712     obj_set_arg_type(action, AB_ARG_VOID_PTR);
713     action->info.action.to = NULL;
714
715     obj_set_from(action, obj);
716     obj_set_when(action, when);
717
718     install_action(obj, module, action);
719     return 0;
720 }
721
722
723 static int
724 install_action(ABObj obj, ABObj module, ABObj action)
725 {
726     int                 return_value = 0;
727
728     /*
729      * Cross-module connections sit under the project
730      * intra-module connectoins sit under the module
731      */
732     return_value = obj_add_action(module, action);
733
734     return return_value;
735 }
736
737
738 /*
739  * Finds the target matching the given description, creating it if necessary.
740  * 
741  * Assumes: strings are pointers to allocated space. Sets strings to NULL, if
742  * the values are used.
743  * 
744  * Assumes that obj may not be in the object tree yet, and may return it as the
745  * target.
746  */
747 static ABObj
748 find_or_create_target(
749                         ABObj   obj, 
750                         ABObj   module,
751                         ISTRING interface_name,
752                         ISTRING parent_name,
753                         ISTRING obj_name,
754                         ISTRING item_label
755 )
756 {
757     ABObj               target = NULL;  /* the real thing, baby! */
758     ABObj               target_project = NULL;
759     char                target_interface_file[MAXPATHLEN+1];
760     char                target_interface_name[GIL_MAX_NAME_SIZE];
761     ABObj               target_module = NULL;
762     char                target_parent_name[GIL_MAX_NAME_SIZE];
763     ABObj               target_parent = NULL;
764     char                target_obj_name[GIL_MAX_NAME_SIZE];
765     ABObj               target_obj = NULL;
766     char                target_item_label[GIL_MAX_NAME_SIZE];
767     ABObj               target_item = NULL;
768     AB_TRAVERSAL        trav;
769     *target_interface_file = 0;
770     *target_interface_name = 0;
771     *target_parent_name = 0;
772     *target_obj_name = 0;
773     *target_item_label = 0;
774    
775     /* must have object name */
776     if (debugging()) 
777     {
778         assert(   (obj_name != NULL)
779                && (obj_is_project(module) || obj_is_module(module)));
780     }
781
782     if (obj_is_project(module))
783     {
784         /* The first string must be an interface file name */
785         if (interface_name != NULL)
786         {
787             util_strncpy(target_interface_file, istr_string(interface_name),
788                         GIL_MAX_NAME_SIZE);
789             if (parent_name != NULL)
790             {
791                 util_strncpy(target_parent_name, istr_string(parent_name),
792                         GIL_MAX_NAME_SIZE);
793             }
794         }
795         else if (parent_name != NULL)
796         {
797             util_strncpy(target_interface_file, istr_string(parent_name),
798                         GIL_MAX_NAME_SIZE);
799         }
800         else
801         {
802             abil_print_load_err(ERR_WANT_FULL_NAME);
803             goto epilogue;
804         }
805
806         /* derive the name from the file name */
807         strcpy(target_interface_name, target_interface_file);
808         {
809             int         len = strlen(target_interface_name);
810             if (    (len >= 2) 
811                 && (   util_streq(&(target_interface_name[len-2]), ".G")
812                     || util_streq(&(target_interface_name[len-2]), ".P")))
813             {
814                 target_interface_name[len-2] = 0;
815             }
816         }
817
818         util_strncpy(target_obj_name, istr_string(obj_name), 
819                         GIL_MAX_NAME_SIZE);
820         if (item_label != NULL)
821         {
822             util_strncpy(target_item_label, istr_string(item_label), 
823                         GIL_MAX_NAME_SIZE);
824         }
825     }
826     else        /* ! obj_is_project() */
827     {
828         if (parent_name != NULL)
829         {
830             /* we have parent name and object name */
831             util_strncpy(target_parent_name, istr_string(parent_name), 
832                         GIL_MAX_NAME_SIZE);
833         }
834
835         util_strncpy(target_obj_name, istr_string(obj_name), 
836                         GIL_MAX_NAME_SIZE);
837         if (item_label != NULL)
838         {
839             /* we have object name and item_label */
840             util_strncpy(target_item_label, istr_string(item_label),
841                 GIL_MAX_NAME_SIZE);
842         }
843      }
844
845      /*
846       * We've got the name broken down into the appropriate pieces.
847       * Now find the actual target.
848       */
849     /*util_dprintf(3, "finding: module:'%s' parent:'%s' obj:'%s' item:'%s'\n",
850         target_interface_name, target_parent_name, 
851         target_obj_name, target_item_label);*/
852     
853
854     /*
855      * Find target project
856      */
857     target_project = obj_get_project(module);
858
859     /*
860      * Find target module
861      */
862     if (util_strempty(target_interface_name))
863     {
864         target_module = module;
865     }
866     else
867     {
868         /* find specified intefarce (module) */
869         for (trav_open(&trav, target_project, AB_TRAV_MODULES);
870                 (target_module = trav_next(&trav)) != NULL; )
871         {
872             if (   (target_module != target_project)
873                 && (util_streq(
874                         obj_get_file(target_module), target_interface_file)))
875             {
876                 break;
877             }
878         }
879         trav_close(&trav);
880         if (target_module == NULL)
881         {
882             target_module = obj_create(AB_TYPE_MODULE, target_project);
883             obj_set_is_defined(target_module, FALSE);
884             obj_set_file(target_module, target_interface_file);
885             obj_set_name(target_module, target_interface_name);
886         }
887     }
888
889     /*
890      * Find target parent
891      */
892     if (util_strempty(target_parent_name))
893     {
894         target_parent = target_module;
895     }
896     else
897     {
898         for (trav_open(&trav, target_module, 
899                         AB_TRAV_ALL | AB_TRAV_MOD_PARENTS_FIRST);
900                 (target_parent = trav_next(&trav)) != NULL; )
901         {
902             if (   (target_parent != target_module)
903                 && (util_streq(
904                         obj_get_name(target_parent), target_parent_name)))
905             {
906                 break;
907             }
908         }
909         trav_close(&trav);
910         if (target_parent == NULL)
911         {
912             target_parent = obj_create(AB_TYPE_UNDEF, target_module);
913             obj_set_is_defined(target_parent, FALSE);
914             obj_set_file(target_parent, target_interface_file);
915             obj_set_name(target_parent, target_parent_name);
916         }
917     }
918
919     /*
920      * Find target obj
921      */
922     for (trav_open(&trav, target_parent,
923                         AB_TRAV_ALL | AB_TRAV_MOD_PARENTS_FIRST);
924                 (target_obj = trav_next(&trav)) != NULL; )
925     {
926         if (   (target_obj != target_parent)
927            && util_streq(target_obj_name, obj_get_name(target_obj)))
928         {
929             break;
930         }
931     }
932     trav_close(&trav);
933     if (target_obj == NULL)
934     {
935         target_obj = obj_create(AB_TYPE_UNDEF, target_parent);
936         obj_set_is_defined(target_obj, FALSE);
937         obj_set_file(target_obj, target_interface_file);
938         obj_set_name(target_obj, target_obj_name);
939     }
940
941     /*
942      * Find item
943      */
944     if (util_strempty(target_item_label))
945     {
946         target_item = NULL;
947     }
948     else
949     {
950         for (trav_open(&trav, target_obj, AB_TRAV_ITEMS);
951                 (target_item = trav_next(&trav)) != NULL; )
952         {
953             if (   (target_item != target_obj)
954                 && util_streq(obj_get_label(target_item), target_item_label))
955             {
956                 break;
957             }
958         }
959         trav_close(&trav);
960         if (target_item == NULL)
961         {
962             target_item = obj_create(AB_TYPE_ITEM, target_obj);
963             obj_set_is_defined(target_item, FALSE);
964             obj_set_file(target_item, target_interface_file);
965             obj_set_label(target_item, target_item_label);
966             obj_set_name_from_label(target_item, 
967                                 obj_get_name(obj_get_parent(target_item)));
968         }
969     }
970
971     if (target_item != NULL)
972     {
973         target = target_item;
974     }
975     else
976     {
977         target = target_obj;
978     }
979
980 epilogue:
981     return target;
982 }
983