Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtappbuilder / src / abmf / abmf.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: abmf.c /main/6 1996/11/21 12:31:02 mustafa $
26  * 
27  * @(#)abmf.c   3.53 16 Feb 1994      cde_app_builder/src/abmf
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 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46 #include <dirent.h>
47 #include <sys/times.h>
48 #include <time.h>
49 #include <limits.h>
50 #include <ctype.h>
51 #include <nl_types.h>
52 #include <ab_private/util.h>
53 #include <ab_private/obj.h>
54 #include <ab_private/objxm.h>
55 #include <ab_private/bil.h>
56 #include "dtb_utils.h"
57 #include "write_codeP.h"
58 #include "motifdefsP.h"
59 #include "argsP.h"
60 #include "lib_func_stringsP.h"
61 #include "instancesP.h"
62 #include "ui_header_fileP.h"
63 #include "abmfP.h"
64 #include "abmf.h"
65
66 #ifdef __cplusplus
67 extern "C" {
68 #endif
69 extern long _sysconf(int name);         /* CLK_TCK uses this */
70 #ifdef __cplusplus
71 } // extern "C"
72 #endif
73
74 typedef enum
75 {
76     ABMF_PROFILE_UNDEF = 0,
77     ABMF_PROFILE_LOAD,
78     ABMF_PROFILE_CONFIG,
79     ABMF_PROFILE_TRAVERSALS,
80     ABMF_PROFILE_WHAT_NUM_VALUES
81 } ABMF_PROFILE_WHAT;
82
83
84 typedef struct
85 {
86     BOOL                        force_load_all;
87     ABMF_PROFILE_WHAT           debug_profile_what;
88     ABMF_CGEN_RESTRICTION       cgen_restriction;
89     BOOL                        dump_tree;
90     StringList                  files;
91     BOOL                        i18n;
92     BOOL                        write_main;
93     BOOL                        show_all_windows;
94     BOOL                        show_all_windows_set;
95     BOOL                        merge_files;
96     ISTRING                     proj_file;
97     BOOL                        prototype_funcs;
98     BOOL                        source_browser;
99     BOOL                        use_default_project;
100     int                         verbosity;
101     BOOL                        write_all_resources;
102     BOOL                        write_i18n_resources;
103 } CmdlineArgsRec, *CmdlineArgs;
104
105 BOOL    freshenUnchangedFiles = TRUE;
106
107 /*
108  * Private Functions
109  */
110 static int      abmf_init(void);
111 static int      abmf_usage(void);
112 static int      parse_args(int argc, char *argv[], CmdlineArgs args);
113 static int      find_proj_file(CmdlineArgs args);
114 static int      mark_modules_to_load_and_write(
115                         ABObj           project, 
116                         BOOL            loadAllModules, 
117                         BOOL            genAllModules, 
118                         BOOL            genNoModules,
119                         StringList      fileNames
120                 );
121 static int      load_marked_modules(ABObj project);
122 static int      load_module(ABObj module);
123 static BOOL     write_required(ABObj tree);
124 static int      examine_tree(ABObj project);
125 static int      munge_ensure_win_parent(ABObj win);
126 static int      munge_liberate_menu(ABObj menu);
127 static int      dup_all_menu_refs(ABObj project);
128 static int      abmfP_dup_menu_ref_tree(ABObj obj);
129 static int      abmfP_do_dup_menu_ref_tree(ABObj obj);
130 static int      dump_tree(ABObj tree);
131 static int      print_tree(ABObj root, int indent);
132 static int      abmfP_prepare_tree(ABObj project);
133 static int      abmfP_create_obj_data_for_project(ABObj project);
134 static int      abmfP_create_obj_data_for_module(ABObj objInModule);
135 static int      ensure_data_for_module_obj(ABObj module);
136 static BOOL     proj_file_has_modules(
137                         STRING          projFileName, 
138                         StringList      fileNames
139                 );
140 static int      replace_string_shorter(
141                         STRING buf, 
142                         STRING subStr, 
143                         STRING replaceStr
144                 );
145
146
147
148 /*
149  * Debugging routines
150  */
151 #ifdef DEBUG
152 static int      dump_callbacks(ABObj project);
153 static int      debug_verify_tree(ABObj root);
154 #endif /* DEBUG */
155
156 #ifdef DEBUG    /* performance testing */
157 static int      time_traversal(ABObj root);
158 static int      get_cur_time(double *realTimeOut, double *cpuTimeOut);
159 #endif /* DEBUG */
160
161
162 /* Internationalization defines */
163 nl_catd Dtb_project_catd;
164
165 /* Workaround for XPG4 API compatibility */
166 #if !defined(NL_CAT_LOCALE)
167 #define NL_CAT_LOCALE 0
168 #endif
169
170
171 /* ARGSUSED */
172 main(int argc, STRING *argv)
173 {
174     int                 exitValue = 0;
175     int                 iRC= 0;         /* int return code */
176     CmdlineArgsRec      cmdlineRec;
177     CmdlineArgs         cmdline = &cmdlineRec;
178     ABObj               project = NULL;
179     ABObj               module = NULL;
180     int                 num_modules_processed = 0;
181     BOOL                genAllFiles = FALSE;
182     BOOL                genMain = FALSE;
183     BOOL                genMainOnly = FALSE;
184     BOOL                useDefaultProject = FALSE;
185     BOOL                showAllWindows = FALSE;
186     STRING              errmsg = NULL;
187
188 #ifdef DEBUG    /* performance testing */
189     double              progStartSeconds = 0.0;
190     double              progEndSeconds = 0.0;
191     double              progSeconds = 0.0;
192     double              progStartCPUSeconds = 0.0;
193     double              progEndCPUSeconds = 0.0;
194     double              progCPUSeconds = 0.0;
195     double              configStartSeconds = 0.0;
196     double              configEndSeconds = 0.0;
197     double              configSeconds = 0.0;
198     double              configStartCPUSeconds = 0.0;
199     double              configEndCPUSeconds = 0.0;
200     double              configCPUSeconds = 0.0;
201     double              loadStartSeconds = 0.0;
202     double              loadEndSeconds = 0.0;
203     double              loadSeconds = 0.0;
204     double              loadStartCPUSeconds = 0.0;
205     double              loadEndCPUSeconds = 0.0;
206     double              loadCPUSeconds = 0.0;
207     double              startupStartSeconds = 0.0;
208     double              startupEndSeconds = 0.0;
209     double              startupSeconds = 0.0;
210     double              startupStartCPUSeconds = 0.0;
211     double              startupEndCPUSeconds = 0.0;
212     double              startupCPUSeconds = 0.0;
213     get_cur_time(&progStartSeconds, &progStartCPUSeconds);
214     startupStartSeconds = loadStartSeconds = configStartSeconds
215                                 = progStartSeconds;
216     startupStartCPUSeconds = loadStartCPUSeconds = configStartCPUSeconds
217                                 = progStartCPUSeconds;
218 #endif /* DEBUG */
219
220     /*
221      * Open the standard message catalog for the project.
222      */
223     Dtb_project_catd = catopen("dtcodegen", NL_CAT_LOCALE);
224     if (Dtb_project_catd == (nl_catd)-1)
225     {
226         fprintf(stderr, 
227             "WARNING: Could not open message catalog: dtcodegen.cat\n");
228     }
229
230     util_init(&argc, &argv);
231     dtb_save_command(argv[0]);
232     objxm_init(NULL);
233     abmf_init();
234
235     if ((iRC = parse_args(argc, argv, cmdline)) < 0)
236     {
237         exit(1);
238     }
239     util_set_verbosity(cmdline->verbosity);
240
241     /*********************************************************************
242      **                                                                 **
243      **          Figure out what the user wants                         **
244      **                                                                 **
245      *********************************************************************/
246
247     /*
248      * Find the project file
249      */
250     if (cmdline->use_default_project)
251     {
252         useDefaultProject = TRUE;
253     }
254     else if (cmdline->proj_file == NULL)
255     {
256         int numProjFiles = find_proj_file(cmdline);
257         if (cmdline->proj_file == NULL)
258         {
259             if (!strlist_is_empty(cmdline->files))
260             {
261                 useDefaultProject = TRUE;
262                 if (!util_be_silent())
263                 {
264                     util_printf(
265                         catgets(Dtb_project_catd, 1, 1,
266             "No project file that references module(s) - using defaults\n"));
267                 }
268             }
269             else if (numProjFiles == 0)
270             {
271                 util_printf(
272                     catgets(Dtb_project_catd, 1, 2,
273                       "No files specified, and no project file found\n"));
274                 abmf_usage();
275             }
276             else
277             {
278                 /* assume find_proj_file() complained sufficiently */
279                 exit(1);
280             }
281         }
282     }
283
284     genMain = FALSE;
285     genMainOnly = FALSE;
286     genAllFiles = FALSE;
287     if (strlist_is_empty(cmdline->files))
288     {
289         if (cmdline->write_main)
290         {
291             /* only -main was specified */
292             genMain = TRUE;
293             genMainOnly = TRUE;
294         }
295         else
296         {
297             /* no specific files requested - gen them all */
298             genAllFiles = TRUE;
299             genMain = TRUE;
300         }
301     }
302     else
303     {
304         /* files specified */
305         if (cmdline->write_main)
306         {
307             genMain = TRUE;
308             if (useDefaultProject)
309             {
310                 /* dtcodegen -np module.bil -main : only gen main */
311                 genMainOnly = TRUE;
312             }
313         }
314         else
315         {
316             if (useDefaultProject)
317             {
318                 genAllFiles = TRUE;
319                 genMain = TRUE;
320             }
321         }
322     }
323
324     if (cmdline->show_all_windows_set)
325     {
326         showAllWindows = cmdline->show_all_windows;
327     }
328     else if (useDefaultProject)
329     {
330         /* user did not override, so we're going to set show_all_windows */
331         showAllWindows = TRUE;
332     }
333
334     util_dprintf(1, "main:%d mainonly:%d all:%d defaultproj:%d showall:%d\n",
335         genMain, genMainOnly, genAllFiles, useDefaultProject, showAllWindows);
336
337     if ((!util_be_silent()) && (cmdline->proj_file != NULL))
338     {
339         char *proj_file_name = istr_string_safe(cmdline->proj_file);
340         util_printf(
341             catgets(Dtb_project_catd, 1, 3, "Reading project %s.\n"),
342                 proj_file_name);
343     }
344
345 #ifdef DEBUG    /* performance testing */
346     get_cur_time(&loadStartSeconds, &loadStartCPUSeconds);
347 #endif
348
349     /*********************************************************************
350      **                                                                 **
351      **                 Load or create the project                      **
352      **                                                                 **
353      *********************************************************************/
354
355     if (cmdline->proj_file != NULL)
356     {
357         /* project = bil_load_file(istr_string(cmdline->proj_file), NULL, project);
358         assert(project != NULL); */
359
360         iRC = bil_load_file_and_resolve_all(
361                                 istr_string(cmdline->proj_file), NULL, &project);
362         if (iRC < 0)
363         {
364             exitValue = 1;
365             goto epilogue;
366         }
367     }
368
369     if (useDefaultProject)
370     {
371         int     i = 0;
372         int     numModuleFiles = 0;
373         STRING  moduleFileName = NULL;
374         ABObj   fileObj = NULL;
375         char    *dotPtr = NULL;
376         char    projNameBuf[1024];
377         *projNameBuf = 0;
378
379         /*
380          * Create the default project
381          */
382         if (project != NULL)
383         {
384             ABObj oldProject = project;
385             project = obj_create(AB_TYPE_PROJECT, NULL);
386             obj_move_children(project, oldProject);
387             obj_destroy(oldProject);
388         }
389         else
390         {
391             project = obj_create(AB_TYPE_PROJECT, NULL);
392         }
393         util_strncpy(projNameBuf, 
394                         strlist_get_str(cmdline->files, 0, NULL), 1024);
395         dotPtr = strrchr(projNameBuf, '.');
396         if (dotPtr != NULL)
397         {
398             *dotPtr = 0;
399         }
400         obj_set_name(project, projNameBuf);
401         obj_set_file(project, strlist_get_str(cmdline->files, 0, NULL));
402         obj_set_is_default(project, TRUE);
403
404         /*
405          * Create "files" to get converted to undefined modules
406          */
407         numModuleFiles = strlist_get_num_strs(cmdline->files);
408         for (i = 0; i < numModuleFiles; ++i)
409         {
410             moduleFileName = strlist_get_str(cmdline->files, i, NULL);
411             fileObj = obj_create(AB_TYPE_FILE, project);
412             obj_set_file(fileObj, moduleFileName);
413         }
414     }
415
416     /*
417      * Load the appropriate files
418      */
419     if (genMain)
420     {
421         mfobj_set_flags(project, CGenFlagLoadMe|CGenFlagIsReferenced);
422         obj_set_write_me(project, TRUE);
423     }
424     mark_modules_to_load_and_write(
425         project, cmdline->force_load_all, genAllFiles, genMainOnly, cmdline->files);
426     load_marked_modules(project);
427
428 #ifdef DEBUG    /* performance testing */
429     get_cur_time(&loadEndSeconds, &loadEndCPUSeconds);
430     loadSeconds = loadEndSeconds - loadStartSeconds;
431     loadCPUSeconds = loadEndCPUSeconds - loadStartCPUSeconds;
432     printf("load real:%lg  CPU:%lg\n", loadSeconds, loadCPUSeconds);
433 #endif /* DEBUG */
434
435     if (iRC < 0)
436     {
437         char *prog_name_string = util_get_program_name();
438
439         fprintf(stderr, 
440             catgets(Dtb_project_catd, 1, 4,
441                 "%s: exiting due to error loading project.\n"), 
442                 prog_name_string);
443         exit(1);
444     }
445     if (cmdline->debug_profile_what == ABMF_PROFILE_LOAD)
446     {
447         exit(0);
448     }
449
450     /*
451      * See if we actually have anything to write
452      */
453     if (!write_required(project))
454     {
455         char *prog_name_string = util_get_program_name();
456
457         fprintf(stderr, 
458             catgets(Dtb_project_catd, 1, 5,
459               "%s: Nothing to do!\n"), prog_name_string);
460         exit(1);
461     }
462
463     /*
464      * Configure the raw objects into AB objects
465      */
466     if (showAllWindows)
467     {
468         ABObj   window = NULL;
469         AB_TRAVERSAL    trav;
470         for (trav_open(&trav, project, AB_TRAV_WINDOWS);
471             (window = trav_next(&trav)) != NULL; )
472         {
473             obj_set_is_initially_visible(window, TRUE);
474         }
475         trav_close(&trav);
476     }
477
478 #ifdef DEBUG    /* performance testing */
479     get_cur_time(&configStartSeconds, &configStartCPUSeconds);
480 #endif
481
482     examine_tree(project);
483
484 #ifdef DEBUG    /* performance testing */
485     get_cur_time(&configEndSeconds, &configEndCPUSeconds);
486     configSeconds = configEndSeconds - configStartSeconds;
487     configCPUSeconds = configEndCPUSeconds - configStartCPUSeconds;
488     get_cur_time(&startupEndSeconds, &startupEndCPUSeconds);
489     startupSeconds = startupEndSeconds - startupStartSeconds;
490     startupCPUSeconds = startupEndCPUSeconds - startupStartCPUSeconds;
491
492     /*
493      * Print out startup stats (if debugging build)
494      */
495     util_printf("Startup real time: %lg s (%lg s load, %lg s config)\n",
496                 startupSeconds, loadSeconds, configSeconds);
497     util_printf("Startup CPU time: %lg s (%lg s load, %lg s config)\n",
498                 startupCPUSeconds, loadCPUSeconds, configCPUSeconds);
499 #endif /* DEBUG */
500
501 #ifdef DEBUG
502     util_dprintf(1, "after configure_tree\n");
503     debug_verify_tree(project);
504 #endif /* DEBUG */
505
506     /*
507      * The tree has been loaded, examined, mangled, and generally messed with.
508      * Now, do what the user has requested.
509      */
510
511 #ifdef DEBUG
512     /* make sure we didn't muss anything up */
513     if (debugging())
514     {
515         int     numObjs = trav_count(project, AB_TRAV_ALL);
516         obj_tree_verify(project);
517         if (   ((debug_level() >= 10) || ((25*debug_level()) >= numObjs))
518             && (!cmdline->dump_tree))
519         {
520             objxm_tree_print(project);
521         }
522     }
523 #endif /* DEBUG */
524
525     if (cmdline->dump_tree)
526     {
527         dump_tree(project);
528     }
529     else
530     {
531         AB_ARG_CLASS_FLAGS dumpedRes = obj_get_res_file_arg_classes(project);
532         ABMF_I18N_METHOD   i18n_method = ABMF_I18N_NONE;
533
534         if (obj_get_i18n_enabled(project))
535             i18n_method = ABMF_I18N_XPG4_API;
536
537         /*
538          * Generate the code!
539          */
540         iRC = abmf_generate_code(
541                          project,
542                          cmdline->cgen_restriction,
543                          cmdline->merge_files,
544                          i18n_method,
545                          cmdline->prototype_funcs,
546                          dumpedRes
547             );
548         if (iRC < 0)
549         {
550             exitValue = 1;
551         }
552     }
553
554 #ifdef DEBUG    /* performance testing */
555     get_cur_time(&progEndSeconds, &progEndCPUSeconds);
556     progSeconds = progEndSeconds - progStartSeconds;
557     progCPUSeconds = progEndCPUSeconds - progStartCPUSeconds;
558     util_printf("Total real time: %lg s   CPU time: %lg s\n",
559         progSeconds, progCPUSeconds);
560 #endif /* DEBUG */
561
562 epilogue:
563 #ifdef DEBUG
564     debug_verify_tree(project);
565 #endif /* DEBUG */
566
567     return exitValue;
568 }
569
570
571 static int
572 parse_args(int argc, char *argv[], CmdlineArgs cmdline)
573 {
574     int                 iReturn = 0;
575     int                 argCount = 0;
576
577     /*
578      * Set default values
579      */
580     cmdline->force_load_all = TRUE;
581     cmdline->debug_profile_what = ABMF_PROFILE_UNDEF;
582     cmdline->cgen_restriction = ABMF_CGEN_ALL;
583     cmdline->dump_tree = FALSE;
584     cmdline->files = strlist_create();
585     cmdline->i18n = FALSE;
586     cmdline->show_all_windows = FALSE;
587     cmdline->show_all_windows_set = FALSE;
588     cmdline->write_main = FALSE;
589     cmdline->merge_files = TRUE;
590     cmdline->proj_file = NULL;
591     cmdline->prototype_funcs = TRUE;
592     cmdline->source_browser = FALSE;
593     cmdline->use_default_project = FALSE;
594     cmdline->verbosity = util_get_verbosity();
595     cmdline->write_all_resources = FALSE;
596     cmdline->write_i18n_resources = FALSE;
597
598     for (argCount = 1; argCount < argc; ++argCount)
599     {
600         char               *arg = argv[argCount];
601         if (*arg == '-')
602         {
603             if (strcmp(arg, "-s") == 0 ||
604                 strcmp(arg, "-silent") == 0)
605             {
606                 cmdline->verbosity = 0;
607             }
608             else if (strcmp(arg, "-a") == 0 ||
609                      strcmp(arg, "-ansi") == 0)
610             {
611                 cmdline->prototype_funcs = TRUE;
612             }
613             else if (util_streq(arg, "-freshen"))
614             {
615                 freshenUnchangedFiles = TRUE;
616             }
617             else if (util_streq(arg, "-nofreshen"))
618             {
619                 freshenUnchangedFiles = FALSE;
620             }
621 #ifdef DEBUG
622             else if (util_streq(arg, "-tree"))
623             {
624                 cmdline->dump_tree = TRUE;
625             }
626 #endif /* DEBUG */
627             else if (util_streq(arg, "-changed"))
628             {
629                 cmdline->cgen_restriction = ABMF_CGEN_BY_DATE;
630             }
631             else if (strcmp(arg, "-k") == 0 ||
632                      strcmp(arg, "-kandr") == 0)
633             {
634                 cmdline->prototype_funcs = FALSE;
635             }
636             else if (strcmp(arg, "-main") == 0)
637             {
638                 cmdline->write_main = TRUE;
639             }
640             else if (util_streq(arg, "-showall"))
641             {
642                 cmdline->show_all_windows = TRUE;
643                 cmdline->show_all_windows_set = TRUE;
644             }
645             else if (util_streq(arg, "-noshowall"))
646             {
647                 cmdline->show_all_windows = FALSE;
648                 cmdline->show_all_windows_set = TRUE;
649             }
650             else if (util_streq(arg, "-merge"))
651             {
652                 cmdline->merge_files = TRUE;
653             }
654             else if (util_streq(arg, "-nomerge"))
655             {
656                 cmdline->merge_files = FALSE;
657             }
658             else if (strcmp(arg, "-P") == 0 ||
659                      strcmp(arg, "-p") == 0 ||
660                      strcmp(arg, "-project") == 0)
661             {
662                 if ((argCount + 1) >= argc)
663                 {
664                     util_error( catgets(Dtb_project_catd, 1, 6,
665                     "Missing project name for -p option"));
666                     abmf_usage();
667                 }
668                 else
669                 {
670
671                     /*
672                      * get the project file name
673                      */
674                     STRING      projArg;
675                     ++argCount;
676                     projArg= argv[argCount];
677                     if (   util_file_name_has_extension(projArg, "bip")
678                         || util_file_name_has_extension(projArg, "bix"))
679                     {
680                         cmdline->proj_file = istr_const(projArg);
681                     }
682                     else
683                     {
684                         char                projFile[MAX_PATH_SIZE];
685                         sprintf(projFile, "%s.bip", projArg);
686                         if (!util_file_exists(projFile))
687                         {
688                             char        encapsFile[MAXPATHLEN];
689                             sprintf(encapsFile, "%s.bix", projArg);
690                             if (util_file_exists(encapsFile))
691                             {
692                                 strcpy(projFile, encapsFile);
693                             }
694                         }
695                         cmdline->proj_file = istr_create(projFile);
696                     }
697                 }
698             }
699             else if (   util_streq(arg, "-np")
700                      || util_streq(arg, "-noproject"))
701             {
702                 cmdline->use_default_project = TRUE;
703             }
704             else if (strcmp(arg, "-help") == 0)
705             {
706                 abmf_usage();
707             }
708             else if (strcmp(arg, "-i") == 0 ||
709                      strcmp(arg, "-i18n") == 0)
710             {
711                 cmdline->i18n = TRUE;
712             }
713             else if (strcmp(arg, "-r") == 0 ||
714                      strcmp(arg, "-resources") == 0)
715             {
716                 cmdline->write_all_resources = TRUE;
717             }
718             else if (strcmp(arg, "-sb") == 0)
719             {
720                 cmdline->source_browser = TRUE;
721             }
722             else if (strncmp(arg, "-v", 2) == 0)
723             {
724                 cmdline->verbosity = 2;
725             }
726
727             /* 
728              * debugging options 
729              */
730 #ifdef DEBUG
731             else if (strncmp(arg, "-V", 2) == 0)
732             {
733                 int                 i;
734                 for (i = 1; arg[i] == 'V'; ++i) 
735                     { /* empty */ }
736                 --i;
737                 cmdline->verbosity = i;
738             }
739             else if (strncmp(arg, "-time", 5) == 0)
740             {
741                 if (argCount < (argc-1))
742                 {
743                     arg = argv[++argCount];
744                     if (util_streq(arg, "load"))
745                     {
746                         cmdline->debug_profile_what = ABMF_PROFILE_LOAD;
747                     }
748                 }
749             }
750             else if (strncmp(arg, "-loadall", 8) == 0)
751             {
752                 cmdline->force_load_all = TRUE;
753             }
754 #endif /* DEBUG */
755             else
756             {
757                 char *prog_name_string = util_get_program_name();
758
759                 fprintf(stderr, catgets(Dtb_project_catd, 1, 7,
760                     "%s: Illegal option \"%s\"\n\n"), prog_name_string, arg);
761                 abmf_usage();
762             }
763
764         }                       /* arg == '-' */
765         else
766         {
767
768             /*
769              * It's a file name
770              */
771             if (   util_file_name_has_extension(arg, "bip")
772                 || util_file_name_has_extension(arg, "bix") )
773             {
774                 if (cmdline->proj_file != NULL)
775                 {
776                     util_error(
777                         catgets(Dtb_project_catd, 1, 8,
778                     "Only one project file may be specified."));
779                     abmf_usage();
780                 }
781                 else
782                 {
783                     cmdline->proj_file = istr_const(arg);
784                 }
785             }
786             else
787             {
788                 ISTRING             newFile = NULL;
789
790                 if (util_file_name_has_ab_extension(arg))
791                 {
792                     newFile = istr_const(arg);
793                 }
794                 else
795                 {
796                     char                fileName[MAX_PATH_SIZE];
797                     strcpy(fileName, arg);
798                     strcat(fileName, ".bil");
799                     newFile = istr_create(fileName);
800                 }
801
802                 strlist_add_istr(cmdline->files, newFile, NULL);
803             }                   /* not project file */
804         }                       /* ! flag arg */
805     } /* for argCount */
806
807
808     /*
809      * Make the comand-line args consistent
810      */
811     if (cmdline->use_default_project && (cmdline->proj_file != NULL))
812     {
813         char *proj_file_name = istr_string_safe(cmdline->proj_file);
814
815         util_printf_err(
816           catgets(Dtb_project_catd, 1, 9,
817           "ignoring -noproject (-np) because project file was specified: %s\n"),
818                proj_file_name);
819         cmdline->use_default_project = FALSE;
820     }
821
822     return iReturn;
823 }
824
825
826 static int
827 mark_modules_to_load_and_write(
828                         ABObj           project, 
829                         BOOL            loadAllModules, 
830                         BOOL            genAllModules,
831                         BOOL            genNoModules,
832                         StringList      fileNames
833 )
834 {
835     int                 return_value = 0;
836     AB_TRAVERSAL        fileTrav;
837     ABObj               file = NULL;
838     ISTRING             fileName = NULL;
839     char                newModuleName[1024];
840     STRING              dotPtr = NULL;
841     AB_TRAVERSAL        allTrav;
842     ABObj               obj = NULL;
843     ABObj               obj1 = NULL;
844     ABObj               obj2 = NULL;
845     AB_TRAVERSAL        moduleTrav;
846     ABObj               module = NULL;
847     ABObj               winParent = NULL;
848     *newModuleName = 0;
849
850     /*
851      * Convert remaining files into undefined modules
852      */
853     for (trav_open(&fileTrav, project, AB_TRAV_FILES | AB_TRAV_MOD_SAFE);
854         (file = trav_next(&fileTrav)) != NULL; )
855     {
856         fileName = istr_create(obj_get_file(file));
857         util_get_file_name_from_path(
858                         istr_string(fileName), newModuleName, 1024);
859         dotPtr = strrchr(newModuleName, '.');
860         if (dotPtr != NULL)
861         {
862             *dotPtr = 0;
863         }
864
865         module = obj_find_module_by_name(project, newModuleName);
866         if (module != NULL)
867         {
868             /* this module already exists, probably because of a forward */
869             /* reference */
870             obj_destroy(file);
871         }
872         else
873         {
874             obj_set_type(file, AB_TYPE_MODULE);
875             module = file; file = NULL;
876             obj_set_name(module, newModuleName);
877             obj_set_is_defined(module, FALSE);
878             mfobj_set_flags(module, CGenFlagLoadMe|CGenFlagIsReferenced);
879         }
880
881         /*
882          * Objects/modules created as a forward reference will
883          * not have their file names set, so we're going to
884          * check it.
885          */
886         if (obj_get_file(module) == NULL)
887         {
888             obj_set_file(module, istr_string(fileName));
889         }
890         istr_destroy(fileName);
891
892         load_module(module);
893     }
894     trav_close(&fileTrav);
895
896
897     /*
898      * Mark the modules that are to be written
899      */
900     {
901         char    explodedModuleFile[MAXPATHLEN+1];
902         *explodedModuleFile = 0;
903
904         for (trav_open(&moduleTrav, project, AB_TRAV_MODULES|AB_TRAV_MOD_SAFE);
905             (module = trav_next(&moduleTrav)) != NULL; )
906         {
907             sprintf(explodedModuleFile, "%s.bil", obj_get_name(module));
908
909             if ((genAllModules && obj_is_defined(module)) ||
910                 (strlist_str_exists(fileNames, explodedModuleFile) && (!genNoModules)))
911             {
912                 if (obj_is_defined(module))     /* must be defined!! */
913                 {
914                     strlist_set_str_data(fileNames, explodedModuleFile, (void*)TRUE);
915                     obj_set_write_me(module, TRUE);
916                 }
917             }
918         }
919
920         trav_close(&moduleTrav);
921     }
922
923     /*
924      * Make sure all the modules on the command line were found
925      */
926     {
927         int     i = 0;
928         int     numFiles = strlist_get_num_strs(fileNames);
929         STRING  fileName = NULL;
930         BOOL    wasFound = FALSE;
931         void    *wasFoundVoidPtr;
932         BOOL    errOccurred = FALSE;
933         for (i = 0; i < numFiles; ++i)
934         {
935             fileName = strlist_get_str(fileNames, i, &wasFoundVoidPtr);
936             assert(fileName != NULL);
937             wasFound = (BOOL)(unsigned)wasFoundVoidPtr;
938             if (!wasFound)
939             {
940                 util_printf_err("module not found in project: %s\n", fileName);
941                 errOccurred = TRUE;
942             }
943         }
944         if (errOccurred)
945         {
946             exit(1);
947         }
948     }
949
950     /*
951      * Determine dependencies necessary to write the requested modules
952      */
953     /* if loadAll... */
954     {
955         for (trav_open(&allTrav, project, AB_TRAV_ALL | AB_TRAV_MOD_SAFE);
956             (obj = trav_next(&allTrav)) != NULL; )
957         {
958             switch (obj_get_type(obj))
959             {
960             case AB_TYPE_MODULE:
961                 if (obj_get_write_me(obj))
962                 {
963                     mfobj_set_flags(obj, CGenFlagIsReferenced);
964                 }
965             break;
966     
967             /*
968              * win-parent can be in another module
969              */
970             case AB_TYPE_DIALOG:
971             case AB_TYPE_BASE_WINDOW:
972                 if (   obj_is_defined(obj)
973                     && obj_is_popup(obj)
974                     && obj_get_write_me(obj_get_module(obj)))
975                 {
976                     if ((winParent = obj_get_win_parent(obj)) != NULL)
977                     {
978                         mfobj_set_flags(obj_get_module(winParent), 
979                                         CGenFlagIsReferenced);
980                     }
981                 }
982
983                 /* visible windows must be loaded to write main */
984                 if (   obj_get_write_me(project)
985                     && obj_is_defined(obj) && obj_is_initially_visible(obj))
986                 {
987                     mfobj_set_flags(obj_get_module(obj), 
988                                         CGenFlagIsReferenced);
989                 }
990             break;
991     
992             /*
993              *
994              */
995             case AB_TYPE_ACTION:
996                 obj1 = obj_get_from(obj);
997                 if (obj_is_project(obj1))
998                     break;
999                 obj2 = obj_get_to(obj);
1000                 if (  (   (obj1 != NULL) 
1001                        && obj_is_defined(obj1)
1002                        && obj_get_write_me(obj_get_module(obj1)))
1003                     ||(   (obj2 != NULL) 
1004                        && obj_is_defined(obj2)
1005                        && obj_get_write_me(obj_get_module(obj2)))
1006                    )
1007                 {
1008                         /*
1009                          * At least one object will be written, make sure
1010                          * both have data.
1011                          */
1012                         if (obj1 != NULL)
1013                         {
1014                             mfobj_set_flags((obj_get_module(obj1)), 
1015                                         CGenFlagIsReferenced);
1016                         }
1017                         if (obj2 != NULL)
1018                         {
1019                             mfobj_set_flags((obj_get_module(obj2)), 
1020                                          CGenFlagIsReferenced);
1021                         }
1022                 }
1023
1024                 /*
1025                  * to/from of cross-module conns must be available to write
1026                  * main
1027                  */
1028                 if (   obj_get_write_me(project)
1029                     && obj_is_defined(obj)
1030                     && obj_is_cross_module(obj))
1031                 {
1032                         if ((obj1 != NULL) && obj_is_defined(obj1))
1033                         {
1034                             mfobj_set_flags((obj_get_module(obj1)), 
1035                                         CGenFlagIsReferenced);
1036                         }
1037                         if ((obj2 != NULL) && obj_is_defined(obj2))
1038                         {
1039                             mfobj_set_flags((obj_get_module(obj2)), 
1040                                          CGenFlagIsReferenced);
1041                         }
1042                 }
1043             break;
1044             }
1045         }
1046         trav_close(&allTrav);
1047     }
1048
1049     return 0;
1050 }
1051
1052
1053 static int
1054 load_marked_modules(ABObj project)
1055 {
1056     ABObj               module = NULL;
1057     AB_TRAVERSAL        moduleTrav;
1058     char        fileName[MAXPATHLEN+1] = "";
1059
1060     for (trav_open(&moduleTrav, project, AB_TRAV_MODULES|AB_TRAV_MOD_SAFE);
1061         (module = trav_next(&moduleTrav)) != NULL; )
1062     {
1063         if (   mfobj_has_flags(module, CGenFlagLoadMe) 
1064             && (!obj_is_defined(module)))
1065         {
1066             load_module(module);
1067         }
1068     }
1069     trav_close(&moduleTrav);
1070
1071     return 0;
1072 }
1073
1074
1075 static int
1076 load_module(ABObj module)
1077 {
1078     char        fileName[MAXPATHLEN+1];
1079     ABObj       newProject = NULL;
1080     ABObj       project = obj_get_project(module);
1081     *fileName = 0;
1082
1083         if (obj_get_file(module) != NULL)
1084         {
1085             strcpy(fileName, obj_get_file(module));
1086         }
1087         else
1088         {
1089             strcpy(fileName, obj_get_name(module));
1090             if (!util_file_name_has_ab_extension(fileName))
1091             {
1092                 strcat(fileName, ".bil");
1093             }
1094         }
1095
1096         newProject = bil_load_file(fileName, NULL, project, NULL);
1097         if (newProject == NULL)
1098         {
1099             /* a failure ocurred. The error has already been reported */
1100             exit(1);
1101         }
1102         else if (newProject != project)
1103         {
1104             util_printf_err(
1105             catgets(Dtb_project_catd, 1, 10,
1106                      "Unexpected project in file %s. Aborting\n"), fileName);
1107             exit(1);
1108         }
1109         if (!obj_is_defined(module))
1110         {
1111             char *module_name_string = obj_get_name(module);
1112     
1113             util_printf_err(
1114                     catgets(Dtb_project_catd, 1, 11,
1115                         "Module %s not found in file %s. Aborting\n"),
1116                         module_name_string, fileName);
1117             exit(1);
1118         }
1119
1120     return 0;
1121 }
1122
1123
1124 /*
1125  * Print usage message
1126  */
1127 static int
1128 abmf_usage(void)
1129 {
1130     char *program_name_string = util_get_program_name();
1131
1132     fprintf(stderr,"\n");
1133     fprintf(stderr,
1134        catgets(Dtb_project_catd, 1, 12,
1135 "Usage: %s [options] [project-file] [module-file [module-file] ...]\n\n"), 
1136         program_name_string);
1137
1138     fprintf(stderr, catgets(Dtb_project_catd, 1, 13,
1139 "Code is generated for each module specified on the command line, or for\n"));
1140     fprintf(stderr, catgets(Dtb_project_catd, 1, 14,
1141 "all modules in the project, if no modules are specified. If no project\n"));
1142     fprintf(stderr, catgets(Dtb_project_catd, 1, 15,
1143 "file is specified, a project file containing the specified module(s) is\n"));
1144     fprintf(stderr, catgets(Dtb_project_catd, 1, 16,
1145 "searched for in the current directory.\n\n"));
1146
1147     fprintf(stderr, catgets(Dtb_project_catd, 1, 17,
1148 "Files with extension .bip are assumend to be BIL project files, files with\n"));
1149     fprintf(stderr, catgets(Dtb_project_catd, 1, 18,
1150 ".bix extenstion are assumed to be encapsulated BIL files, and files\n"));
1151     fprintf(stderr, catgets(Dtb_project_catd, 1, 19,
1152 "With a .bil extension are assumed to be BIL module files.\n\n"));
1153
1154     fprintf(stderr, catgets(Dtb_project_catd, 1, 20,
1155 "Options (* = default, + = default with no project file):\n"));
1156     fprintf(stderr, catgets(Dtb_project_catd, 1, 21,
1157 "  -help (-h)        Print out this help message\n"));
1158     fprintf(stderr, catgets(Dtb_project_catd, 1, 22,
1159 "  -main             Write file containing main()\n"));
1160     fprintf(stderr, catgets(Dtb_project_catd, 1, 23,
1161 "  -changed          Only generate files that have changed\n"));
1162     fprintf(stderr, catgets(Dtb_project_catd, 1, 24,
1163 "* -merge            Merge generated _stubs.c files with previous version\n"));
1164     fprintf(stderr, catgets(Dtb_project_catd, 1, 25,
1165 "  -nomerge          Don't merge existing and new stubs file\n"));
1166     fprintf(stderr, catgets(Dtb_project_catd, 1, 26,
1167 "* -project (-p)     Specify a project to generate code for\n"));
1168     fprintf(stderr, catgets(Dtb_project_catd, 1, 27,
1169 "  -noproject (-np)  Use default project settings, ignore project file\n"));
1170     fprintf(stderr, catgets(Dtb_project_catd, 1, 28,
1171 "+ -showall          Application shows (maps) all windows at startup\n"));
1172     fprintf(stderr, catgets(Dtb_project_catd, 1, 29,
1173 "* -noshowall        Application shows (maps) only initially-visible windows\n"));
1174     fprintf(stderr, catgets(Dtb_project_catd, 1, 30,
1175 "  -silent (-s)      Silent mode, no messages written\n"));
1176     fprintf(stderr, catgets(Dtb_project_catd, 1, 31,
1177 "  -verbose (-v)     Verbose mode, detailed progress messages\n\n"));
1178
1179
1180 /* "-a (-ansi)      Write ANSI C code\n" */
1181 /* "-k (-kandr)     Write K&R C code, no function prototypes\n" */
1182 /* "-i (-i18n)      Create resource file for I18N\n" */
1183 /* "-r (-resources) Write all resources into a resource file\n" */
1184
1185     exit(1);
1186     return ERR_INTERNAL;
1187 }
1188
1189
1190 /*
1191  * Searches the current directory for a project file
1192  * Sets the cmdline->proj_file member
1193  *
1194  * Returns the total number of project files found
1195  *    
1196  */
1197 static int
1198 find_proj_file(CmdlineArgs cmdline)
1199 {
1200     DIR                 *dir= NULL;
1201     struct dirent       *dirEntry= NULL;
1202     int                 numProjectFiles = 0;
1203     StringListRec       projFiles;
1204     strlist_construct(&projFiles);
1205
1206     dir= opendir(".");
1207     if (dir == NULL)
1208     {
1209         perror(catgets(Dtb_project_catd,1,32,"Couldn't open '.'"));
1210         return -1;
1211     }
1212
1213     while ((dirEntry= readdir(dir)) != NULL)
1214     {
1215         if (util_file_name_has_extension(dirEntry->d_name, "bip"))
1216         {
1217             /* found a project file! */
1218             strlist_add_str(&projFiles, dirEntry->d_name, NULL);
1219         }
1220     }
1221
1222     numProjectFiles = strlist_get_num_strs(&projFiles);
1223     if (numProjectFiles > 0)
1224     {
1225         int     num_strings = strlist_get_num_strs(&projFiles);
1226         int     i = 0;
1227         STRING  fileName = NULL;
1228
1229         for (i = 0; i < strlist_get_num_strs(&projFiles); ++i)
1230         {
1231             fileName = strlist_get_str(&projFiles, i, NULL);
1232             if (!proj_file_has_modules(fileName, cmdline->files))
1233             {
1234                 strlist_remove_index(&projFiles, i);
1235                 --i;
1236             }
1237         }
1238     }
1239
1240     if (strlist_get_num_strs(&projFiles) == 1)
1241     {
1242         cmdline->proj_file = istr_create(strlist_get_str(&projFiles, 0, NULL));
1243     }
1244     else if (strlist_get_num_strs(&projFiles) > 1)
1245     {
1246         int     i = 0;
1247         char    *prog_name_string = util_get_program_name();
1248
1249         fprintf(stderr, catgets(Dtb_project_catd, 1, 33,
1250             "%s: Please specify project file (e.g."), prog_name_string);
1251         for (i = 0; i < strlist_get_num_strs(&projFiles); ++i)
1252         {
1253             fprintf(stderr, ", %s", strlist_get_str(&projFiles, i, NULL));
1254         }
1255         fprintf(stderr, catgets(Dtb_project_catd, 1, 34, ")\n"));
1256         if (!strlist_is_empty(cmdline->files))
1257         {
1258             fprintf(stderr,
1259                 catgets(Dtb_project_catd, 1, 35,
1260                 "%s: More than one project contains specified module(s)\n"),
1261                 prog_name_string);
1262         }
1263     }
1264
1265     closedir(dir); dir= NULL;
1266
1267     strlist_destruct(&projFiles);
1268     return numProjectFiles;
1269 }
1270
1271
1272 static BOOL
1273 proj_file_has_modules(STRING projFileName, StringList moduleFileNames)
1274 {
1275     BOOL        hasModules = FALSE;
1276     char        word[1024] = "";
1277     int         modulesFound = 0;
1278     int         wordLen = 0;
1279     File        file = NULL;
1280     int         c = 0;
1281     fpos_t      fpos;
1282     int         numFiles = strlist_get_num_strs(moduleFileNames);
1283
1284     if (numFiles < 1)
1285     {
1286         return TRUE;
1287     }
1288
1289     file = util_fopen_locked(projFileName, "r");
1290     if (file == NULL)
1291     {
1292         perror(projFileName);
1293         return FALSE;
1294     }
1295
1296     while ((c = fgetc(file)) != EOF)
1297     {
1298         if (c == ':')
1299         {
1300             fgetpos(file, &fpos);
1301             *word = 0;
1302             if (   (fgets(word, 6, file) != NULL) 
1303                 && (strncmp(word, "files", 5) == 0))
1304             {
1305                 /* :files <file-list> */
1306                 BOOL    filesDone = FALSE;
1307                 while (((c = fgetc(file)) != EOF) && (c != '(')) {}
1308                 filesDone = (c == EOF);
1309                 while (!filesDone)
1310                 {
1311                     while (((c = fgetc(file)) != EOF) && isspace(c)) {}
1312                     ungetc(c, file);
1313                     *word = 0;
1314                     wordLen = 0;
1315                     while (((c = fgetc(file)) != EOF) && (!isspace(c)))
1316                     {
1317                         if (c == ')')
1318                         {
1319                             filesDone = TRUE;
1320                             break;
1321                         }
1322                         word[wordLen++] = c;
1323                         word[wordLen] = 0;
1324                     }
1325                     if (c == EOF)
1326                     {
1327                         filesDone = TRUE;
1328                     }
1329
1330                     if (*word != 0)
1331                     {
1332                         int     i = 0;
1333                         ISTRING temp_istr = istr_create(word);
1334                         for (i = 0; i < numFiles; ++i)
1335                         {
1336                             if (istr_equal(temp_istr, 
1337                                     strlist_get_istr(moduleFileNames, i, NULL)))
1338                             {
1339                                 ++modulesFound;
1340                                 break;
1341                             }
1342                         }
1343                         istr_destroy(temp_istr);
1344                     }
1345                 }
1346             }
1347             else if (   (strncmp(word, "modul", 5) == 0)
1348                      && (fgets(word, 2, file) != NULL)
1349                      && (strncmp(word, "e", 1) == 0) )
1350             {
1351                 /* :module <module-name */
1352                 /* REMIND: we need to have this for .bix files to work! */
1353             }
1354             else
1355             {
1356                 fsetpos(file, &fpos);
1357             }
1358         } /* c == ':' */
1359     } /* while c != EOF */
1360
1361     util_fclose(file);
1362     hasModules = (modulesFound >= numFiles);
1363
1364     return hasModules;
1365 }
1366
1367
1368 static BOOL
1369 write_required(ABObj tree)
1370 {
1371     BOOL        writeSomething= FALSE;
1372
1373     if (obj_get_write_me(tree))
1374     {
1375         writeSomething= TRUE;
1376     }
1377     else
1378     {
1379         AB_TRAVERSAL    trav;
1380         ABObj           module= NULL;
1381
1382         for(trav_open(&trav, tree, AB_TRAV_MODULES);
1383             (module= trav_next(&trav)) != NULL; )
1384         {
1385             if (obj_get_write_me(module))
1386             {
1387                 writeSomething= TRUE;
1388                 break;
1389             }
1390         }
1391         trav_close(&trav);
1392     }
1393
1394     return writeSomething;
1395 }
1396
1397
1398 /*
1399  * Initializes everything in abmf.
1400  */
1401 static int
1402 abmf_init(void)
1403 {
1404     STRING      templateFuncName = NULL;
1405
1406     abmfP_motifdefs_init();
1407     abmfP_ui_header_file_init();
1408     abmfP_args_init();
1409
1410     /*
1411      * Turn "template" library functions into printf format strings
1412      */
1413     templateFuncName = "dtb_default_dragCB";
1414     replace_string_shorter(abmfP_lib_default_dragCB->proto, 
1415                                 templateFuncName, "%s");
1416     replace_string_shorter(abmfP_lib_default_dragCB->def, 
1417                                 templateFuncName, "%s");
1418
1419     templateFuncName = "dtb_default_dropCB";
1420     replace_string_shorter(abmfP_lib_default_dropCB->proto, 
1421                                 templateFuncName, "%s");
1422     replace_string_shorter(abmfP_lib_default_dropCB->def, 
1423                                 templateFuncName, "%s");
1424
1425     return 0;
1426 }
1427
1428
1429 /*
1430  * Replaces all occurences of substr with replacestr. 
1431  * replaceStr *must* be shorter than or the same length as subStr
1432  */
1433 static int
1434 replace_string_shorter(STRING buf, STRING subStr, STRING replaceStr)
1435 {
1436     int         numReplaced = 0;
1437     char        *bufPtr = buf;
1438     char        *bufEnd = buf + strlen(buf);
1439     int         subStrLen = strlen(subStr);
1440     char        *subStrPtr = subStr;
1441     int         replaceStrLen = strlen(replaceStr);
1442     int         replaceDiffLen = subStrLen - replaceStrLen;
1443
1444     assert(strlen(subStr) >= (size_t)strlen(replaceStr));
1445
1446     while ((subStrPtr = strstr(bufPtr, subStr)) != NULL)
1447     {
1448         memmove(subStrPtr+replaceStrLen, 
1449                 subStrPtr+subStrLen,
1450                 ((int)(bufEnd - (subStrPtr+subStrLen))) + 1);
1451         strncpy(subStrPtr, replaceStr, replaceStrLen);  /* no NULL! */
1452         bufPtr = subStrPtr+replaceStrLen;
1453         bufEnd -= replaceDiffLen;
1454         ++numReplaced;
1455     }
1456     return numReplaced;
1457 }
1458
1459
1460 /* 
1461  *
1462  */
1463 static int
1464 examine_tree(ABObj project)
1465 {
1466     int                 returnValue = 0;
1467     AB_TRAVERSAL        moduleTrav;
1468     AB_TRAVERSAL        uiTrav;
1469     ABObj               module = NULL;
1470     ABObj               obj = NULL;
1471     ABObj               parent = NULL;
1472     StringList          proj_callbacks = NULL;
1473     ABObj               callbackScopeObj = NULL;
1474     STRING              funcName = NULL;
1475
1476     objxm_obj_configure(project, OBJXM_CONFIG_CODEGEN, TRUE);
1477
1478     for (trav_open(&moduleTrav, project, AB_TRAV_MODULES);
1479         (module = trav_next(&moduleTrav)) != NULL; )
1480     {
1481         if (!mfobj_has_flags(module, CGenFlagIsReferenced))
1482         {
1483             continue;
1484         }
1485
1486 #ifdef DEBUG
1487         if (debugging())
1488         {
1489             char        name[256];
1490             util_dprintf(1, "Configuring %s\n", 
1491                 obj_get_safe_name(module, name, 256));
1492         }
1493 #endif /* DEBUG */
1494         objxm_tree_configure(module, OBJXM_CONFIG_CODEGEN);
1495         dup_all_menu_refs(module);      /* this can create new objs */
1496
1497         for (trav_open(&uiTrav, module, 
1498                 AB_TRAV_UI | AB_TRAV_MOD_PARENTS_FIRST | AB_TRAV_MOD_SAFE);
1499             (obj = trav_next(&uiTrav)) != NULL; )
1500         {
1501             if (   (obj_get_class_name(obj) == NULL)
1502                 && (!obj_has_flag(obj, NoCodeGenFlag)) ) 
1503             { 
1504                 #ifdef DEBUG
1505                 if (debugging())
1506                 {
1507                     if (!(obj_is_item(obj) || obj_is_menu(obj) || obj_is_message(obj)))
1508                     {
1509                     char name[256] = "";
1510                     util_dprintf(0, 
1511                         "WARNING: "
1512                       "Object has no class name (NoCodeGenFlag not set): %s\n",
1513                         obj_get_safe_name(obj, name, 256));
1514                     }
1515                 }
1516                 #endif /* DEBUG */
1517             };
1518
1519             munge_ensure_win_parent(obj);
1520             munge_liberate_menu(obj);
1521         }
1522         trav_close(&uiTrav);
1523     } /* trav modules */
1524     trav_close(&moduleTrav);
1525
1526     abmfP_prepare_tree(project);        /* creates extra data for each obj */
1527
1528     return returnValue;
1529 }
1530
1531
1532 static int
1533 munge_ensure_win_parent(ABObj win)
1534 {
1535     ABObj       root_window = abmfP_get_root_window(obj_get_project(win));
1536     if (!obj_is_window(win))
1537     {
1538         return 0;
1539     }
1540
1541     if ((obj_get_win_parent(win) == NULL) && (win != root_window))
1542     {
1543         obj_set_win_parent(win, root_window);
1544     }
1545
1546     return 0;
1547 }
1548
1549
1550 static int
1551 munge_liberate_menu(ABObj menu)
1552 {
1553     if (!obj_is_menu(menu))
1554     {
1555         return -1;
1556     }
1557     {
1558         ABObj           compRoot = obj_get_root(menu);
1559         AB_OBJECT_TYPE  compType = AB_TYPE_UNDEF;
1560         
1561         if (compRoot != NULL)
1562         {
1563             compType = obj_get_type(compRoot);
1564         }
1565         if (   (compRoot != menu)
1566             && (   (compType == AB_TYPE_ITEM)
1567                 || (compType == AB_TYPE_BUTTON)) )
1568         {
1569             menu->part_of = NULL;
1570         }
1571     }
1572
1573     return 0;
1574 }
1575
1576
1577 static int
1578 dup_all_menu_refs(ABObj project)
1579 {
1580     AB_TRAVERSAL        moduleTrav;
1581     AB_TRAVERSAL        menuTrav;
1582     ABObj               module = NULL;
1583     ABObj               menu = NULL;
1584
1585     for (trav_open(&moduleTrav, project, AB_TRAV_MODULES);
1586         (module = trav_next(&moduleTrav)) != NULL; )
1587     {
1588         if (!obj_get_write_me(module))
1589         {
1590             continue;
1591         }
1592         for (trav_open(&menuTrav, module, AB_TRAV_MENUS);
1593             (menu = trav_next(&menuTrav)) != NULL; )
1594         {
1595             if (obj_is_ref(menu))
1596             {
1597                 abmfP_dup_menu_ref_tree(menu);
1598                 if (obj_is_popup(menu))
1599                 {
1600                    STRING title = obj_get_menu_title(obj_get_parent(menu));
1601                    if (!util_strempty(title))
1602                         objxm_create_popup_menu_title(menu, OBJXM_CONFIG_CODEGEN,
1603                                 title);
1604                 }
1605             }
1606         }
1607         trav_close(&menuTrav);
1608     }
1609     trav_close(&moduleTrav);
1610
1611     return 0;
1612 }
1613
1614
1615 static int
1616 abmfP_dup_menu_ref_tree(ABObj obj)
1617 {
1618     int         rc = 0;         /* return code */
1619     int                 return_value = 0;
1620     ABObj       refObj = NULL;
1621     AB_TRAVERSAL        trav;
1622
1623     if (!obj_is_menu_ref(obj))
1624     {
1625         return 0;
1626     }
1627     rc = abmfP_do_dup_menu_ref_tree(obj);
1628     if (rc < 0)
1629     {
1630         return rc;
1631     }
1632
1633     /*
1634      * We can't handle multi-layered references, so we are going to collapse
1635      * any reference lists to only reference the final (actual) object.
1636      */
1637     for (trav_open(&trav, obj, AB_TRAV_UI);
1638         (obj = trav_next(&trav)) != NULL; )
1639     {
1640         refObj = obj_get_actual_obj(obj);
1641         if (refObj != NULL)
1642         {
1643             while (obj_is_ref(refObj))
1644             {
1645                 refObj = obj_get_actual_obj(refObj);
1646             }
1647             obj_cvt_to_ref(obj, refObj);
1648         }
1649     }
1650     trav_close(&trav);
1651     return return_value;
1652 }
1653
1654
1655 static int
1656 abmfP_do_dup_menu_ref_tree(ABObj obj)
1657 {
1658     int         return_value = 0;
1659     int         rc = 0;
1660     ABObj       actualMenu = NULL;
1661     if (!obj_is_menu_ref(obj))
1662     {
1663         return 0;
1664     }
1665     actualMenu = obj_get_actual_obj(obj);
1666     if (actualMenu == NULL)
1667     {
1668         return -1;
1669     }
1670
1671     if (obj_get_num_items(obj) != obj_get_num_items(actualMenu))
1672     {
1673         ABObj dupTree = obj_tree_create_ref(actualMenu);
1674         if (dupTree == NULL)
1675         {
1676             return_value = -1;
1677             goto epilogue;
1678         }
1679         rc = obj_move_children(obj, dupTree);
1680         if (rc < 0)
1681         {
1682             return_value = rc;
1683         }
1684         obj_destroy(dupTree);
1685
1686         {
1687             AB_TRAVERSAL        trav;
1688             ABObj               descendant = NULL;
1689
1690             for (trav_open(&trav, obj, 
1691                         AB_TRAV_UI|AB_TRAV_MOD_PARENTS_FIRST|AB_TRAV_MOD_SAFE);
1692                 (descendant = trav_next(&trav)) != NULL; )
1693             {
1694                 if (descendant == obj)
1695                 {
1696                     continue;
1697                 }
1698                 if (obj_is_menu_ref(descendant))
1699                 {
1700                     abmfP_do_dup_menu_ref_tree(descendant);
1701                 }
1702             }
1703             trav_close(&trav);
1704         }
1705     }
1706 epilogue:
1707     return return_value;
1708 }
1709
1710
1711 static int
1712 dump_tree(ABObj tree)
1713 {
1714     int         return_value = 0;
1715     int         old_verbosity = util_get_verbosity();
1716
1717     switch (old_verbosity)
1718     {
1719         case 0: /* FALLTHROUGH */
1720         case 1: util_set_verbosity(3);
1721         break;
1722
1723         case 2: util_set_verbosity(4); 
1724         break;
1725     }
1726
1727     print_tree(tree, 0);
1728
1729 epilogue:
1730     util_set_verbosity(old_verbosity);
1731     return return_value;
1732 }
1733
1734
1735 static int
1736 print_tree(ABObj root, int indent)
1737 {
1738     AB_TRAVERSAL        trav;
1739     ABObj               child = NULL;
1740     int                 numPrinted = 0;
1741     int                 travType = AB_TRAV_SALIENT_CHILDREN;
1742
1743     if (util_get_verbosity() >= 4)
1744     {
1745         travType = AB_TRAV_CHILDREN;
1746     }
1747
1748     if (   (travType == AB_TRAV_CHILDREN)
1749         || (obj_is_salient(root)) )
1750     {
1751         objxm_print_indented(root, indent, util_get_verbosity());
1752         ++numPrinted;
1753     }
1754     
1755     if (obj_is_module(root) && (!obj_get_write_me(root)))
1756     {
1757         goto epilogue;
1758     }
1759     for (trav_open(&trav, root, travType);
1760         (child = trav_next(&trav)) != NULL; )
1761     {
1762         numPrinted += print_tree(child, indent+4);
1763     }
1764     trav_close(&trav);
1765
1766     /*
1767      * Look for non-salient children that need their children printed
1768      */
1769     if (travType == AB_TRAV_SALIENT_CHILDREN)
1770     {
1771         for (trav_open(&trav, root, AB_TRAV_CHILDREN);
1772             (child = trav_next(&trav)) != NULL; )
1773         {
1774             if ((!obj_is_salient(child)) && (obj_get_root(child) != root))
1775             {
1776                 numPrinted += print_tree(child, indent);
1777             }
1778         }
1779     }
1780
1781 epilogue:
1782     return numPrinted;
1783 }
1784
1785
1786 #ifdef DEBUG
1787 static int
1788 time_traversal(ABObj root)
1789 {
1790         int             return_value = 0;
1791         AB_TRAVERSAL    trav;
1792         ABObj           obj = NULL;
1793         int             i = 0;
1794         double          startTime = 0;
1795         double          endTime = 0;
1796         double          totalTravTime = 0;
1797         double          oneTravTime = 0;
1798         int             numTravs = 1000;
1799         struct tms      timeBuf;
1800         long            ticks_per_second = sysconf(_SC_CLK_TCK);
1801         int             oldVerbosity = util_get_verbosity();
1802
1803         if (ticks_per_second <= 0)
1804         {
1805             util_dprintf(0, "Couldn't get the value of _SC_CLK_TCK!\n");
1806             return_code(ERR_INTERNAL);
1807         }
1808         
1809         util_set_verbosity(0);          /* no expensive error-checking */
1810
1811         /*
1812          *  all
1813          */
1814         util_printf("Beginning trav test\n");
1815         startTime = (times(&timeBuf) *1.0) / ticks_per_second;
1816         for (i = 0; i < numTravs; ++i)
1817         {
1818             for (trav_open(&trav, root, AB_TRAV_ALL);
1819                 (obj = trav_next(&trav)) != NULL; )
1820             {
1821             }
1822             trav_close(&trav);
1823         }
1824         endTime = (times(&timeBuf) *1.0) / ticks_per_second;
1825         util_printf("end of trav test\n");
1826         totalTravTime = (endTime - startTime);
1827         oneTravTime = totalTravTime/numTravs;
1828         util_printf("one ALL traversal time: %g\n", oneTravTime);
1829
1830         /*
1831          * salient
1832          */
1833         startTime = (times(&timeBuf) *1.0) / ticks_per_second;
1834         for (i = 0; i < numTravs; ++i)
1835         {
1836             for (trav_open(&trav, root, AB_TRAV_SALIENT);
1837                 (obj = trav_next(&trav)) != NULL; )
1838             {
1839             }
1840             trav_close(&trav);
1841         }
1842         endTime = (times(&timeBuf) *1.0) / ticks_per_second;
1843         util_printf("end of trav test\n");
1844         totalTravTime = (endTime - startTime);
1845         oneTravTime = totalTravTime/numTravs;
1846         util_printf("one SALIENT traversal time: %lg\n", oneTravTime);
1847
1848 epilogue:
1849     util_set_verbosity(oldVerbosity);
1850     return return_value;
1851 }
1852 #endif /* DEBUG */
1853
1854
1855 /*
1856  * Actually sets the tree up for code generation.
1857  */
1858 static int
1859 abmfP_prepare_tree(ABObj project)
1860 {
1861     ABObj               module = NULL;
1862     AB_TRAVERSAL        trav;
1863     StringList          proj_callbacks = NULL;
1864     ABObj               obj = NULL;
1865     AB_TRAVERSAL        allTrav;
1866     ABObj               callbackScopeObj;
1867     STRING              funcName = NULL;
1868     ABObj               parent = NULL;
1869
1870     /*
1871      * Create extra cgen data for each object
1872      */
1873     abmfP_create_obj_data_for_project(project);
1874     for(trav_open(&trav, project, AB_TRAV_MODULES);
1875         (module = trav_next(&trav)) != NULL; )
1876     {
1877         abmfP_create_obj_data_for_module(module);
1878     }
1879     trav_close(&trav);
1880
1881     proj_callbacks = mfobj_get_proj_data(project)->callbacks;
1882
1883     for (trav_open(&allTrav, project, 
1884                 AB_TRAV_ALL | AB_TRAV_MOD_PARENTS_FIRST | AB_TRAV_MOD_SAFE);
1885         (obj = trav_next(&allTrav)) != NULL; )
1886     {
1887         module = obj_get_module(obj);
1888
1889         if (obj_is_action(obj) && (obj_get_func_type(obj) == AB_FUNC_USER_DEF))
1890         {
1891             /* 
1892              * we have a user-defined callback. decide where to put it 
1893              */
1894             funcName = obj_get_func_name(obj);
1895             callbackScopeObj = abmfP_find_callback_scope(project, funcName);
1896             if (callbackScopeObj == NULL)
1897             {
1898                 /* doesn't exist */
1899                 if (obj_is_intra_module(obj) &&
1900                     !obj_is_project(obj_get_from(obj)))
1901                 {
1902                     strlist_add_str(mfobj_get_module_data(module)->callbacks, 
1903                         funcName, (void *)obj);
1904                 }
1905                 else
1906                 {
1907                     strlist_add_str(mfobj_get_proj_data(project)->callbacks,
1908                         funcName, (void *)obj);
1909
1910                     if (obj_is_project(obj_get_from(obj)))
1911                         mfobj_set_flags(obj, CGenFlagWriteDefToProjFile);
1912                 }
1913             }
1914             else
1915             {
1916                 /*
1917                  * It exists - see if it's in the right place...
1918                  */
1919                 if (   obj_is_module(callbackScopeObj) 
1920                     && (callbackScopeObj != module))
1921                 {
1922                     /*
1923                      * it's in more than one module - put it in the project
1924                      */
1925                     int         str_index = 0;
1926                     ABObj       originalConn = NULL;
1927                     StringList  moduleCallbacks = 
1928                                     mfobj_get_module_data(callbackScopeObj)
1929                                         ->callbacks;
1930
1931                     str_index = 
1932                         strlist_get_str_index(moduleCallbacks, funcName);
1933                     strlist_get_str(moduleCallbacks, str_index, 
1934                         (void **)&originalConn);
1935                     if (originalConn != NULL)
1936                     {
1937                         mfobj_set_flags(originalConn, 
1938                                 CGenFlagWriteDefToProjFile);
1939                     }
1940                     strlist_remove_index(moduleCallbacks, str_index);
1941                     strlist_add_str(
1942                         mfobj_get_proj_data(project)->callbacks,
1943                         funcName, (void *)originalConn);
1944                     mfobj_set_flags(obj, CGenFlagWriteDefToProjFile);
1945                 }
1946
1947                 /*
1948                  * Mark this as a duplicate, so we only write it once
1949                  */
1950                 mfobj_set_flags(obj, CGenFlagIsDuplicateDef);
1951             }
1952         } /* action */
1953         else if ((module != NULL) && (obj_get_write_me(module)))
1954         {
1955             /*
1956              * For some reason, menu titles are of type menu and not label
1957              */
1958             if (ObjWClassIsLabel(obj))
1959             {
1960                 obj->type = AB_TYPE_LABEL;
1961                 parent = abmfP_parent(obj);
1962                 if (   obj_is_menu(parent)
1963                     || obj_is_menu_ref(parent))
1964                 {
1965                     obj->part_of = abmfP_parent(obj);
1966                     parent->part_of = parent;
1967                 }
1968             }
1969
1970             if (   (obj_is_menu(obj) || (obj_is_menu_ref(obj)))
1971                 && (obj_get_class_name(obj) == NULL))
1972             {
1973                 obj_set_class_name(obj, istr_string(abmfP_xmMenuShell));
1974             }
1975         } /* obj_get_write_me() */
1976         if ((!(mfobj_get_proj_data(project)->has_ui_obj)) && obj_is_ui(obj))
1977         {
1978             mfobj_get_proj_data(project)->has_ui_obj = TRUE;
1979         }
1980         if (obj_get_type(obj) == AB_TYPE_TERM_PANE)
1981         {
1982             mfobj_get_proj_data(project)->has_terminal = TRUE;
1983         }
1984     } /* trav modules */
1985     trav_close(&allTrav);
1986
1987     return 0;
1988 }
1989
1990
1991 static BOOL
1992 abmfP_obj_has_no_module(ABObj obj)
1993 {
1994     return ((obj == NULL) || (obj_get_module(obj) == NULL));
1995 }
1996
1997
1998 /*
1999  * Creates data ONLY for project-specific things that are not covered
2000  * by the individual modules.
2001  *
2002  * Assumes: project is a project
2003  */
2004 static int
2005 abmfP_create_obj_data_for_project(ABObj project)
2006 {
2007     AB_TRAVERSAL        trav;
2008     ABObj               obj = NULL;
2009     CGenProjData        projData = NULL;
2010     CGenData            objData = NULL;
2011     size_t              objDataNumBytes = 0;
2012     int                 numObjects = 0;
2013     int                 objCount = 0;
2014
2015     numObjects = 0;
2016     for (trav_open_cond(&trav, project, AB_TRAV_ALL|AB_TRAV_MOD_SAFE, 
2017                                                 abmfP_obj_has_no_module);
2018         (obj = trav_next(&trav)) != NULL; )
2019     {
2020         ++numObjects;
2021     }
2022     /* don't close trav, yet */
2023
2024     /*
2025      * Create data space for all children
2026      */
2027     objDataNumBytes = numObjects * sizeof(CGenDataRec);
2028     objData= (CGenData)util_malloc(objDataNumBytes);
2029     memset(objData, 0, objDataNumBytes);
2030
2031     /*
2032      * Assign each obj it's own struct
2033      */
2034     for (trav_reset(&trav), objCount = 0; 
2035         (obj = trav_next(&trav)) != NULL; )
2036     {
2037         obj->cgen_data = (CGenData)&(objData[objCount++]);
2038         mfobj_set_flags(obj, CGenFlagDataIsObj);
2039     }
2040     trav_close(&trav);  /* close it, now */
2041     assert(objCount == numObjects);
2042
2043     /*
2044      * Create project-specific data
2045      */
2046     projData = (CGenProjData)calloc(1, sizeof(CGenProjDataRec));
2047     projData->callbacks = strlist_create();
2048     projData->children_data = objData;
2049     mfobj_set_proj_data(project, projData);
2050
2051     return 0;
2052 }
2053
2054 /*
2055  * Accepts any value (NULL, obj w/o module, ...)
2056  */
2057 static int
2058 abmfP_create_obj_data_for_module(ABObj objInModule)
2059 {
2060     ABObj               module = NULL;
2061     int                 numObjects = 0;
2062     CGenData            objData = NULL;
2063     size_t              objDataBytes = 0;
2064     ABObj               obj = NULL;
2065     AB_TRAVERSAL        trav;
2066     int                 objCount = 0;
2067
2068     if (   (objInModule == NULL) 
2069         || (mfobj_has_data(objInModule))
2070         || ((module = obj_get_module(objInModule)) == NULL)
2071        )
2072     {
2073         return 0;
2074     }
2075
2076
2077     /*
2078      * object data is an array of all data for the module.
2079      */
2080     numObjects = trav_count(module, AB_TRAV_ALL);
2081     objDataBytes = numObjects * sizeof(CGenDataRec);
2082     objData = (CGenData)util_malloc(objDataBytes);
2083     memset(objData, 0, objDataBytes);
2084     if (objData == NULL)
2085     {
2086         util_printf_err(catgets(Dtb_project_catd, 1, 36,
2087             "Could not allocate cgen data\n"));
2088         return -1;
2089     }
2090
2091     /*
2092      * Assign a structure to each object
2093      */
2094     for (trav_open(&trav, module, AB_TRAV_ALL), objCount = 0;
2095         (obj = trav_next(&trav)) != NULL; )
2096     {
2097         if (obj->cgen_data == NULL)
2098         {
2099             obj->cgen_data = (CGenData)&(objData[objCount++]);
2100             mfobj_set_flags(obj, CGenFlagDataIsObj);
2101         }
2102     }
2103     trav_close(&trav);
2104     assert(objCount <= numObjects);
2105
2106     /*
2107      * Create module-specific data
2108      */
2109     ensure_data_for_module_obj(module);
2110     mfobj_get_module_data(module)->children_data = objData;
2111
2112     return 0;
2113 }
2114
2115
2116 /*
2117  * Makes sure the module has a cgen data associated with it. Will load
2118  * the objects in the module if necessary, if loadFile is TRUE.
2119  */
2120 static int
2121 ensure_data_for_module_obj(ABObj module)
2122 {
2123     CGenModuleData      moduleData = NULL;
2124     ABObj               project = NULL;
2125     ABObj               newProject = NULL;
2126
2127     if (!obj_is_module(module))
2128     {
2129         return -1;
2130     }
2131     project = obj_get_project(module);
2132     if (module->cgen_data == NULL)
2133     {
2134         module->cgen_data = (CGenData)calloc(sizeof(CGenDataRec), 1);
2135     }
2136
2137     if (mfobj_get_module_data(module) == NULL)
2138     {
2139         moduleData = (CGenModuleData)calloc(sizeof(CGenModuleDataRec), 1);
2140         moduleData->callbacks = strlist_create();
2141         mfobj_set_module_data(module, moduleData);
2142     }
2143
2144     return 0;
2145 }
2146
2147
2148 #ifdef DEBUG
2149
2150 static int
2151 dump_callbacks(ABObj project)
2152 {
2153     ABObj               module = NULL;
2154     AB_TRAVERSAL        moduleTrav;
2155     StringList          callbacks = NULL;
2156
2157     util_dprintf(0, "\n***** CALLBACKS *****\n");
2158     util_dprintf(0, "project callbacks\n");
2159     callbacks = mfobj_get_proj_data(project)->callbacks;
2160     if (callbacks != NULL)
2161     {
2162         strlist_dump(callbacks);
2163     }
2164     for (trav_open(&moduleTrav, project, AB_TRAV_MODULES);
2165         (module = trav_next(&moduleTrav)) != NULL; )
2166     {
2167         util_dprintf(0, "module '%s' callbacks\n", util_strsafe(obj_get_name(module)));
2168         callbacks = mfobj_get_module_data(module)->callbacks;
2169         if (callbacks != NULL)
2170         {
2171             strlist_dump(callbacks);
2172         }
2173     }
2174     trav_close(&moduleTrav);
2175     util_dprintf(0,"\n");
2176     return 0;
2177 }
2178
2179 /*
2180  * Checks tree and aborts if an error is found.
2181  */
2182 static int
2183 debug_verify_tree(ABObj root)
2184 {
2185     AB_TRAVERSAL        trav;
2186     char                name[256];
2187     ABObj               obj = NULL;
2188     *name = 0;
2189
2190     if (!debugging())
2191     {
2192         return 0;
2193     }
2194
2195     util_dprintf(1, "Examining tree for defects.\n");
2196
2197     /*
2198      * Do the standard verification
2199      */
2200     if (obj_tree_verify(root) < 0)
2201     {
2202         util_dprintf(1, "Project tree is corrupt! Aborting.\n");
2203         abort();
2204     }
2205
2206     /*
2207      * Perform more code-generator specific checks
2208      */
2209     for (trav_open(&trav, root, AB_TRAV_ALL);
2210         (obj = trav_next(&trav)) != NULL; )
2211     {
2212         if (obj_is_ui(obj))
2213         {
2214             if (   (obj_get_write_me(obj_get_module(obj)))
2215                 && (obj_get_name(obj) == NULL) )
2216             {
2217                 util_dprintf(1, "Object has no name: %s\n",
2218                         obj_get_safe_name(obj, name, 256));
2219                 abort();
2220             }
2221         }
2222     }
2223     trav_close(&trav);
2224
2225     return 0;
2226 }
2227
2228 #endif /* DEBUG */
2229
2230
2231 #ifdef DEBUG    /* performance testing */
2232 static int      
2233 get_cur_time(double *realTimeOut, double *cpuTimeOut)
2234 {
2235         long            ticks_per_second = sysconf(_SC_CLK_TCK);
2236     struct tms  timeInfo;
2237     double      realTime = times(&timeInfo);
2238     double      cpuTime = timeInfo.tms_utime + timeInfo.tms_stime
2239                         + timeInfo.tms_cutime + timeInfo.tms_cstime;
2240     *realTimeOut  = realTime / CLK_TCK;
2241     *cpuTimeOut = cpuTime / CLK_TCK;
2242
2243     return 0;
2244 }
2245
2246 #endif /* DEBUG */
2247