623 lines
17 KiB
C
623 lines
17 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
/*
|
|
* $XConsortium: ab_bil.c /main/3 1995/11/06 17:12:37 rswiston $
|
|
*
|
|
* @(#)ab_bil.c 1.85 22 May 1995
|
|
*
|
|
* RESTRICTED CONFIDENTIAL INFORMATION:
|
|
*
|
|
* The information in this document is subject to special
|
|
* restrictions in a confidential disclosure agreement between
|
|
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
|
|
* document outside HP, IBM, Sun, USL, SCO, or Univel without
|
|
* Sun's specific written approval. This document and all copies
|
|
* and derivative works thereof must be returned or destroyed at
|
|
* Sun's request.
|
|
*
|
|
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* File: ab_bil.c - functions dealing with bil files
|
|
*/
|
|
#include <stdio.h>
|
|
#include <sys/times.h>
|
|
#include <time.h>
|
|
#include <sys/param.h> /* MAXPATHLEN */
|
|
#include <errno.h>
|
|
#include "dtb_utils.h"
|
|
#include <ab_private/obj.h>
|
|
#include <ab_private/trav.h>
|
|
#include <ab_private/bil.h>
|
|
#include <ab_private/objxm.h>
|
|
#include <ab_private/abobj.h>
|
|
#include <ab_private/abobj_set.h>
|
|
#include <ab_private/brws.h>
|
|
#include <ab_private/proj.h>
|
|
#include <ab_private/conn.h>
|
|
#include <ab_private/ui_util.h>
|
|
#include <ab_private/ab.h>
|
|
#include <ab_private/ab_bil.h>
|
|
#include "../libABobj/objP.h"
|
|
#include "palette_ui.h"
|
|
|
|
/* REMIND: #ifdef DEBUG */
|
|
typedef struct
|
|
{
|
|
double startSeconds;
|
|
double endSeconds;
|
|
double elapsedSeconds;
|
|
} ABTimedIntervalRec, *ABTimedInterval;
|
|
|
|
typedef struct
|
|
{
|
|
ABTimedIntervalRec realTime;
|
|
ABTimedIntervalRec CPUTime;
|
|
} ABProfiledIntervalRec, *ABProfiledInterval;
|
|
|
|
static int get_cur_times(double *realTimeOut, double *cpuTimeOut);
|
|
static int get_start_times(ABProfiledInterval);
|
|
static int get_end_times(ABProfiledInterval);
|
|
static int calc_elapsed_times(ABProfiledInterval);
|
|
static int print_load_stats(
|
|
ABObj tree,
|
|
ABProfiledInterval totalTime,
|
|
ABProfiledInterval loadTime,
|
|
ABProfiledInterval configTime
|
|
);
|
|
|
|
extern char Buf[MAXPATHLEN]; /* Work buffer */
|
|
|
|
/*
|
|
* Loads in a new project, replacing the current project.
|
|
* Chdirs to the directory where the project is. Called
|
|
* from the 'File->Open Project' and 'Project->Open'
|
|
* (Project Organizer) menus, and the cmd-line (dtbuilder.c).
|
|
*/
|
|
int
|
|
ab_load_bil_file(
|
|
STRING fileName,
|
|
FILE *inFile,
|
|
BOOL BufferDrop
|
|
)
|
|
{
|
|
int rc = 0; /* return code */
|
|
ABObj newProject = NULL;
|
|
ABObj mod = NULL;
|
|
STRING init_msg = NULL;
|
|
STRING modfile = NULL;
|
|
int pLinesRead = 0;
|
|
ABProfiledIntervalRec totalTime;
|
|
ABProfiledIntervalRec loadTime;
|
|
ABProfiledIntervalRec configTime;
|
|
XmString xm_buf = (XmString) NULL;
|
|
int NoWrite = 0;
|
|
int len = 0;
|
|
STRING errmsg = NULL;
|
|
BOOL read_OK, write_OK;
|
|
AB_TRAVERSAL trav;
|
|
|
|
get_start_times(&totalTime);
|
|
|
|
get_start_times(&loadTime);
|
|
rc = bil_load_file_and_resolve_all(fileName, inFile, &newProject);
|
|
if (newProject == NULL)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
/* If BufferDrop is TRUE, then that means that
|
|
* ab_load_bil_file() is being called due to
|
|
* a buffer drop (i.e. a .bix dtmail attachment).
|
|
* In that case, we don't need to check whether
|
|
* the modules are read-only, since there aren't
|
|
* .bil files associated with the modules.
|
|
*/
|
|
if (!BufferDrop)
|
|
{
|
|
/* Check if any of the modules are read-only. If so, post
|
|
* a message.
|
|
*/
|
|
for (trav_open(&trav, newProject, AB_TRAV_MODULES);
|
|
(mod = trav_next(&trav)) != NULL; )
|
|
{
|
|
if (!obj_is_defined(mod))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
modfile = obj_get_file(mod);
|
|
abio_access_file(modfile, &read_OK, &write_OK);
|
|
if (!write_OK && !util_strempty(modfile))
|
|
{
|
|
obj_set_read_only(mod, TRUE);
|
|
|
|
len = len + strlen(modfile) + 2;
|
|
/*
|
|
** Is this the first read-only file we've encountered?
|
|
** If so, initialize the notice message.
|
|
*/
|
|
if (NoWrite == 0)
|
|
{
|
|
/* The first thing in the message is
|
|
* some general text.
|
|
*/
|
|
init_msg = catgets(Dtb_project_catd, 100, 38, "The following modules are read-only.\nIf you edit these modules, you\nwill not be able to save your edits.");
|
|
|
|
/* If we have an old buffer lying around, free it */
|
|
if (errmsg != (STRING) NULL)
|
|
util_free(errmsg);
|
|
|
|
/* Now create a new buffer of the proper size */
|
|
len = strlen(init_msg) + strlen(modfile) + 3;
|
|
errmsg = (STRING) util_malloc(len);
|
|
|
|
/*
|
|
** Put the general text plus name of the first
|
|
** read-only file into the notice message.
|
|
*/
|
|
sprintf(errmsg, "%s\n\n%s", init_msg, modfile);
|
|
}
|
|
else
|
|
{
|
|
errmsg = (STRING) realloc(errmsg, len);
|
|
strcat(errmsg, "\n");
|
|
strcat(errmsg, modfile);
|
|
}
|
|
NoWrite++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!util_strempty(errmsg))
|
|
{
|
|
util_set_help_data(catgets(Dtb_project_catd, 100, 92,
|
|
"Any changes made to a read-only module cannot be saved,\nunless you save the module to a different file name."),
|
|
NULL, NULL);
|
|
util_puts(errmsg);
|
|
util_free(errmsg);
|
|
}
|
|
get_end_times(&loadTime);
|
|
|
|
if( obj_get_num_children(newProject) == 0 )
|
|
{
|
|
sprintf(Buf, catgets(Dtb_project_catd, 100, 23,
|
|
"%s: Empty project file loaded."), fileName);
|
|
xm_buf = XmStringCreateLocalized(Buf);
|
|
dtb_palette_empty_proj_msg_initialize(&dtb_palette_empty_proj_msg);
|
|
(void)dtb_show_modal_message(dtb_get_toplevel_widget(),
|
|
&dtb_palette_empty_proj_msg, xm_buf, NULL, NULL);
|
|
XmStringFree(xm_buf);
|
|
}
|
|
|
|
if (util_get_verbosity() >= 5)
|
|
obj_tree_print(newProject);
|
|
|
|
/* Destroy the old project, first. Then initialize
|
|
* the project to be the one just created. This
|
|
* also sets the current module to NULL, since a
|
|
* module has not been shown yet.
|
|
*/
|
|
proj_destroy_project(proj_get_project());
|
|
proj_set_project(newProject);
|
|
|
|
/* REMIND: Check this out later */
|
|
|
|
get_start_times(&configTime);
|
|
objxm_tree_configure(newProject, OBJXM_CONFIG_BUILD);
|
|
get_end_times(&configTime);
|
|
|
|
abobj_update_proj_name(newProject);
|
|
abobj_update_palette_title(newProject);
|
|
obj_tree_update_clients(newProject);
|
|
|
|
#ifdef DEBUG
|
|
get_end_times(&totalTime);
|
|
print_load_stats(newProject, &totalTime, &loadTime, &configTime);
|
|
#endif /* DEBUG */
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int
|
|
ab_import_bil_file(
|
|
STRING fileName,
|
|
FILE *inFile,
|
|
BOOL ImportByCopy
|
|
)
|
|
{
|
|
int return_value = 0;
|
|
AB_TRAVERSAL trav;
|
|
ABObj project = proj_get_project();
|
|
ABObj module = NULL;
|
|
ABObjList loaded_comp_objs = NULL;
|
|
ABObj loaded_module = NULL;
|
|
STRING file = NULL;
|
|
|
|
/*
|
|
* XmConfigured flags is not getting set properly. If it's already
|
|
* here, we'll assume it's configured.
|
|
*/
|
|
for (trav_open(&trav, project, AB_TRAV_MODULES);
|
|
(module= trav_next(&trav)) != NULL; )
|
|
{
|
|
obj_set_flag(module, XmConfiguredFlag);
|
|
}
|
|
trav_close(&trav);
|
|
|
|
if (bil_load_file(fileName, inFile, project, &loaded_comp_objs)
|
|
== NULL)
|
|
{
|
|
return_value = -1;
|
|
goto epilogue;
|
|
}
|
|
|
|
/* loaded_module will point to the module that was
|
|
* created.
|
|
*/
|
|
loaded_module = NULL;
|
|
if (objlist_get_num_objs(loaded_comp_objs) >= 1)
|
|
{
|
|
loaded_module = objlist_get_obj(loaded_comp_objs, 0, NULL);
|
|
}
|
|
|
|
if (loaded_module != NULL)
|
|
{
|
|
if (ImportByCopy)
|
|
{
|
|
obj_set_file(loaded_module, (String) NULL);
|
|
}
|
|
else /* Import by reference */
|
|
{
|
|
/* Convert the imported module's file field to a
|
|
* path that is relative to the directory in which
|
|
* the project is stored.
|
|
*/
|
|
file = proj_cvt_mod_file_to_rel_path(fileName,
|
|
obj_get_file(project));
|
|
obj_set_file(loaded_module, file);
|
|
util_free(file);
|
|
}
|
|
|
|
/*
|
|
* configure anything that's not marked as configured
|
|
*/
|
|
abobj_show_tree(loaded_module, TRUE);
|
|
obj_tree_update_clients(loaded_module);
|
|
proj_set_cur_module(loaded_module);
|
|
}
|
|
|
|
epilogue:
|
|
objlist_destroy(loaded_comp_objs);
|
|
return return_value;
|
|
}
|
|
|
|
|
|
static int
|
|
get_start_times(ABProfiledInterval interval)
|
|
{
|
|
return get_cur_times(&(interval->realTime.startSeconds),
|
|
&(interval->CPUTime.startSeconds));
|
|
}
|
|
|
|
|
|
static int
|
|
get_end_times(ABProfiledInterval interval)
|
|
{
|
|
return get_cur_times(&(interval->realTime.endSeconds),
|
|
&(interval->CPUTime.endSeconds));
|
|
}
|
|
|
|
|
|
static int
|
|
calc_elapsed_times(ABProfiledInterval interval)
|
|
{
|
|
interval->realTime.elapsedSeconds =
|
|
interval->realTime.endSeconds - interval->realTime.startSeconds;
|
|
interval->CPUTime.elapsedSeconds =
|
|
interval->CPUTime.endSeconds - interval->CPUTime.startSeconds;
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* REMIND: #ifdef DEBUG */
|
|
static int
|
|
print_load_stats(
|
|
ABObj tree,
|
|
ABProfiledInterval totalTime,
|
|
ABProfiledInterval loadTime,
|
|
ABProfiledInterval configTime
|
|
)
|
|
{
|
|
ABProfiledIntervalRec otherTimeRec;
|
|
ABProfiledInterval otherTime = &otherTimeRec;
|
|
|
|
/*
|
|
* Print out statistics about load
|
|
*/
|
|
calc_elapsed_times(totalTime);
|
|
calc_elapsed_times(loadTime);
|
|
calc_elapsed_times(configTime);
|
|
otherTime->realTime.elapsedSeconds =
|
|
(totalTime->realTime.elapsedSeconds
|
|
- loadTime->realTime.elapsedSeconds
|
|
- configTime->realTime.elapsedSeconds);
|
|
otherTime->CPUTime.elapsedSeconds =
|
|
(totalTime->CPUTime.elapsedSeconds
|
|
- loadTime->CPUTime.elapsedSeconds
|
|
- configTime->CPUTime.elapsedSeconds);
|
|
|
|
fprintf(stderr, "\nLoad Times (Real/CPU) seconds:\n");
|
|
fprintf(stderr, " Total: (%lg/%lg)\n",
|
|
totalTime->realTime.elapsedSeconds,
|
|
totalTime->CPUTime.elapsedSeconds);
|
|
fprintf(stderr, " Actual load: (%lg/%lg)\n",
|
|
loadTime->realTime.elapsedSeconds,
|
|
loadTime->CPUTime.elapsedSeconds);
|
|
fprintf(stderr, " Config: (%lg/%lg)\n",
|
|
configTime->realTime.elapsedSeconds,
|
|
configTime->CPUTime.elapsedSeconds);
|
|
fprintf(stderr, " Other: (%lg/%lg)\n",
|
|
otherTime->realTime.elapsedSeconds,
|
|
otherTime->CPUTime.elapsedSeconds);
|
|
|
|
fprintf(stderr, "Number of objects loaded - salient:%d total:%d\n",
|
|
trav_count(tree, AB_TRAV_SALIENT),
|
|
trav_count(tree, AB_TRAV_ALL));
|
|
|
|
return 0;
|
|
}
|
|
/* REMIND: #endif DEBUG */
|
|
|
|
|
|
static int
|
|
get_cur_times(double *realTimeOut, double *cpuTimeOut)
|
|
{
|
|
static BOOL initialized = FALSE;
|
|
static long ticks_per_second = 1;
|
|
struct tms timeInfo;
|
|
double realTime;
|
|
double cpuTime;
|
|
if (!initialized)
|
|
{
|
|
initialized = TRUE;
|
|
ticks_per_second = sysconf(_SC_CLK_TCK);
|
|
}
|
|
|
|
realTime = times(&timeInfo);
|
|
cpuTime = timeInfo.tms_utime + timeInfo.tms_stime
|
|
+ timeInfo.tms_cutime + timeInfo.tms_cstime;
|
|
*realTimeOut = realTime / ticks_per_second;
|
|
*cpuTimeOut = cpuTime / ticks_per_second;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* Called by the 'File->Open Project' callback and the
|
|
* 'Project->Open' callback. NOT called when a project
|
|
* is loaded from the command-line.
|
|
*/
|
|
int
|
|
ab_check_and_open_bip(
|
|
STRING fileName
|
|
)
|
|
{
|
|
DTB_MODAL_ANSWER answer = DTB_ANSWER_NONE;
|
|
BOOL read_OK, write_OK;
|
|
int iRet = 0;
|
|
XmString xm_buf = (XmString) NULL;
|
|
DtbObjectHelpData help_data = NULL;
|
|
|
|
abio_access_file(fileName, &read_OK, &write_OK);
|
|
if (read_OK)
|
|
{
|
|
if (write_OK)
|
|
{
|
|
iRet = ab_load_project(fileName, NULL, FALSE);
|
|
}
|
|
else /* Read-only file */
|
|
{
|
|
/* You can read it but you can't write to it. */
|
|
sprintf(Buf, catgets(Dtb_project_catd, 100, 17,
|
|
"The file %s is a read-only file.\nYou may open the project\nor cancel the operation."), fileName);
|
|
xm_buf = XmStringCreateLocalized(Buf);
|
|
dtb_palette_open_ro_proj_msg_initialize(
|
|
&dtb_palette_open_ro_proj_msg);
|
|
|
|
help_data = (DtbObjectHelpData) util_malloc(sizeof(DtbObjectHelpDataRec));
|
|
help_data->help_text = catgets(Dtb_project_catd, 100, 90,
|
|
"Opening a read-only project means that any changes that\naffect the project (.bip) file, such as creation of a\nnew module or creation of a cross-module connection,\ncannot be saved, unless you save the project to a\ndifferent file name. You have the option of continuing\nwith the open operation or cancelling it.");
|
|
help_data->help_volume = "";
|
|
help_data->help_locationID = "";
|
|
|
|
answer = dtb_show_modal_message(dtb_get_toplevel_widget(),
|
|
&dtb_palette_open_ro_proj_msg, xm_buf, help_data, NULL);
|
|
|
|
util_free(help_data);
|
|
XmStringFree(xm_buf);
|
|
switch (answer)
|
|
{
|
|
case DTB_ANSWER_ACTION1:
|
|
iRet = ab_load_project(fileName, NULL, FALSE);
|
|
break;
|
|
|
|
case DTB_ANSWER_CANCEL:
|
|
break;
|
|
|
|
case DTB_ANSWER_HELP:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sprintf(Buf, catgets(Dtb_project_catd, 100, 20,
|
|
"%s does not have read permission."), fileName);
|
|
xm_buf = XmStringCreateLocalized(Buf);
|
|
dtb_palette_error_msg_initialize(&dtb_palette_error_msg);
|
|
(void)dtb_show_modal_message(dtb_get_toplevel_widget(),
|
|
&dtb_palette_error_msg, xm_buf, NULL, NULL);
|
|
XmStringFree(xm_buf);
|
|
iRet = -1;
|
|
}
|
|
|
|
return (iRet);
|
|
}
|
|
|
|
int
|
|
ab_load_project(
|
|
STRING fileName,
|
|
FILE *inFile,
|
|
BOOL BufferDrop
|
|
)
|
|
{
|
|
int ret = 0;
|
|
|
|
ab_set_busy_cursor(TRUE);
|
|
ui_sync_display_of_widget(AB_toplevel);
|
|
|
|
if ((ret = ab_load_bil_file(fileName, inFile, BufferDrop)) != -1)
|
|
{
|
|
proj_show_proj_dir();
|
|
objxm_tree_configure(proj_get_project(), OBJXM_CONFIG_BUILD);
|
|
/* Popup the Project Organizer */
|
|
proj_show_dialog();
|
|
}
|
|
|
|
ab_set_busy_cursor(FALSE);
|
|
|
|
return (ret);
|
|
}
|
|
|
|
/* Calls ab_import_bil_file(). Called by the File->Import->Module
|
|
* callback and the Module->Import callback. NOT called when
|
|
* a project is loaded from the command-line.
|
|
*/
|
|
int
|
|
ab_check_and_import_bil(
|
|
STRING fileName,
|
|
BOOL ImportByCopy
|
|
)
|
|
{
|
|
BOOL read_OK, write_OK;
|
|
DTB_MODAL_ANSWER answer = DTB_ANSWER_NONE;
|
|
ABObj project = proj_get_project();
|
|
int iRet = 0;
|
|
XmString xm_buf = (XmString) NULL;
|
|
DtbObjectHelpData help_data = NULL;
|
|
|
|
abio_access_file(fileName, &read_OK, &write_OK);
|
|
if (read_OK)
|
|
{
|
|
if (ImportByCopy)
|
|
{
|
|
iRet = ab_import_module(fileName, NULL, TRUE);
|
|
}
|
|
else /* Importing by Reference. Have to check permissions. */
|
|
{
|
|
if (write_OK)
|
|
{
|
|
/* The file is readable and writable, can be opened,
|
|
* and is a valid module file, so import it.
|
|
*/
|
|
iRet = ab_import_module(fileName, NULL, FALSE);
|
|
}
|
|
else
|
|
{
|
|
/* You can read it but you can't write to it. */
|
|
sprintf(Buf, catgets(Dtb_project_catd, 100, 21,
|
|
"The file %s is a read-only file.\n\
|
|
You may import the module or cancel\n\
|
|
the operation."), fileName);
|
|
xm_buf = XmStringCreateLocalized(Buf);
|
|
dtb_palette_import_ro_msg_initialize(
|
|
&dtb_palette_import_ro_msg);
|
|
|
|
help_data = (DtbObjectHelpData) util_malloc(sizeof(DtbObjectHelpDataRec));
|
|
help_data->help_text = catgets(Dtb_project_catd, 100, 91,
|
|
"Importing a read-only module means that any changes\nthat affect the module cannot be saved, unless you\nsave the module to a different file name. You have\nthe option of continuing with the import operation\nor cancelling it.");
|
|
|
|
help_data->help_volume = "";
|
|
help_data->help_locationID = "";
|
|
|
|
answer = dtb_show_modal_message(dtb_get_toplevel_widget(),
|
|
&dtb_palette_import_ro_msg, xm_buf, help_data, NULL);
|
|
|
|
util_free(help_data);
|
|
XmStringFree(xm_buf);
|
|
switch (answer)
|
|
{
|
|
case DTB_ANSWER_ACTION1:
|
|
iRet = ab_import_module(fileName, NULL, ImportByCopy);
|
|
break;
|
|
|
|
case DTB_ANSWER_CANCEL:
|
|
case DTB_ANSWER_HELP:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sprintf(Buf, catgets(Dtb_project_catd, 100, 9,
|
|
"%s does not have read permission."), fileName);
|
|
xm_buf = XmStringCreateLocalized(Buf);
|
|
dtb_palette_error_msg_initialize(&dtb_palette_error_msg);
|
|
(void)dtb_show_modal_message(dtb_get_toplevel_widget(),
|
|
&dtb_palette_error_msg, xm_buf, NULL, NULL);
|
|
XmStringFree(xm_buf);
|
|
iRet = -1;
|
|
}
|
|
|
|
return (iRet);
|
|
}
|
|
|
|
int
|
|
ab_import_module(
|
|
STRING fileName,
|
|
FILE *inFile,
|
|
BOOL ImportByCopy
|
|
)
|
|
{
|
|
int iRet = 0;
|
|
|
|
ab_set_busy_cursor(TRUE);
|
|
ui_sync_display_of_widget(AB_toplevel);
|
|
|
|
iRet = ab_import_bil_file(fileName, inFile, ImportByCopy);
|
|
if (iRet != -1)
|
|
{
|
|
abobj_set_save_needed(proj_get_project(), TRUE);
|
|
}
|
|
ab_set_busy_cursor(FALSE);
|
|
|
|
return (iRet);
|
|
}
|